swap.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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(__FreeBSD__)
  19. #include <sys/endian.h>
  20. #endif
  21. #include <cstring>
  22. #include "common/common_types.h"
  23. // GCC 4.6+
  24. #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
  25. #if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) && !defined(COMMON_LITTLE_ENDIAN)
  26. #define COMMON_LITTLE_ENDIAN 1
  27. #elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) && !defined(COMMON_BIG_ENDIAN)
  28. #define COMMON_BIG_ENDIAN 1
  29. #endif
  30. // LLVM/clang
  31. #elif __clang__
  32. #if __LITTLE_ENDIAN__ && !defined(COMMON_LITTLE_ENDIAN)
  33. #define COMMON_LITTLE_ENDIAN 1
  34. #elif __BIG_ENDIAN__ && !defined(COMMON_BIG_ENDIAN)
  35. #define COMMON_BIG_ENDIAN 1
  36. #endif
  37. // MSVC
  38. #elif defined(_MSC_VER) && !defined(COMMON_BIG_ENDIAN) && !defined(COMMON_LITTLE_ENDIAN)
  39. #define COMMON_LITTLE_ENDIAN 1
  40. #endif
  41. // Worst case, default to little endian.
  42. #if !COMMON_BIG_ENDIAN && !COMMON_LITTLE_ENDIAN
  43. #define COMMON_LITTLE_ENDIAN 1
  44. #endif
  45. namespace Common {
  46. #ifdef _MSC_VER
  47. inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
  48. inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
  49. inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
  50. #elif _M_ARM
  51. inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
  52. inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
  53. inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
  54. #elif __linux__
  55. inline u16 swap16(u16 _data) {return bswap_16(_data);}
  56. inline u32 swap32(u32 _data) {return bswap_32(_data);}
  57. inline u64 swap64(u64 _data) {return bswap_64(_data);}
  58. #elif __APPLE__
  59. inline __attribute__((always_inline)) u16 swap16(u16 _data)
  60. {return (_data >> 8) | (_data << 8);}
  61. inline __attribute__((always_inline)) u32 swap32(u32 _data)
  62. {return __builtin_bswap32(_data);}
  63. inline __attribute__((always_inline)) u64 swap64(u64 _data)
  64. {return __builtin_bswap64(_data);}
  65. #elif __FreeBSD__
  66. inline u16 swap16(u16 _data) {return bswap16(_data);}
  67. inline u32 swap32(u32 _data) {return bswap32(_data);}
  68. inline u64 swap64(u64 _data) {return bswap64(_data);}
  69. #else
  70. // Slow generic implementation.
  71. inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);}
  72. inline u32 swap32(u32 data) {return (swap16(data) << 16) | swap16(data >> 16);}
  73. inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 32);}
  74. #endif
  75. inline float swapf(float f) {
  76. static_assert(sizeof(u32) == sizeof(float),
  77. "float must be the same size as uint32_t.");
  78. u32 value;
  79. std::memcpy(&value, &f, sizeof(u32));
  80. value = swap32(value);
  81. std::memcpy(&f, &value, sizeof(u32));
  82. return f;
  83. }
  84. inline double swapd(double f) {
  85. static_assert(sizeof(u64) == sizeof(double),
  86. "double must be the same size as uint64_t.");
  87. u64 value;
  88. std::memcpy(&value, &f, sizeof(u64));
  89. value = swap64(value);
  90. std::memcpy(&f, &value, sizeof(u64));
  91. return f;
  92. }
  93. } // Namespace Common
  94. template <typename T, typename F>
  95. struct swap_struct_t {
  96. typedef swap_struct_t<T, F> swapped_t;
  97. protected:
  98. T value = T();
  99. static T swap(T v) {
  100. return F::swap(v);
  101. }
  102. public:
  103. T const swap() const {
  104. return swap(value);
  105. }
  106. swap_struct_t() = default;
  107. swap_struct_t(const T &v): value(swap(v)) {}
  108. template <typename S>
  109. swapped_t& operator=(const S &source) {
  110. value = swap((T)source);
  111. return *this;
  112. }
  113. operator s8() const { return (s8)swap(); }
  114. operator u8() const { return (u8)swap(); }
  115. operator s16() const { return (s16)swap(); }
  116. operator u16() const { return (u16)swap(); }
  117. operator s32() const { return (s32)swap(); }
  118. operator u32() const { return (u32)swap(); }
  119. operator s64() const { return (s64)swap(); }
  120. operator u64() const { return (u64)swap(); }
  121. operator float() const { return (float)swap(); }
  122. operator double() const { return (double)swap(); }
  123. // +v
  124. swapped_t operator +() const {
  125. return +swap();
  126. }
  127. // -v
  128. swapped_t operator -() const {
  129. return -swap();
  130. }
  131. // v / 5
  132. swapped_t operator/(const swapped_t &i) const {
  133. return swap() / i.swap();
  134. }
  135. template <typename S>
  136. swapped_t operator/(const S &i) const {
  137. return swap() / i;
  138. }
  139. // v * 5
  140. swapped_t operator*(const swapped_t &i) const {
  141. return swap() * i.swap();
  142. }
  143. template <typename S>
  144. swapped_t operator*(const S &i) const {
  145. return swap() * i;
  146. }
  147. // v + 5
  148. swapped_t operator+(const swapped_t &i) const {
  149. return swap() + i.swap();
  150. }
  151. template <typename S>
  152. swapped_t operator+(const S &i) const {
  153. return swap() + (T)i;
  154. }
  155. // v - 5
  156. swapped_t operator-(const swapped_t &i) const {
  157. return swap() - i.swap();
  158. }
  159. template <typename S>
  160. swapped_t operator-(const S &i) const {
  161. return swap() - (T)i;
  162. }
  163. // v += 5
  164. swapped_t& operator+=(const swapped_t &i) {
  165. value = swap(swap() + i.swap());
  166. return *this;
  167. }
  168. template <typename S>
  169. swapped_t& operator+=(const S &i) {
  170. value = swap(swap() + (T)i);
  171. return *this;
  172. }
  173. // v -= 5
  174. swapped_t& operator-=(const swapped_t &i) {
  175. value = swap(swap() - i.swap());
  176. return *this;
  177. }
  178. template <typename S>
  179. swapped_t& operator-=(const S &i) {
  180. value = swap(swap() - (T)i);
  181. return *this;
  182. }
  183. // ++v
  184. swapped_t& operator++() {
  185. value = swap(swap()+1);
  186. return *this;
  187. }
  188. // --v
  189. swapped_t& operator--() {
  190. value = swap(swap()-1);
  191. return *this;
  192. }
  193. // v++
  194. swapped_t operator++(int) {
  195. swapped_t old = *this;
  196. value = swap(swap()+1);
  197. return old;
  198. }
  199. // v--
  200. swapped_t operator--(int) {
  201. swapped_t old = *this;
  202. value = swap(swap()-1);
  203. return old;
  204. }
  205. // Comparaison
  206. // v == i
  207. bool operator==(const swapped_t &i) const {
  208. return swap() == i.swap();
  209. }
  210. template <typename S>
  211. bool operator==(const S &i) const {
  212. return swap() == i;
  213. }
  214. // v != i
  215. bool operator!=(const swapped_t &i) const {
  216. return swap() != i.swap();
  217. }
  218. template <typename S>
  219. bool operator!=(const S &i) const {
  220. return swap() != i;
  221. }
  222. // v > i
  223. bool operator>(const swapped_t &i) const {
  224. return swap() > i.swap();
  225. }
  226. template <typename S>
  227. bool operator>(const S &i) const {
  228. return swap() > i;
  229. }
  230. // v < i
  231. bool operator<(const swapped_t &i) const {
  232. return swap() < i.swap();
  233. }
  234. template <typename S>
  235. bool operator<(const S &i) const {
  236. return swap() < i;
  237. }
  238. // v >= i
  239. bool operator>=(const swapped_t &i) const {
  240. return swap() >= i.swap();
  241. }
  242. template <typename S>
  243. bool operator>=(const S &i) const {
  244. return swap() >= i;
  245. }
  246. // v <= i
  247. bool operator<=(const swapped_t &i) const {
  248. return swap() <= i.swap();
  249. }
  250. template <typename S>
  251. bool operator<=(const S &i) const {
  252. return swap() <= i;
  253. }
  254. // logical
  255. swapped_t operator !() const {
  256. return !swap();
  257. }
  258. // bitmath
  259. swapped_t operator ~() const {
  260. return ~swap();
  261. }
  262. swapped_t operator &(const swapped_t &b) const {
  263. return swap() & b.swap();
  264. }
  265. template <typename S>
  266. swapped_t operator &(const S &b) const {
  267. return swap() & b;
  268. }
  269. swapped_t& operator &=(const swapped_t &b) {
  270. value = swap(swap() & b.swap());
  271. return *this;
  272. }
  273. template <typename S>
  274. swapped_t& operator &=(const S b) {
  275. value = swap(swap() & b);
  276. return *this;
  277. }
  278. swapped_t operator |(const swapped_t &b) const {
  279. return swap() | b.swap();
  280. }
  281. template <typename S>
  282. swapped_t operator |(const S &b) const {
  283. return swap() | b;
  284. }
  285. swapped_t& operator |=(const swapped_t &b) {
  286. value = swap(swap() | b.swap());
  287. return *this;
  288. }
  289. template <typename S>
  290. swapped_t& operator |=(const S &b) {
  291. value = swap(swap() | b);
  292. return *this;
  293. }
  294. swapped_t operator ^(const swapped_t &b) const {
  295. return swap() ^ b.swap();
  296. }
  297. template <typename S>
  298. swapped_t operator ^(const S &b) const {
  299. return swap() ^ b;
  300. }
  301. swapped_t& operator ^=(const swapped_t &b) {
  302. value = swap(swap() ^ b.swap());
  303. return *this;
  304. }
  305. template <typename S>
  306. swapped_t& operator ^=(const S &b) {
  307. value = swap(swap() ^ b);
  308. return *this;
  309. }
  310. template <typename S>
  311. swapped_t operator <<(const S &b) const {
  312. return swap() << b;
  313. }
  314. template <typename S>
  315. swapped_t& operator <<=(const S &b) const {
  316. value = swap(swap() << b);
  317. return *this;
  318. }
  319. template <typename S>
  320. swapped_t operator >>(const S &b) const {
  321. return swap() >> b;
  322. }
  323. template <typename S>
  324. swapped_t& operator >>=(const S &b) const {
  325. value = swap(swap() >> b);
  326. return *this;
  327. }
  328. // Member
  329. /** todo **/
  330. // Arithmetics
  331. template <typename S, typename T2, typename F2>
  332. friend S operator+(const S &p, const swapped_t v);
  333. template <typename S, typename T2, typename F2>
  334. friend S operator-(const S &p, const swapped_t v);
  335. template <typename S, typename T2, typename F2>
  336. friend S operator/(const S &p, const swapped_t v);
  337. template <typename S, typename T2, typename F2>
  338. friend S operator*(const S &p, const swapped_t v);
  339. template <typename S, typename T2, typename F2>
  340. friend S operator%(const S &p, const swapped_t v);
  341. // Arithmetics + assignements
  342. template <typename S, typename T2, typename F2>
  343. friend S operator+=(const S &p, const swapped_t v);
  344. template <typename S, typename T2, typename F2>
  345. friend S operator-=(const S &p, const swapped_t v);
  346. // Bitmath
  347. template <typename S, typename T2, typename F2>
  348. friend S operator&(const S &p, const swapped_t v);
  349. // Comparison
  350. template <typename S, typename T2, typename F2>
  351. friend bool operator<(const S &p, const swapped_t v);
  352. template <typename S, typename T2, typename F2>
  353. friend bool operator>(const S &p, const swapped_t v);
  354. template <typename S, typename T2, typename F2>
  355. friend bool operator<=(const S &p, const swapped_t v);
  356. template <typename S, typename T2, typename F2>
  357. friend bool operator>=(const S &p, const swapped_t v);
  358. template <typename S, typename T2, typename F2>
  359. friend bool operator!=(const S &p, const swapped_t v);
  360. template <typename S, typename T2, typename F2>
  361. friend bool operator==(const S &p, const swapped_t v);
  362. };
  363. // Arithmetics
  364. template <typename S, typename T, typename F>
  365. S operator+(const S &i, const swap_struct_t<T, F> v) {
  366. return i + v.swap();
  367. }
  368. template <typename S, typename T, typename F>
  369. S operator-(const S &i, const swap_struct_t<T, F> v) {
  370. return i - v.swap();
  371. }
  372. template <typename S, typename T, typename F>
  373. S operator/(const S &i, const swap_struct_t<T, F> v) {
  374. return i / v.swap();
  375. }
  376. template <typename S, typename T, typename F>
  377. S operator*(const S &i, const swap_struct_t<T, F> v) {
  378. return i * v.swap();
  379. }
  380. template <typename S, typename T, typename F>
  381. S operator%(const S &i, const swap_struct_t<T, F> v) {
  382. return i % v.swap();
  383. }
  384. // Arithmetics + assignements
  385. template <typename S, typename T, typename F>
  386. S &operator+=(S &i, const swap_struct_t<T, F> v) {
  387. i += v.swap();
  388. return i;
  389. }
  390. template <typename S, typename T, typename F>
  391. S &operator-=(S &i, const swap_struct_t<T, F> v) {
  392. i -= v.swap();
  393. return i;
  394. }
  395. // Logical
  396. template <typename S, typename T, typename F>
  397. S operator&(const S &i, const swap_struct_t<T, F> v) {
  398. return i & v.swap();
  399. }
  400. template <typename S, typename T, typename F>
  401. S operator&(const swap_struct_t<T, F> v, const S &i) {
  402. return (S)(v.swap() & i);
  403. }
  404. // Comparaison
  405. template <typename S, typename T, typename F>
  406. bool operator<(const S &p, const swap_struct_t<T, F> v) {
  407. return p < v.swap();
  408. }
  409. template <typename S, typename T, typename F>
  410. bool operator>(const S &p, const swap_struct_t<T, F> v) {
  411. return p > v.swap();
  412. }
  413. template <typename S, typename T, typename F>
  414. bool operator<=(const S &p, const swap_struct_t<T, F> v) {
  415. return p <= v.swap();
  416. }
  417. template <typename S, typename T, typename F>
  418. bool operator>=(const S &p, const swap_struct_t<T, F> v) {
  419. return p >= v.swap();
  420. }
  421. template <typename S, typename T, typename F>
  422. bool operator!=(const S &p, const swap_struct_t<T, F> v) {
  423. return p != v.swap();
  424. }
  425. template <typename S, typename T, typename F>
  426. bool operator==(const S &p, const swap_struct_t<T, F> v) {
  427. return p == v.swap();
  428. }
  429. template <typename T>
  430. struct swap_64_t {
  431. static T swap(T x) {
  432. return static_cast<T>(Common::swap64(x));
  433. }
  434. };
  435. template <typename T>
  436. struct swap_32_t {
  437. static T swap(T x) {
  438. return static_cast<T>(Common::swap32(x));
  439. }
  440. };
  441. template <typename T>
  442. struct swap_16_t {
  443. static T swap(T x) {
  444. return static_cast<T>(Common::swap16(x));
  445. }
  446. };
  447. template <typename T>
  448. struct swap_float_t {
  449. static T swap(T x) {
  450. return static_cast<T>(Common::swapf(x));
  451. }
  452. };
  453. template <typename T>
  454. struct swap_double_t {
  455. static T swap(T x) {
  456. return static_cast<T>(Common::swapd(x));
  457. }
  458. };
  459. #if COMMON_LITTLE_ENDIAN
  460. typedef u32 u32_le;
  461. typedef u16 u16_le;
  462. typedef u64 u64_le;
  463. typedef s32 s32_le;
  464. typedef s16 s16_le;
  465. typedef s64 s64_le;
  466. typedef float float_le;
  467. typedef double double_le;
  468. typedef swap_struct_t<u64, swap_64_t<u64> > u64_be;
  469. typedef swap_struct_t<s64, swap_64_t<s64> > s64_be;
  470. typedef swap_struct_t<u32, swap_32_t<u32> > u32_be;
  471. typedef swap_struct_t<s32, swap_32_t<s32> > s32_be;
  472. typedef swap_struct_t<u16, swap_16_t<u16> > u16_be;
  473. typedef swap_struct_t<s16, swap_16_t<s16> > s16_be;
  474. typedef swap_struct_t<float, swap_float_t<float> > float_be;
  475. typedef swap_struct_t<double, swap_double_t<double> > double_be;
  476. #else
  477. typedef swap_struct_t<u64, swap_64_t<u64> > u64_le;
  478. typedef swap_struct_t<s64, swap_64_t<s64> > s64_le;
  479. typedef swap_struct_t<u32, swap_32_t<u32> > u32_le;
  480. typedef swap_struct_t<s32, swap_32_t<s32> > s32_le;
  481. typedef swap_struct_t<u16, swap_16_t<u16> > u16_le;
  482. typedef swap_struct_t< s16, swap_16_t<s16> > s16_le;
  483. typedef swap_struct_t<float, swap_float_t<float> > float_le;
  484. typedef swap_struct_t<double, swap_double_t<double> > double_le;
  485. typedef u32 u32_be;
  486. typedef u16 u16_be;
  487. typedef u64 u64_be;
  488. typedef s32 s32_be;
  489. typedef s16 s16_be;
  490. typedef s64 s64_be;
  491. typedef float float_be;
  492. typedef double double_be;
  493. #endif