swap.h 16 KB

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