armsupp.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
  2. Copyright (C) 1994 Advanced RISC Machines Ltd.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #include "core/arm/skyeye_common/armdefs.h"
  15. // Unsigned sum of absolute difference
  16. u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
  17. {
  18. if (left > right)
  19. return left - right;
  20. return right - left;
  21. }
  22. // Add with carry, indicates if a carry-out or signed overflow occurred.
  23. u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
  24. {
  25. u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
  26. s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
  27. u64 result = (unsigned_sum & 0xFFFFFFFF);
  28. if (carry_out_occurred)
  29. *carry_out_occurred = (result != unsigned_sum);
  30. if (overflow_occurred)
  31. *overflow_occurred = ((s64)(s32)result != signed_sum);
  32. return (u32)result;
  33. }
  34. // Compute whether an addition of A and B, giving RESULT, overflowed.
  35. bool AddOverflow(ARMword a, ARMword b, ARMword result)
  36. {
  37. return ((NEG(a) && NEG(b) && POS(result)) ||
  38. (POS(a) && POS(b) && NEG(result)));
  39. }
  40. // Compute whether a subtraction of A and B, giving RESULT, overflowed.
  41. bool SubOverflow(ARMword a, ARMword b, ARMword result)
  42. {
  43. return ((NEG(a) && POS(b) && POS(result)) ||
  44. (POS(a) && NEG(b) && NEG(result)));
  45. }
  46. // Returns true if the Q flag should be set as a result of overflow.
  47. bool ARMul_AddOverflowQ(ARMword a, ARMword b)
  48. {
  49. u32 result = a + b;
  50. if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
  51. return true;
  52. return false;
  53. }
  54. // 8-bit signed saturated addition
  55. u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
  56. {
  57. u8 result = left + right;
  58. if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
  59. if (left & 0x80)
  60. result = 0x80;
  61. else
  62. result = 0x7F;
  63. }
  64. return result;
  65. }
  66. // 8-bit signed saturated subtraction
  67. u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
  68. {
  69. u8 result = left - right;
  70. if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
  71. if (left & 0x80)
  72. result = 0x80;
  73. else
  74. result = 0x7F;
  75. }
  76. return result;
  77. }
  78. // 16-bit signed saturated addition
  79. u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
  80. {
  81. u16 result = left + right;
  82. if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
  83. if (left & 0x8000)
  84. result = 0x8000;
  85. else
  86. result = 0x7FFF;
  87. }
  88. return result;
  89. }
  90. // 16-bit signed saturated subtraction
  91. u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
  92. {
  93. u16 result = left - right;
  94. if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
  95. if (left & 0x8000)
  96. result = 0x8000;
  97. else
  98. result = 0x7FFF;
  99. }
  100. return result;
  101. }
  102. // 8-bit unsigned saturated addition
  103. u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
  104. {
  105. u8 result = left + right;
  106. if (result < left)
  107. result = 0xFF;
  108. return result;
  109. }
  110. // 16-bit unsigned saturated addition
  111. u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
  112. {
  113. u16 result = left + right;
  114. if (result < left)
  115. result = 0xFFFF;
  116. return result;
  117. }
  118. // 8-bit unsigned saturated subtraction
  119. u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
  120. {
  121. if (left <= right)
  122. return 0;
  123. return left - right;
  124. }
  125. // 16-bit unsigned saturated subtraction
  126. u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
  127. {
  128. if (left <= right)
  129. return 0;
  130. return left - right;
  131. }
  132. // Signed saturation.
  133. u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
  134. {
  135. const u32 max = (1 << shift) - 1;
  136. const s32 top = (value >> shift);
  137. if (top > 0) {
  138. *saturation_occurred = true;
  139. return max;
  140. }
  141. else if (top < -1) {
  142. *saturation_occurred = true;
  143. return ~max;
  144. }
  145. *saturation_occurred = false;
  146. return (u32)value;
  147. }
  148. // Unsigned saturation
  149. u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
  150. {
  151. const u32 max = (1 << shift) - 1;
  152. if (value < 0) {
  153. *saturation_occurred = true;
  154. return 0;
  155. } else if ((u32)value > max) {
  156. *saturation_occurred = true;
  157. return max;
  158. }
  159. *saturation_occurred = false;
  160. return (u32)value;
  161. }
  162. // Whether or not the given CPU is in big endian mode (E bit is set)
  163. bool InBigEndianMode(ARMul_State* cpu)
  164. {
  165. return (cpu->Cpsr & (1 << 9)) != 0;
  166. }