sljitNativeMIPS_64.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /*
  2. * Stack-less Just-In-Time compiler
  3. *
  4. * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification, are
  7. * permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this list of
  10. * conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form must reproduce the above copyright notice, this list
  13. * of conditions and the following disclaimer in the documentation and/or other materials
  14. * provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  19. * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  21. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  22. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  24. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /* mips 64-bit arch dependent functions. */
  27. static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
  28. {
  29. sljit_s32 shift = 32;
  30. sljit_s32 shift2;
  31. sljit_s32 inv = 0;
  32. sljit_ins ins;
  33. sljit_uw uimm;
  34. if (!(imm & ~0xffff))
  35. return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
  36. if (imm < 0 && imm >= SIMM_MIN)
  37. return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
  38. if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
  39. FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
  40. return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
  41. }
  42. /* Zero extended number. */
  43. uimm = imm;
  44. if (imm < 0) {
  45. uimm = ~imm;
  46. inv = 1;
  47. }
  48. while (!(uimm & 0xff00000000000000l)) {
  49. shift -= 8;
  50. uimm <<= 8;
  51. }
  52. if (!(uimm & 0xf000000000000000l)) {
  53. shift -= 4;
  54. uimm <<= 4;
  55. }
  56. if (!(uimm & 0xc000000000000000l)) {
  57. shift -= 2;
  58. uimm <<= 2;
  59. }
  60. if ((sljit_sw)uimm < 0) {
  61. uimm >>= 1;
  62. shift += 1;
  63. }
  64. SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
  65. if (inv)
  66. uimm = ~uimm;
  67. FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
  68. if (uimm & 0x0000ffff00000000l)
  69. FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
  70. imm &= (1l << shift) - 1;
  71. if (!(imm & ~0xffff)) {
  72. ins = (shift == 32) ? DSLL32 : DSLL;
  73. if (shift < 32)
  74. ins |= SH_IMM(shift);
  75. FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
  76. return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
  77. }
  78. /* Double shifts needs to be performed. */
  79. uimm <<= 32;
  80. shift2 = shift - 16;
  81. while (!(uimm & 0xf000000000000000l)) {
  82. shift2 -= 4;
  83. uimm <<= 4;
  84. }
  85. if (!(uimm & 0xc000000000000000l)) {
  86. shift2 -= 2;
  87. uimm <<= 2;
  88. }
  89. if (!(uimm & 0x8000000000000000l)) {
  90. shift2--;
  91. uimm <<= 1;
  92. }
  93. SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
  94. FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
  95. FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
  96. FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
  97. imm &= (1l << shift2) - 1;
  98. return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
  99. }
  100. #define SELECT_OP(a, b) \
  101. (!(op & SLJIT_I32_OP) ? a : b)
  102. #define EMIT_LOGICAL(op_imm, op_norm) \
  103. if (flags & SRC2_IMM) { \
  104. if (op & SLJIT_SET_Z) \
  105. FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
  106. if (!(flags & UNUSED_DEST)) \
  107. FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
  108. } \
  109. else { \
  110. if (op & SLJIT_SET_Z) \
  111. FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
  112. if (!(flags & UNUSED_DEST)) \
  113. FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
  114. }
  115. #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
  116. if (flags & SRC2_IMM) { \
  117. if (src2 >= 32) { \
  118. SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
  119. ins = op_dimm32; \
  120. src2 -= 32; \
  121. } \
  122. else \
  123. ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
  124. if (op & SLJIT_SET_Z) \
  125. FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
  126. if (!(flags & UNUSED_DEST)) \
  127. FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
  128. } \
  129. else { \
  130. ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
  131. if (op & SLJIT_SET_Z) \
  132. FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
  133. if (!(flags & UNUSED_DEST)) \
  134. FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
  135. }
  136. static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
  137. sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
  138. {
  139. sljit_ins ins;
  140. sljit_s32 is_overflow, is_carry, is_handled;
  141. switch (GET_OPCODE(op)) {
  142. case SLJIT_MOV:
  143. case SLJIT_MOV_P:
  144. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  145. if (dst != src2)
  146. return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
  147. return SLJIT_SUCCESS;
  148. case SLJIT_MOV_U8:
  149. case SLJIT_MOV_S8:
  150. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  151. if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  152. if (op == SLJIT_MOV_S8) {
  153. FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
  154. return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
  155. }
  156. return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
  157. }
  158. else {
  159. SLJIT_ASSERT(dst == src2);
  160. }
  161. return SLJIT_SUCCESS;
  162. case SLJIT_MOV_U16:
  163. case SLJIT_MOV_S16:
  164. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  165. if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  166. if (op == SLJIT_MOV_S16) {
  167. FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
  168. return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
  169. }
  170. return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
  171. }
  172. else {
  173. SLJIT_ASSERT(dst == src2);
  174. }
  175. return SLJIT_SUCCESS;
  176. case SLJIT_MOV_U32:
  177. SLJIT_ASSERT(!(op & SLJIT_I32_OP));
  178. FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
  179. return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
  180. case SLJIT_MOV_S32:
  181. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  182. return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
  183. case SLJIT_NOT:
  184. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  185. if (op & SLJIT_SET_Z)
  186. FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  187. if (!(flags & UNUSED_DEST))
  188. FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
  189. return SLJIT_SUCCESS;
  190. case SLJIT_CLZ:
  191. SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  192. #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  193. if (op & SLJIT_SET_Z)
  194. FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  195. if (!(flags & UNUSED_DEST))
  196. FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
  197. #else
  198. if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
  199. FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
  200. return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
  201. }
  202. /* Nearly all instructions are unmovable in the following sequence. */
  203. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
  204. /* Check zero. */
  205. FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
  206. FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
  207. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
  208. /* Loop for searching the highest bit. */
  209. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
  210. FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
  211. FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
  212. #endif
  213. return SLJIT_SUCCESS;
  214. case SLJIT_ADD:
  215. is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  216. is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  217. if (flags & SRC2_IMM) {
  218. if (is_overflow) {
  219. if (src2 >= 0)
  220. FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  221. else
  222. FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  223. }
  224. else if (op & SLJIT_SET_Z)
  225. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  226. if (is_overflow || is_carry) {
  227. if (src2 >= 0)
  228. FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  229. else {
  230. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  231. FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  232. }
  233. }
  234. /* dst may be the same as src1 or src2. */
  235. if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  236. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
  237. }
  238. else {
  239. if (is_overflow)
  240. FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  241. else if (op & SLJIT_SET_Z)
  242. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  243. if (is_overflow || is_carry)
  244. FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  245. /* dst may be the same as src1 or src2. */
  246. if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  247. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
  248. }
  249. /* a + b >= a | b (otherwise, the carry should be set to 1). */
  250. if (is_overflow || is_carry)
  251. FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  252. if (!is_overflow)
  253. return SLJIT_SUCCESS;
  254. FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  255. FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  256. FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  257. if (op & SLJIT_SET_Z)
  258. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  259. return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  260. case SLJIT_ADDC:
  261. is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  262. if (flags & SRC2_IMM) {
  263. if (is_carry) {
  264. if (src2 >= 0)
  265. FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  266. else {
  267. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  268. FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  269. }
  270. }
  271. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
  272. } else {
  273. if (is_carry)
  274. FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  275. /* dst may be the same as src1 or src2. */
  276. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
  277. }
  278. if (is_carry)
  279. FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  280. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  281. if (!is_carry)
  282. return SLJIT_SUCCESS;
  283. /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
  284. FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  285. /* Set carry flag. */
  286. return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  287. case SLJIT_SUB:
  288. if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  289. FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  290. src2 = TMP_REG2;
  291. flags &= ~SRC2_IMM;
  292. }
  293. is_handled = 0;
  294. if (flags & SRC2_IMM) {
  295. if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  296. FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  297. is_handled = 1;
  298. }
  299. else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  300. FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  301. is_handled = 1;
  302. }
  303. }
  304. if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
  305. is_handled = 1;
  306. if (flags & SRC2_IMM) {
  307. FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  308. src2 = TMP_REG2;
  309. flags &= ~SRC2_IMM;
  310. }
  311. if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  312. FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  313. }
  314. else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
  315. {
  316. FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  317. }
  318. else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  319. FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  320. }
  321. else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
  322. {
  323. FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  324. }
  325. }
  326. if (is_handled) {
  327. if (flags & SRC2_IMM) {
  328. if (op & SLJIT_SET_Z)
  329. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  330. if (!(flags & UNUSED_DEST))
  331. return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
  332. }
  333. else {
  334. if (op & SLJIT_SET_Z)
  335. FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  336. if (!(flags & UNUSED_DEST))
  337. return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
  338. }
  339. return SLJIT_SUCCESS;
  340. }
  341. is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  342. is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  343. if (flags & SRC2_IMM) {
  344. if (is_overflow) {
  345. if (src2 >= 0)
  346. FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  347. else
  348. FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  349. }
  350. else if (op & SLJIT_SET_Z)
  351. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  352. if (is_overflow || is_carry)
  353. FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  354. /* dst may be the same as src1 or src2. */
  355. if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  356. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  357. }
  358. else {
  359. if (is_overflow)
  360. FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  361. else if (op & SLJIT_SET_Z)
  362. FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  363. if (is_overflow || is_carry)
  364. FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  365. /* dst may be the same as src1 or src2. */
  366. if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  367. FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
  368. }
  369. if (!is_overflow)
  370. return SLJIT_SUCCESS;
  371. FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  372. FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  373. FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  374. if (op & SLJIT_SET_Z)
  375. FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  376. return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  377. case SLJIT_SUBC:
  378. if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  379. FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  380. src2 = TMP_REG2;
  381. flags &= ~SRC2_IMM;
  382. }
  383. is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  384. if (flags & SRC2_IMM) {
  385. if (is_carry)
  386. FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  387. /* dst may be the same as src1 or src2. */
  388. FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  389. }
  390. else {
  391. if (is_carry)
  392. FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  393. /* dst may be the same as src1 or src2. */
  394. FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
  395. }
  396. if (is_carry)
  397. FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
  398. FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  399. return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
  400. case SLJIT_MUL:
  401. SLJIT_ASSERT(!(flags & SRC2_IMM));
  402. if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
  403. #if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
  404. return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
  405. #elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  406. if (op & SLJIT_I32_OP)
  407. return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
  408. FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
  409. return push_inst(compiler, MFLO | D(dst), DR(dst));
  410. #else /* !SLJIT_MIPS_R6 && !SLJIT_MIPS_R1 */
  411. FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
  412. return push_inst(compiler, MFLO | D(dst), DR(dst));
  413. #endif /* SLJIT_MIPS_R6 */
  414. }
  415. #if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
  416. FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
  417. FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  418. #else /* !SLJIT_MIPS_R6 */
  419. FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
  420. FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
  421. FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
  422. #endif /* SLJIT_MIPS_R6 */
  423. FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
  424. return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  425. case SLJIT_AND:
  426. EMIT_LOGICAL(ANDI, AND);
  427. return SLJIT_SUCCESS;
  428. case SLJIT_OR:
  429. EMIT_LOGICAL(ORI, OR);
  430. return SLJIT_SUCCESS;
  431. case SLJIT_XOR:
  432. EMIT_LOGICAL(XORI, XOR);
  433. return SLJIT_SUCCESS;
  434. case SLJIT_SHL:
  435. EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
  436. return SLJIT_SUCCESS;
  437. case SLJIT_LSHR:
  438. EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
  439. return SLJIT_SUCCESS;
  440. case SLJIT_ASHR:
  441. EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
  442. return SLJIT_SUCCESS;
  443. }
  444. SLJIT_UNREACHABLE();
  445. return SLJIT_SUCCESS;
  446. }
  447. static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
  448. {
  449. FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
  450. FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
  451. FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
  452. FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
  453. FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
  454. return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
  455. }
  456. SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
  457. {
  458. sljit_ins *inst = (sljit_ins *)addr;
  459. inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
  460. inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
  461. inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
  462. inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
  463. inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  464. SLJIT_CACHE_FLUSH(inst, inst + 6);
  465. }
  466. SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
  467. {
  468. sljit_ins *inst = (sljit_ins *)addr;
  469. inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
  470. inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
  471. inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
  472. inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
  473. inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  474. SLJIT_CACHE_FLUSH(inst, inst + 6);
  475. }
  476. static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
  477. {
  478. sljit_s32 arg_count = 0;
  479. sljit_s32 word_arg_count = 0;
  480. sljit_s32 float_arg_count = 0;
  481. sljit_s32 types = 0;
  482. sljit_ins prev_ins = NOP;
  483. sljit_ins ins = NOP;
  484. SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
  485. arg_types >>= SLJIT_DEF_SHIFT;
  486. while (arg_types) {
  487. types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
  488. switch (arg_types & SLJIT_DEF_MASK) {
  489. case SLJIT_ARG_TYPE_F32:
  490. case SLJIT_ARG_TYPE_F64:
  491. arg_count++;
  492. float_arg_count++;
  493. break;
  494. default:
  495. arg_count++;
  496. word_arg_count++;
  497. break;
  498. }
  499. arg_types >>= SLJIT_DEF_SHIFT;
  500. }
  501. while (types) {
  502. switch (types & SLJIT_DEF_MASK) {
  503. case SLJIT_ARG_TYPE_F32:
  504. if (arg_count != float_arg_count)
  505. ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
  506. else if (arg_count == 1)
  507. ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
  508. arg_count--;
  509. float_arg_count--;
  510. break;
  511. case SLJIT_ARG_TYPE_F64:
  512. if (arg_count != float_arg_count)
  513. ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
  514. else if (arg_count == 1)
  515. ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
  516. arg_count--;
  517. float_arg_count--;
  518. break;
  519. default:
  520. if (arg_count != word_arg_count)
  521. ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
  522. else if (arg_count == 1)
  523. ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
  524. arg_count--;
  525. word_arg_count--;
  526. break;
  527. }
  528. if (ins != NOP) {
  529. if (prev_ins != NOP)
  530. FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  531. prev_ins = ins;
  532. ins = NOP;
  533. }
  534. types >>= SLJIT_DEF_SHIFT;
  535. }
  536. *ins_ptr = prev_ins;
  537. return SLJIT_SUCCESS;
  538. }
  539. SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
  540. sljit_s32 arg_types)
  541. {
  542. struct sljit_jump *jump;
  543. sljit_ins ins;
  544. CHECK_ERROR_PTR();
  545. CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
  546. jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
  547. PTR_FAIL_IF(!jump);
  548. set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
  549. type &= 0xff;
  550. PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
  551. SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  552. PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
  553. jump->flags |= IS_JAL | IS_CALL;
  554. PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  555. jump->addr = compiler->size;
  556. PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  557. return jump;
  558. }
  559. SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
  560. sljit_s32 arg_types,
  561. sljit_s32 src, sljit_sw srcw)
  562. {
  563. sljit_ins ins;
  564. CHECK_ERROR();
  565. CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
  566. SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  567. if (src & SLJIT_IMM)
  568. FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
  569. else if (FAST_IS_REG(src))
  570. FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
  571. else if (src & SLJIT_MEM) {
  572. ADJUST_LOCAL_OFFSET(src, srcw);
  573. FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
  574. }
  575. FAIL_IF(call_with_args(compiler, arg_types, &ins));
  576. /* Register input. */
  577. FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  578. return push_inst(compiler, ins, UNMOVABLE_INS);
  579. }