swap.h 16 KB

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