Fully support dynamic code modifications again.
[sljit.git] / sljit_src / sljitNativePPC_common.c
blob150c0bf9f482bb249ed60c2f1fda9fc4f6601f4e
1 /*
2 * Stack-less Just-In-Time compiler
4 * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
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.
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.
27 SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
29 return "PowerPC" SLJIT_CPUINFO;
32 /* Length of an instruction word.
33 Both for ppc-32 and ppc-64. */
34 typedef sljit_u32 sljit_ins;
36 #if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
37 || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
38 #define SLJIT_PPC_STACK_FRAME_V2 1
39 #endif
41 #ifdef _AIX
42 #include <sys/cache.h>
43 #endif
45 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
46 #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
47 #endif
49 #if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
51 static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
53 #ifdef _AIX
54 _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
55 #elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
56 # if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
57 /* Cache flush for POWER architecture. */
58 while (from < to) {
59 __asm__ volatile (
60 "clf 0, %0\n"
61 "dcs\n"
62 : : "r"(from)
64 from++;
66 __asm__ volatile ( "ics" );
67 # elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
68 # error "Cache flush is not implemented for PowerPC/POWER common mode."
69 # else
70 /* Cache flush for PowerPC architecture. */
71 while (from < to) {
72 __asm__ volatile (
73 "dcbf 0, %0\n"
74 "sync\n"
75 "icbi 0, %0\n"
76 : : "r"(from)
78 from++;
80 __asm__ volatile ( "isync" );
81 # endif
82 # ifdef __xlc__
83 # warning "This file may fail to compile if -qfuncsect is used"
84 # endif
85 #elif defined(__xlc__)
86 #error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
87 #else
88 #error "This platform requires a cache flush implementation."
89 #endif /* _AIX */
92 #endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
94 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
95 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
96 #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
97 #define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 5)
99 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
100 #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 6)
101 #else
102 #define TMP_CALL_REG TMP_REG2
103 #endif
105 #define TMP_FREG1 (0)
106 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
108 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
109 0, 3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 8, 9, 10, 31, 12
112 /* --------------------------------------------------------------------- */
113 /* Instrucion forms */
114 /* --------------------------------------------------------------------- */
115 #define D(d) (reg_map[d] << 21)
116 #define S(s) (reg_map[s] << 21)
117 #define A(a) (reg_map[a] << 16)
118 #define B(b) (reg_map[b] << 11)
119 #define C(c) (reg_map[c] << 6)
120 #define FD(fd) ((fd) << 21)
121 #define FS(fs) ((fs) << 21)
122 #define FA(fa) ((fa) << 16)
123 #define FB(fb) ((fb) << 11)
124 #define FC(fc) ((fc) << 6)
125 #define IMM(imm) ((imm) & 0xffff)
126 #define CRD(d) ((d) << 21)
128 /* Instruction bit sections.
129 OE and Rc flag (see ALT_SET_FLAGS). */
130 #define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
131 /* Rc flag (see ALT_SET_FLAGS). */
132 #define RC(flags) ((flags & ALT_SET_FLAGS) >> 10)
133 #define HI(opcode) ((opcode) << 26)
134 #define LO(opcode) ((opcode) << 1)
136 #define ADD (HI(31) | LO(266))
137 #define ADDC (HI(31) | LO(10))
138 #define ADDE (HI(31) | LO(138))
139 #define ADDI (HI(14))
140 #define ADDIC (HI(13))
141 #define ADDIS (HI(15))
142 #define ADDME (HI(31) | LO(234))
143 #define AND (HI(31) | LO(28))
144 #define ANDI (HI(28))
145 #define ANDIS (HI(29))
146 #define Bx (HI(18))
147 #define BCx (HI(16))
148 #define BCCTR (HI(19) | LO(528) | (3 << 11))
149 #define BLR (HI(19) | LO(16) | (0x14 << 21))
150 #define CNTLZD (HI(31) | LO(58))
151 #define CNTLZW (HI(31) | LO(26))
152 #define CMP (HI(31) | LO(0))
153 #define CMPI (HI(11))
154 #define CMPL (HI(31) | LO(32))
155 #define CMPLI (HI(10))
156 #define CROR (HI(19) | LO(449))
157 #define DIVD (HI(31) | LO(489))
158 #define DIVDU (HI(31) | LO(457))
159 #define DIVW (HI(31) | LO(491))
160 #define DIVWU (HI(31) | LO(459))
161 #define EXTSB (HI(31) | LO(954))
162 #define EXTSH (HI(31) | LO(922))
163 #define EXTSW (HI(31) | LO(986))
164 #define FABS (HI(63) | LO(264))
165 #define FADD (HI(63) | LO(21))
166 #define FADDS (HI(59) | LO(21))
167 #define FCFID (HI(63) | LO(846))
168 #define FCMPU (HI(63) | LO(0))
169 #define FCTIDZ (HI(63) | LO(815))
170 #define FCTIWZ (HI(63) | LO(15))
171 #define FDIV (HI(63) | LO(18))
172 #define FDIVS (HI(59) | LO(18))
173 #define FMR (HI(63) | LO(72))
174 #define FMUL (HI(63) | LO(25))
175 #define FMULS (HI(59) | LO(25))
176 #define FNEG (HI(63) | LO(40))
177 #define FRSP (HI(63) | LO(12))
178 #define FSUB (HI(63) | LO(20))
179 #define FSUBS (HI(59) | LO(20))
180 #define LD (HI(58) | 0)
181 #define LWZ (HI(32))
182 #define MFCR (HI(31) | LO(19))
183 #define MFLR (HI(31) | LO(339) | 0x80000)
184 #define MFXER (HI(31) | LO(339) | 0x10000)
185 #define MTCTR (HI(31) | LO(467) | 0x90000)
186 #define MTLR (HI(31) | LO(467) | 0x80000)
187 #define MTXER (HI(31) | LO(467) | 0x10000)
188 #define MULHD (HI(31) | LO(73))
189 #define MULHDU (HI(31) | LO(9))
190 #define MULHW (HI(31) | LO(75))
191 #define MULHWU (HI(31) | LO(11))
192 #define MULLD (HI(31) | LO(233))
193 #define MULLI (HI(7))
194 #define MULLW (HI(31) | LO(235))
195 #define NEG (HI(31) | LO(104))
196 #define NOP (HI(24))
197 #define NOR (HI(31) | LO(124))
198 #define OR (HI(31) | LO(444))
199 #define ORI (HI(24))
200 #define ORIS (HI(25))
201 #define RLDICL (HI(30))
202 #define RLWINM (HI(21))
203 #define SLD (HI(31) | LO(27))
204 #define SLW (HI(31) | LO(24))
205 #define SRAD (HI(31) | LO(794))
206 #define SRADI (HI(31) | LO(413 << 1))
207 #define SRAW (HI(31) | LO(792))
208 #define SRAWI (HI(31) | LO(824))
209 #define SRD (HI(31) | LO(539))
210 #define SRW (HI(31) | LO(536))
211 #define STD (HI(62) | 0)
212 #define STDU (HI(62) | 1)
213 #define STDUX (HI(31) | LO(181))
214 #define STFIWX (HI(31) | LO(983))
215 #define STW (HI(36))
216 #define STWU (HI(37))
217 #define STWUX (HI(31) | LO(183))
218 #define SUBF (HI(31) | LO(40))
219 #define SUBFC (HI(31) | LO(8))
220 #define SUBFE (HI(31) | LO(136))
221 #define SUBFIC (HI(8))
222 #define XOR (HI(31) | LO(316))
223 #define XORI (HI(26))
224 #define XORIS (HI(27))
226 #define SIMM_MAX (0x7fff)
227 #define SIMM_MIN (-0x8000)
228 #define UIMM_MAX (0xffff)
230 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
231 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
233 sljit_sw* ptrs;
234 if (func_ptr)
235 *func_ptr = (void*)context;
236 ptrs = (sljit_sw*)func;
237 context->addr = addr ? addr : ptrs[0];
238 context->r2 = ptrs[1];
239 context->r11 = ptrs[2];
241 #endif
243 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
245 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
246 FAIL_IF(!ptr);
247 *ptr = ins;
248 compiler->size++;
249 return SLJIT_SUCCESS;
252 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
254 sljit_sw diff;
255 sljit_uw target_addr;
256 sljit_sw extra_jump_flags;
258 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
259 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
260 return 0;
261 #else
262 if (jump->flags & SLJIT_REWRITABLE_JUMP)
263 return 0;
264 #endif
266 if (jump->flags & JUMP_ADDR)
267 target_addr = jump->u.target;
268 else {
269 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
270 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
273 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
274 if (jump->flags & IS_CALL)
275 goto keep_address;
276 #endif
278 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
280 extra_jump_flags = 0;
281 if (jump->flags & IS_COND) {
282 if (diff <= 0x7fff && diff >= -0x8000) {
283 jump->flags |= PATCH_B;
284 return 1;
286 if (target_addr <= 0xffff) {
287 jump->flags |= PATCH_B | PATCH_ABS_B;
288 return 1;
290 extra_jump_flags = REMOVE_COND;
292 diff -= sizeof(sljit_ins);
295 if (diff <= 0x01ffffff && diff >= -0x02000000) {
296 jump->flags |= PATCH_B | extra_jump_flags;
297 return 1;
300 if (target_addr <= 0x03ffffff) {
301 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
302 return 1;
305 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
306 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
307 keep_address:
308 #endif
309 if (target_addr <= 0x7fffffff) {
310 jump->flags |= PATCH_ABS32;
311 return 1;
314 if (target_addr <= 0x7fffffffffffl) {
315 jump->flags |= PATCH_ABS48;
316 return 1;
318 #endif
320 return 0;
323 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
325 struct sljit_memory_fragment *buf;
326 sljit_ins *code;
327 sljit_ins *code_ptr;
328 sljit_ins *buf_ptr;
329 sljit_ins *buf_end;
330 sljit_uw word_count;
331 sljit_sw executable_offset;
332 sljit_uw addr;
334 struct sljit_label *label;
335 struct sljit_jump *jump;
336 struct sljit_const *const_;
338 CHECK_ERROR_PTR();
339 CHECK_PTR(check_sljit_generate_code(compiler));
340 reverse_buf(compiler);
342 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
343 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
344 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
345 #else
346 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
347 #endif
348 #endif
349 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
350 PTR_FAIL_WITH_EXEC_IF(code);
351 buf = compiler->buf;
353 code_ptr = code;
354 word_count = 0;
355 executable_offset = SLJIT_EXEC_OFFSET(code);
357 label = compiler->labels;
358 jump = compiler->jumps;
359 const_ = compiler->consts;
361 do {
362 buf_ptr = (sljit_ins*)buf->memory;
363 buf_end = buf_ptr + (buf->used_size >> 2);
364 do {
365 *code_ptr = *buf_ptr++;
366 SLJIT_ASSERT(!label || label->size >= word_count);
367 SLJIT_ASSERT(!jump || jump->addr >= word_count);
368 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
369 /* These structures are ordered by their address. */
370 if (label && label->size == word_count) {
371 /* Just recording the address. */
372 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
373 label->size = code_ptr - code;
374 label = label->next;
376 if (jump && jump->addr == word_count) {
377 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
378 jump->addr = (sljit_uw)(code_ptr - 3);
379 #else
380 jump->addr = (sljit_uw)(code_ptr - 6);
381 #endif
382 if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
383 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
384 code_ptr[-3] = code_ptr[0];
385 code_ptr -= 3;
386 #else
387 if (jump->flags & PATCH_ABS32) {
388 code_ptr -= 3;
389 code_ptr[-1] = code_ptr[2];
390 code_ptr[0] = code_ptr[3];
392 else if (jump->flags & PATCH_ABS48) {
393 code_ptr--;
394 code_ptr[-1] = code_ptr[0];
395 code_ptr[0] = code_ptr[1];
396 /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
397 SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
398 code_ptr[-3] ^= 0x8422;
399 /* oris -> ori */
400 code_ptr[-2] ^= 0x4000000;
402 else {
403 code_ptr[-6] = code_ptr[0];
404 code_ptr -= 6;
406 #endif
407 if (jump->flags & REMOVE_COND) {
408 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
409 code_ptr++;
410 jump->addr += sizeof(sljit_ins);
411 code_ptr[0] = Bx;
412 jump->flags -= IS_COND;
415 jump = jump->next;
417 if (const_ && const_->addr == word_count) {
418 const_->addr = (sljit_uw)code_ptr;
419 const_ = const_->next;
421 code_ptr ++;
422 word_count ++;
423 } while (buf_ptr < buf_end);
425 buf = buf->next;
426 } while (buf);
428 if (label && label->size == word_count) {
429 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
430 label->size = code_ptr - code;
431 label = label->next;
434 SLJIT_ASSERT(!label);
435 SLJIT_ASSERT(!jump);
436 SLJIT_ASSERT(!const_);
437 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
438 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
439 #else
440 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
441 #endif
443 jump = compiler->jumps;
444 while (jump) {
445 do {
446 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
447 buf_ptr = (sljit_ins *)jump->addr;
449 if (jump->flags & PATCH_B) {
450 if (jump->flags & IS_COND) {
451 if (!(jump->flags & PATCH_ABS_B)) {
452 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
453 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
454 *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
456 else {
457 SLJIT_ASSERT(addr <= 0xffff);
458 *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
461 else {
462 if (!(jump->flags & PATCH_ABS_B)) {
463 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
464 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
465 *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
467 else {
468 SLJIT_ASSERT(addr <= 0x03ffffff);
469 *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
472 break;
475 /* Set the fields of immediate loads. */
476 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
477 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
478 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
479 #else
480 if (jump->flags & PATCH_ABS32) {
481 SLJIT_ASSERT(addr <= 0x7fffffff);
482 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
483 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
484 break;
486 if (jump->flags & PATCH_ABS48) {
487 SLJIT_ASSERT(addr <= 0x7fffffffffff);
488 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
489 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
490 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
491 break;
493 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
494 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
495 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
496 buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
497 #endif
498 } while (0);
499 jump = jump->next;
502 compiler->error = SLJIT_ERR_COMPILED;
503 compiler->executable_offset = executable_offset;
504 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
506 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
508 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
509 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
510 if (((sljit_sw)code_ptr) & 0x4)
511 code_ptr++;
512 #endif
513 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
514 #endif
516 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
518 SLJIT_CACHE_FLUSH(code, code_ptr);
520 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
521 return code_ptr;
522 #else
523 return code;
524 #endif
527 /* --------------------------------------------------------------------- */
528 /* Entry, exit */
529 /* --------------------------------------------------------------------- */
531 /* inp_flags: */
533 /* Creates an index in data_transfer_insts array. */
534 #define LOAD_DATA 0x01
535 #define INDEXED 0x02
536 #define WRITE_BACK 0x04
537 #define WORD_DATA 0x00
538 #define BYTE_DATA 0x08
539 #define HALF_DATA 0x10
540 #define INT_DATA 0x18
541 #define SIGNED_DATA 0x20
542 /* Separates integer and floating point registers */
543 #define GPR_REG 0x3f
544 #define DOUBLE_DATA 0x40
546 #define MEM_MASK 0x7f
548 /* Other inp_flags. */
550 #define ARG_TEST 0x000100
551 /* Integer opertion and set flags -> requires exts on 64 bit systems. */
552 #define ALT_SIGN_EXT 0x000200
553 /* This flag affects the RC() and OERC() macros. */
554 #define ALT_SET_FLAGS 0x000400
555 #define ALT_KEEP_CACHE 0x000800
556 #define ALT_FORM1 0x010000
557 #define ALT_FORM2 0x020000
558 #define ALT_FORM3 0x040000
559 #define ALT_FORM4 0x080000
560 #define ALT_FORM5 0x100000
561 #define ALT_FORM6 0x200000
563 /* Source and destination is register. */
564 #define REG_DEST 0x000001
565 #define REG1_SOURCE 0x000002
566 #define REG2_SOURCE 0x000004
567 /* getput_arg_fast returned true. */
568 #define FAST_DEST 0x000008
569 /* Multiple instructions are required. */
570 #define SLOW_DEST 0x000010
572 ALT_SIGN_EXT 0x000200
573 ALT_SET_FLAGS 0x000400
574 ALT_FORM1 0x010000
576 ALT_FORM6 0x200000 */
578 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
579 #include "sljitNativePPC_32.c"
580 #else
581 #include "sljitNativePPC_64.c"
582 #endif
584 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
585 #define STACK_STORE STW
586 #define STACK_LOAD LWZ
587 #else
588 #define STACK_STORE STD
589 #define STACK_LOAD LD
590 #endif
592 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
593 sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
594 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
596 sljit_s32 i, tmp, offs;
598 CHECK_ERROR();
599 CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
600 set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
602 FAIL_IF(push_inst(compiler, MFLR | D(0)));
603 offs = -(sljit_s32)(sizeof(sljit_sw));
604 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
606 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
607 for (i = SLJIT_S0; i >= tmp; i--) {
608 offs -= (sljit_s32)(sizeof(sljit_sw));
609 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
612 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
613 offs -= (sljit_s32)(sizeof(sljit_sw));
614 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
617 SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
619 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
620 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
621 #else
622 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
623 #endif
625 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
626 if (args >= 1)
627 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
628 if (args >= 2)
629 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
630 if (args >= 3)
631 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
633 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
634 local_size = (local_size + 15) & ~0xf;
635 compiler->local_size = local_size;
637 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
638 if (local_size <= SIMM_MAX)
639 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
640 else {
641 FAIL_IF(load_immediate(compiler, 0, -local_size));
642 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
644 #else
645 if (local_size <= SIMM_MAX)
646 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
647 else {
648 FAIL_IF(load_immediate(compiler, 0, -local_size));
649 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
651 #endif
653 return SLJIT_SUCCESS;
656 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
657 sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
658 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
660 CHECK_ERROR();
661 CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
662 set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
664 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
665 compiler->local_size = (local_size + 15) & ~0xf;
666 return SLJIT_SUCCESS;
669 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
671 sljit_s32 i, tmp, offs;
673 CHECK_ERROR();
674 CHECK(check_sljit_emit_return(compiler, op, src, srcw));
676 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
678 if (compiler->local_size <= SIMM_MAX)
679 FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
680 else {
681 FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
682 FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
685 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
686 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
687 #else
688 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
689 #endif
691 offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
693 tmp = compiler->scratches;
694 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
695 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
696 offs += (sljit_s32)(sizeof(sljit_sw));
699 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
700 for (i = tmp; i <= SLJIT_S0; i++) {
701 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
702 offs += (sljit_s32)(sizeof(sljit_sw));
705 FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
706 SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
708 FAIL_IF(push_inst(compiler, MTLR | S(0)));
709 FAIL_IF(push_inst(compiler, BLR));
711 return SLJIT_SUCCESS;
714 #undef STACK_STORE
715 #undef STACK_LOAD
717 /* --------------------------------------------------------------------- */
718 /* Operators */
719 /* --------------------------------------------------------------------- */
721 /* i/x - immediate/indexed form
722 n/w - no write-back / write-back (1 bit)
723 s/l - store/load (1 bit)
724 u/s - signed/unsigned (1 bit)
725 w/b/h/i - word/byte/half/int allowed (2 bit)
726 It contans 32 items, but not all are different. */
728 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
729 #define INT_ALIGNED 0x10000
730 /* 64-bit only: there is no lwau instruction. */
731 #define UPDATE_REQ 0x20000
733 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
734 #define ARCH_32_64(a, b) a
735 #define INST_CODE_AND_DST(inst, flags, reg) \
736 ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
737 #else
738 #define ARCH_32_64(a, b) b
739 #define INST_CODE_AND_DST(inst, flags, reg) \
740 (((inst) & ~(INT_ALIGNED | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
741 #endif
743 static const sljit_ins data_transfer_insts[64 + 8] = {
745 /* -------- Unsigned -------- */
747 /* Word. */
749 /* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
750 /* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
751 /* u w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
752 /* u w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
754 /* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
755 /* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
756 /* u w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
757 /* u w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
759 /* Byte. */
761 /* u b n i s */ HI(38) /* stb */,
762 /* u b n i l */ HI(34) /* lbz */,
763 /* u b n x s */ HI(31) | LO(215) /* stbx */,
764 /* u b n x l */ HI(31) | LO(87) /* lbzx */,
766 /* u b w i s */ HI(39) /* stbu */,
767 /* u b w i l */ HI(35) /* lbzu */,
768 /* u b w x s */ HI(31) | LO(247) /* stbux */,
769 /* u b w x l */ HI(31) | LO(119) /* lbzux */,
771 /* Half. */
773 /* u h n i s */ HI(44) /* sth */,
774 /* u h n i l */ HI(40) /* lhz */,
775 /* u h n x s */ HI(31) | LO(407) /* sthx */,
776 /* u h n x l */ HI(31) | LO(279) /* lhzx */,
778 /* u h w i s */ HI(45) /* sthu */,
779 /* u h w i l */ HI(41) /* lhzu */,
780 /* u h w x s */ HI(31) | LO(439) /* sthux */,
781 /* u h w x l */ HI(31) | LO(311) /* lhzux */,
783 /* Int. */
785 /* u i n i s */ HI(36) /* stw */,
786 /* u i n i l */ HI(32) /* lwz */,
787 /* u i n x s */ HI(31) | LO(151) /* stwx */,
788 /* u i n x l */ HI(31) | LO(23) /* lwzx */,
790 /* u i w i s */ HI(37) /* stwu */,
791 /* u i w i l */ HI(33) /* lwzu */,
792 /* u i w x s */ HI(31) | LO(183) /* stwux */,
793 /* u i w x l */ HI(31) | LO(55) /* lwzux */,
795 /* -------- Signed -------- */
797 /* Word. */
799 /* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
800 /* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
801 /* s w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
802 /* s w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
804 /* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
805 /* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
806 /* s w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
807 /* s w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
809 /* Byte. */
811 /* s b n i s */ HI(38) /* stb */,
812 /* s b n i l */ HI(34) /* lbz */ /* EXTS_REQ */,
813 /* s b n x s */ HI(31) | LO(215) /* stbx */,
814 /* s b n x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
816 /* s b w i s */ HI(39) /* stbu */,
817 /* s b w i l */ HI(35) /* lbzu */ /* EXTS_REQ */,
818 /* s b w x s */ HI(31) | LO(247) /* stbux */,
819 /* s b w x l */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */,
821 /* Half. */
823 /* s h n i s */ HI(44) /* sth */,
824 /* s h n i l */ HI(42) /* lha */,
825 /* s h n x s */ HI(31) | LO(407) /* sthx */,
826 /* s h n x l */ HI(31) | LO(343) /* lhax */,
828 /* s h w i s */ HI(45) /* sthu */,
829 /* s h w i l */ HI(43) /* lhau */,
830 /* s h w x s */ HI(31) | LO(439) /* sthux */,
831 /* s h w x l */ HI(31) | LO(375) /* lhaux */,
833 /* Int. */
835 /* s i n i s */ HI(36) /* stw */,
836 /* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
837 /* s i n x s */ HI(31) | LO(151) /* stwx */,
838 /* s i n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
840 /* s i w i s */ HI(37) /* stwu */,
841 /* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | UPDATE_REQ | 0x2 /* lwa */),
842 /* s i w x s */ HI(31) | LO(183) /* stwux */,
843 /* s i w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
845 /* -------- Double -------- */
847 /* d n i s */ HI(54) /* stfd */,
848 /* d n i l */ HI(50) /* lfd */,
849 /* d n x s */ HI(31) | LO(727) /* stfdx */,
850 /* d n x l */ HI(31) | LO(599) /* lfdx */,
852 /* s n i s */ HI(52) /* stfs */,
853 /* s n i l */ HI(48) /* lfs */,
854 /* s n x s */ HI(31) | LO(663) /* stfsx */,
855 /* s n x l */ HI(31) | LO(535) /* lfsx */,
859 #undef ARCH_32_64
861 /* Simple cases, (no caching is required). */
862 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
864 sljit_ins inst;
866 /* Should work when (arg & REG_MASK) == 0. */
867 SLJIT_COMPILE_ASSERT(A(0) == 0, a0_must_be_0);
868 SLJIT_ASSERT(arg & SLJIT_MEM);
870 if (arg & OFFS_REG_MASK) {
871 if (argw & 0x3)
872 return 0;
873 if (inp_flags & ARG_TEST)
874 return 1;
876 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
877 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
878 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(OFFS_REG(arg))));
879 return -1;
882 if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
883 inp_flags &= ~WRITE_BACK;
885 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
886 inst = data_transfer_insts[inp_flags & MEM_MASK];
887 SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
889 if (argw > SIMM_MAX || argw < SIMM_MIN || ((inst & INT_ALIGNED) && (argw & 0x3)) || (inst & UPDATE_REQ))
890 return 0;
891 if (inp_flags & ARG_TEST)
892 return 1;
893 #endif
895 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
896 if (argw > SIMM_MAX || argw < SIMM_MIN)
897 return 0;
898 if (inp_flags & ARG_TEST)
899 return 1;
901 inst = data_transfer_insts[inp_flags & MEM_MASK];
902 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
903 #endif
905 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | IMM(argw)));
906 return -1;
909 /* See getput_arg below.
910 Note: can_cache is called only for binary operators. Those operator always
911 uses word arguments without write back. */
912 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
914 sljit_sw high_short, next_high_short;
915 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
916 sljit_sw diff;
917 #endif
919 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
921 if (arg & OFFS_REG_MASK)
922 return ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && (argw & 0x3) == (next_argw & 0x3));
924 if (next_arg & OFFS_REG_MASK)
925 return 0;
927 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
928 high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
929 next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
930 return high_short == next_high_short;
931 #else
932 if (argw <= 0x7fffffffl && argw >= -0x80000000l) {
933 high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
934 next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
935 if (high_short == next_high_short)
936 return 1;
939 diff = argw - next_argw;
940 if (!(arg & REG_MASK))
941 return diff <= SIMM_MAX && diff >= SIMM_MIN;
943 if (arg == next_arg && diff <= SIMM_MAX && diff >= SIMM_MIN)
944 return 1;
946 return 0;
947 #endif
950 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
951 #define ADJUST_CACHED_IMM(imm) \
952 if ((inst & INT_ALIGNED) && (imm & 0x3)) { \
953 /* Adjust cached value. Fortunately this is really a rare case */ \
954 compiler->cache_argw += imm & 0x3; \
955 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \
956 imm &= ~0x3; \
958 #endif
960 /* Emit the necessary instructions. See can_cache above. */
961 static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
963 sljit_s32 tmp_r;
964 sljit_ins inst;
965 sljit_sw high_short, next_high_short;
966 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
967 sljit_sw diff;
968 #endif
970 SLJIT_ASSERT(arg & SLJIT_MEM);
972 tmp_r = ((inp_flags & LOAD_DATA) && ((inp_flags) & MEM_MASK) <= GPR_REG) ? reg : TMP_REG1;
973 /* Special case for "mov reg, [reg, ... ]". */
974 if ((arg & REG_MASK) == tmp_r)
975 tmp_r = TMP_REG1;
977 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
978 argw &= 0x3;
979 /* Otherwise getput_arg_fast would capture it. */
980 SLJIT_ASSERT(argw);
982 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg && argw == compiler->cache_argw)
983 tmp_r = TMP_REG3;
984 else {
985 if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {
986 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
987 compiler->cache_argw = argw;
988 tmp_r = TMP_REG3;
990 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
991 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
992 #else
993 FAIL_IF(push_inst(compiler, RLDI(tmp_r, OFFS_REG(arg), argw, 63 - argw, 1)));
994 #endif
996 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
997 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
998 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
1001 if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
1002 inp_flags &= ~WRITE_BACK;
1004 inst = data_transfer_insts[inp_flags & MEM_MASK];
1005 SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
1007 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1008 if (argw <= 0x7fff7fffl && argw >= -0x80000000l
1009 && (!(inst & INT_ALIGNED) || !(argw & 0x3)) && !(inst & UPDATE_REQ)) {
1010 #endif
1012 arg &= REG_MASK;
1013 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
1014 /* The getput_arg_fast should handle this otherwise. */
1015 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1016 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
1017 #else
1018 SLJIT_ASSERT(high_short && !(inst & (INT_ALIGNED | UPDATE_REQ)));
1019 #endif
1021 if (inp_flags & WRITE_BACK) {
1022 if (arg == reg) {
1023 FAIL_IF(push_inst(compiler, OR | S(reg) | A(tmp_r) | B(reg)));
1024 reg = tmp_r;
1026 tmp_r = arg;
1027 FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
1029 else if (compiler->cache_arg != (SLJIT_MEM | arg) || high_short != compiler->cache_argw) {
1030 if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) {
1031 next_high_short = (sljit_s32)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
1032 if (high_short == next_high_short) {
1033 compiler->cache_arg = SLJIT_MEM | arg;
1034 compiler->cache_argw = high_short;
1035 tmp_r = TMP_REG3;
1038 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_r) | A(arg & REG_MASK) | IMM(high_short >> 16)));
1040 else
1041 tmp_r = TMP_REG3;
1043 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r) | IMM(argw));
1045 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1048 /* Everything else is PPC-64 only. */
1049 if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
1050 diff = argw - compiler->cache_argw;
1051 if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1052 ADJUST_CACHED_IMM(diff);
1053 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
1056 diff = argw - next_argw;
1057 if ((next_arg & SLJIT_MEM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1058 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1060 compiler->cache_arg = SLJIT_IMM;
1061 compiler->cache_argw = argw;
1062 tmp_r = TMP_REG3;
1065 FAIL_IF(load_immediate(compiler, tmp_r, argw));
1066 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r));
1069 diff = argw - compiler->cache_argw;
1070 if (compiler->cache_arg == arg && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1071 SLJIT_ASSERT(!(inp_flags & WRITE_BACK) && !(inst & UPDATE_REQ));
1072 ADJUST_CACHED_IMM(diff);
1073 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
1076 if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1077 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1078 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1079 if (compiler->cache_argw != argw) {
1080 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | IMM(diff)));
1081 compiler->cache_argw = argw;
1083 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
1086 if (argw == next_argw && (next_arg & SLJIT_MEM)) {
1087 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1088 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1090 compiler->cache_arg = SLJIT_IMM;
1091 compiler->cache_argw = argw;
1093 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1094 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1095 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
1098 diff = argw - next_argw;
1099 if (arg == next_arg && !(inp_flags & WRITE_BACK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1100 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1101 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1102 FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & REG_MASK)));
1104 compiler->cache_arg = arg;
1105 compiler->cache_argw = argw;
1107 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3));
1110 if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1111 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1112 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1114 compiler->cache_arg = SLJIT_IMM;
1115 compiler->cache_argw = argw;
1116 tmp_r = TMP_REG3;
1118 else
1119 FAIL_IF(load_immediate(compiler, tmp_r, argw));
1121 /* Get the indexed version instead of the normal one. */
1122 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1123 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1124 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
1125 #endif
1128 static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
1130 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1131 return compiler->error;
1132 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1135 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1136 sljit_s32 dst, sljit_sw dstw,
1137 sljit_s32 src1, sljit_sw src1w,
1138 sljit_s32 src2, sljit_sw src2w)
1140 /* arg1 goes to TMP_REG1 or src reg
1141 arg2 goes to TMP_REG2, imm or src reg
1142 TMP_REG3 can be used for caching
1143 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1144 sljit_s32 dst_r;
1145 sljit_s32 src1_r;
1146 sljit_s32 src2_r;
1147 sljit_s32 sugg_src2_r = TMP_REG2;
1148 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1150 if (!(input_flags & ALT_KEEP_CACHE)) {
1151 compiler->cache_arg = 0;
1152 compiler->cache_argw = 0;
1155 /* Destination check. */
1156 if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
1157 if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
1158 return SLJIT_SUCCESS;
1159 dst_r = TMP_REG2;
1161 else if (FAST_IS_REG(dst)) {
1162 dst_r = dst;
1163 flags |= REG_DEST;
1164 if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
1165 sugg_src2_r = dst_r;
1167 else {
1168 SLJIT_ASSERT(dst & SLJIT_MEM);
1169 if (getput_arg_fast(compiler, input_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
1170 flags |= FAST_DEST;
1171 dst_r = TMP_REG2;
1173 else {
1174 flags |= SLOW_DEST;
1175 dst_r = 0;
1179 /* Source 1. */
1180 if (FAST_IS_REG(src1)) {
1181 src1_r = src1;
1182 flags |= REG1_SOURCE;
1184 else if (src1 & SLJIT_IMM) {
1185 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1186 src1_r = TMP_REG1;
1188 else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
1189 FAIL_IF(compiler->error);
1190 src1_r = TMP_REG1;
1192 else
1193 src1_r = 0;
1195 /* Source 2. */
1196 if (FAST_IS_REG(src2)) {
1197 src2_r = src2;
1198 flags |= REG2_SOURCE;
1199 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
1200 dst_r = src2_r;
1202 else if (src2 & SLJIT_IMM) {
1203 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1204 src2_r = sugg_src2_r;
1206 else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
1207 FAIL_IF(compiler->error);
1208 src2_r = sugg_src2_r;
1210 else
1211 src2_r = 0;
1213 /* src1_r, src2_r and dst_r can be zero (=unprocessed).
1214 All arguments are complex addressing modes, and it is a binary operator. */
1215 if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
1216 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1217 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
1218 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1220 else {
1221 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
1222 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
1224 src1_r = TMP_REG1;
1225 src2_r = TMP_REG2;
1227 else if (src1_r == 0 && src2_r == 0) {
1228 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
1229 src1_r = TMP_REG1;
1231 else if (src1_r == 0 && dst_r == 0) {
1232 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1233 src1_r = TMP_REG1;
1235 else if (src2_r == 0 && dst_r == 0) {
1236 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
1237 src2_r = sugg_src2_r;
1240 if (dst_r == 0)
1241 dst_r = TMP_REG2;
1243 if (src1_r == 0) {
1244 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
1245 src1_r = TMP_REG1;
1248 if (src2_r == 0) {
1249 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
1250 src2_r = sugg_src2_r;
1253 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1255 if (flags & (FAST_DEST | SLOW_DEST)) {
1256 if (flags & FAST_DEST)
1257 FAIL_IF(getput_arg_fast(compiler, input_flags, dst_r, dst, dstw));
1258 else
1259 FAIL_IF(getput_arg(compiler, input_flags, dst_r, dst, dstw, 0, 0));
1261 return SLJIT_SUCCESS;
1264 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1266 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1267 sljit_s32 int_op = op & SLJIT_I32_OP;
1268 #endif
1270 CHECK_ERROR();
1271 CHECK(check_sljit_emit_op0(compiler, op));
1273 op = GET_OPCODE(op);
1274 switch (op) {
1275 case SLJIT_BREAKPOINT:
1276 case SLJIT_NOP:
1277 return push_inst(compiler, NOP);
1278 case SLJIT_LMUL_UW:
1279 case SLJIT_LMUL_SW:
1280 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1281 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1282 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1283 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1284 #else
1285 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1286 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1287 #endif
1288 case SLJIT_DIVMOD_UW:
1289 case SLJIT_DIVMOD_SW:
1290 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1291 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1292 FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1293 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1294 #else
1295 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1296 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1297 #endif
1298 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1299 case SLJIT_DIV_UW:
1300 case SLJIT_DIV_SW:
1301 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1302 return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1303 #else
1304 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1305 #endif
1308 return SLJIT_SUCCESS;
1311 #define EMIT_MOV(type, type_flags, type_cast) \
1312 emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw)
1314 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1315 sljit_s32 dst, sljit_sw dstw,
1316 sljit_s32 src, sljit_sw srcw)
1318 sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
1319 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1321 CHECK_ERROR();
1322 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1323 ADJUST_LOCAL_OFFSET(dst, dstw);
1324 ADJUST_LOCAL_OFFSET(src, srcw);
1326 op = GET_OPCODE(op);
1327 if ((src & SLJIT_IMM) && srcw == 0)
1328 src = TMP_ZERO;
1330 if (op_flags & SLJIT_SET_O)
1331 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1333 if (op_flags & SLJIT_I32_OP) {
1334 if (op < SLJIT_NOT) {
1335 if (FAST_IS_REG(src) && src == dst) {
1336 if (!TYPE_CAST_NEEDED(op))
1337 return SLJIT_SUCCESS;
1339 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1340 if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM))
1341 op = SLJIT_MOV_U32;
1342 if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM))
1343 op = SLJIT_MOVU_U32;
1344 if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM))
1345 op = SLJIT_MOV_S32;
1346 if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM))
1347 op = SLJIT_MOVU_S32;
1348 #endif
1350 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1351 else {
1352 /* Most operations expect sign extended arguments. */
1353 flags |= INT_DATA | SIGNED_DATA;
1354 if (src & SLJIT_IMM)
1355 srcw = (sljit_s32)srcw;
1357 #endif
1360 switch (op) {
1361 case SLJIT_MOV:
1362 case SLJIT_MOV_P:
1363 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1364 case SLJIT_MOV_U32:
1365 case SLJIT_MOV_S32:
1366 #endif
1367 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1369 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1370 case SLJIT_MOV_U32:
1371 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1373 case SLJIT_MOV_S32:
1374 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1375 #endif
1377 case SLJIT_MOV_U8:
1378 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1380 case SLJIT_MOV_S8:
1381 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1383 case SLJIT_MOV_U16:
1384 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1386 case SLJIT_MOV_S16:
1387 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1389 case SLJIT_MOVU:
1390 case SLJIT_MOVU_P:
1391 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1392 case SLJIT_MOVU_U32:
1393 case SLJIT_MOVU_S32:
1394 #endif
1395 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
1397 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1398 case SLJIT_MOVU_U32:
1399 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA | WRITE_BACK, (sljit_u32));
1401 case SLJIT_MOVU_S32:
1402 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s32));
1403 #endif
1405 case SLJIT_MOVU_U8:
1406 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, (sljit_u8));
1408 case SLJIT_MOVU_S8:
1409 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s8));
1411 case SLJIT_MOVU_U16:
1412 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, (sljit_u16));
1414 case SLJIT_MOVU_S16:
1415 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s16));
1417 case SLJIT_NOT:
1418 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1420 case SLJIT_NEG:
1421 return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1423 case SLJIT_CLZ:
1424 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1425 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1426 #else
1427 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1428 #endif
1431 return SLJIT_SUCCESS;
1434 #undef EMIT_MOV
1436 #define TEST_SL_IMM(src, srcw) \
1437 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1439 #define TEST_UL_IMM(src, srcw) \
1440 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1442 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1443 #define TEST_SH_IMM(src, srcw) \
1444 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1445 #else
1446 #define TEST_SH_IMM(src, srcw) \
1447 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1448 #endif
1450 #define TEST_UH_IMM(src, srcw) \
1451 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
1453 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1454 #define TEST_ADD_IMM(src, srcw) \
1455 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1456 #else
1457 #define TEST_ADD_IMM(src, srcw) \
1458 ((src) & SLJIT_IMM)
1459 #endif
1461 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1462 #define TEST_UI_IMM(src, srcw) \
1463 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1464 #else
1465 #define TEST_UI_IMM(src, srcw) \
1466 ((src) & SLJIT_IMM)
1467 #endif
1469 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1470 sljit_s32 dst, sljit_sw dstw,
1471 sljit_s32 src1, sljit_sw src1w,
1472 sljit_s32 src2, sljit_sw src2w)
1474 sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
1476 CHECK_ERROR();
1477 CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1478 ADJUST_LOCAL_OFFSET(dst, dstw);
1479 ADJUST_LOCAL_OFFSET(src1, src1w);
1480 ADJUST_LOCAL_OFFSET(src2, src2w);
1482 if ((src1 & SLJIT_IMM) && src1w == 0)
1483 src1 = TMP_ZERO;
1484 if ((src2 & SLJIT_IMM) && src2w == 0)
1485 src2 = TMP_ZERO;
1487 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1488 if (op & SLJIT_I32_OP) {
1489 /* Most operations expect sign extended arguments. */
1490 flags |= INT_DATA | SIGNED_DATA;
1491 if (src1 & SLJIT_IMM)
1492 src1w = (sljit_s32)(src1w);
1493 if (src2 & SLJIT_IMM)
1494 src2w = (sljit_s32)(src2w);
1495 if (GET_FLAGS(op))
1496 flags |= ALT_SIGN_EXT;
1498 #endif
1499 if (op & SLJIT_SET_O)
1500 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1501 if (src2 == TMP_REG2)
1502 flags |= ALT_KEEP_CACHE;
1504 switch (GET_OPCODE(op)) {
1505 case SLJIT_ADD:
1506 if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1507 if (TEST_SL_IMM(src2, src2w)) {
1508 compiler->imm = src2w & 0xffff;
1509 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1511 if (TEST_SL_IMM(src1, src1w)) {
1512 compiler->imm = src1w & 0xffff;
1513 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1515 if (TEST_SH_IMM(src2, src2w)) {
1516 compiler->imm = (src2w >> 16) & 0xffff;
1517 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1519 if (TEST_SH_IMM(src1, src1w)) {
1520 compiler->imm = (src1w >> 16) & 0xffff;
1521 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1523 /* Range between -1 and -32768 is covered above. */
1524 if (TEST_ADD_IMM(src2, src2w)) {
1525 compiler->imm = src2w & 0xffffffff;
1526 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1528 if (TEST_ADD_IMM(src1, src1w)) {
1529 compiler->imm = src1w & 0xffffffff;
1530 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1533 if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
1534 if (TEST_SL_IMM(src2, src2w)) {
1535 compiler->imm = src2w & 0xffff;
1536 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1538 if (TEST_SL_IMM(src1, src1w)) {
1539 compiler->imm = src1w & 0xffff;
1540 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1543 return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w);
1545 case SLJIT_ADDC:
1546 return emit_op(compiler, SLJIT_ADDC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
1548 case SLJIT_SUB:
1549 if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1550 if (TEST_SL_IMM(src2, -src2w)) {
1551 compiler->imm = (-src2w) & 0xffff;
1552 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1554 if (TEST_SL_IMM(src1, src1w)) {
1555 compiler->imm = src1w & 0xffff;
1556 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1558 if (TEST_SH_IMM(src2, -src2w)) {
1559 compiler->imm = ((-src2w) >> 16) & 0xffff;
1560 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1562 /* Range between -1 and -32768 is covered above. */
1563 if (TEST_ADD_IMM(src2, -src2w)) {
1564 compiler->imm = -src2w & 0xffffffff;
1565 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1568 if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
1569 if (!(op & SLJIT_SET_U)) {
1570 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1571 if (TEST_SL_IMM(src2, src2w)) {
1572 compiler->imm = src2w & 0xffff;
1573 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1575 if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
1576 compiler->imm = src1w & 0xffff;
1577 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1580 if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
1581 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1582 if (TEST_UL_IMM(src2, src2w)) {
1583 compiler->imm = src2w & 0xffff;
1584 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1586 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1588 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
1589 compiler->imm = src2w;
1590 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1592 return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1594 if (!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))) {
1595 if (TEST_SL_IMM(src2, -src2w)) {
1596 compiler->imm = (-src2w) & 0xffff;
1597 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1600 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1601 return emit_op(compiler, SLJIT_SUB, flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
1603 case SLJIT_SUBC:
1604 return emit_op(compiler, SLJIT_SUBC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
1606 case SLJIT_MUL:
1607 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1608 if (op & SLJIT_I32_OP)
1609 flags |= ALT_FORM2;
1610 #endif
1611 if (!GET_FLAGS(op)) {
1612 if (TEST_SL_IMM(src2, src2w)) {
1613 compiler->imm = src2w & 0xffff;
1614 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1616 if (TEST_SL_IMM(src1, src1w)) {
1617 compiler->imm = src1w & 0xffff;
1618 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1621 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1623 case SLJIT_AND:
1624 case SLJIT_OR:
1625 case SLJIT_XOR:
1626 /* Commutative unsigned operations. */
1627 if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1628 if (TEST_UL_IMM(src2, src2w)) {
1629 compiler->imm = src2w;
1630 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1632 if (TEST_UL_IMM(src1, src1w)) {
1633 compiler->imm = src1w;
1634 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1636 if (TEST_UH_IMM(src2, src2w)) {
1637 compiler->imm = (src2w >> 16) & 0xffff;
1638 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1640 if (TEST_UH_IMM(src1, src1w)) {
1641 compiler->imm = (src1w >> 16) & 0xffff;
1642 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1645 if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
1646 if (TEST_UI_IMM(src2, src2w)) {
1647 compiler->imm = src2w;
1648 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1650 if (TEST_UI_IMM(src1, src1w)) {
1651 compiler->imm = src1w;
1652 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1655 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1657 case SLJIT_ASHR:
1658 if (op & SLJIT_KEEP_FLAGS)
1659 flags |= ALT_FORM3;
1660 /* Fall through. */
1661 case SLJIT_SHL:
1662 case SLJIT_LSHR:
1663 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1664 if (op & SLJIT_I32_OP)
1665 flags |= ALT_FORM2;
1666 #endif
1667 if (src2 & SLJIT_IMM) {
1668 compiler->imm = src2w;
1669 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1671 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1674 return SLJIT_SUCCESS;
1677 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1679 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1680 return reg_map[reg];
1683 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1685 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1686 return reg;
1689 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1690 void *instruction, sljit_s32 size)
1692 CHECK_ERROR();
1693 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1695 return push_inst(compiler, *(sljit_ins*)instruction);
1698 /* --------------------------------------------------------------------- */
1699 /* Floating point operators */
1700 /* --------------------------------------------------------------------- */
1702 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
1704 #ifdef SLJIT_IS_FPU_AVAILABLE
1705 return SLJIT_IS_FPU_AVAILABLE;
1706 #else
1707 /* Available by default. */
1708 return 1;
1709 #endif
1712 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
1713 #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
1715 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1716 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1717 #else
1718 #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1720 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1721 #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1722 #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1723 #else
1724 #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1725 #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1726 #endif
1728 #endif /* SLJIT_CONFIG_PPC_64 */
1730 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1731 sljit_s32 dst, sljit_sw dstw,
1732 sljit_s32 src, sljit_sw srcw)
1734 if (src & SLJIT_MEM) {
1735 /* We can ignore the temporary data store on the stack from caching point of view. */
1736 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
1737 src = TMP_FREG1;
1740 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1741 op = GET_OPCODE(op);
1742 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1744 if (dst == SLJIT_UNUSED)
1745 return SLJIT_SUCCESS;
1747 if (op == SLJIT_CONV_SW_FROM_F64) {
1748 if (FAST_IS_REG(dst)) {
1749 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0));
1750 return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
1752 return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
1755 #else
1756 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1758 if (dst == SLJIT_UNUSED)
1759 return SLJIT_SUCCESS;
1760 #endif
1762 if (FAST_IS_REG(dst)) {
1763 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1764 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1765 return emit_op_mem2(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
1768 SLJIT_ASSERT(dst & SLJIT_MEM);
1770 if (dst & OFFS_REG_MASK) {
1771 dstw &= 0x3;
1772 if (dstw) {
1773 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1774 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
1775 #else
1776 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1777 #endif
1778 dstw = TMP_REG1;
1780 else
1781 dstw = OFFS_REG(dst);
1783 else {
1784 if ((dst & REG_MASK) && !dstw) {
1785 dstw = dst & REG_MASK;
1786 dst = 0;
1788 else {
1789 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1790 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1791 dstw = TMP_REG1;
1795 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1798 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1799 sljit_s32 dst, sljit_sw dstw,
1800 sljit_s32 src, sljit_sw srcw)
1802 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1804 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1806 if (src & SLJIT_IMM) {
1807 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1808 srcw = (sljit_s32)srcw;
1809 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1810 src = TMP_REG1;
1812 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1813 if (FAST_IS_REG(src))
1814 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1815 else
1816 FAIL_IF(emit_op_mem2(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1817 src = TMP_REG1;
1820 if (FAST_IS_REG(src)) {
1821 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1822 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, dst, dstw));
1824 else
1825 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
1827 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1829 if (dst & SLJIT_MEM)
1830 return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
1831 if (op & SLJIT_F32_OP)
1832 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1833 return SLJIT_SUCCESS;
1835 #else
1837 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1838 sljit_s32 invert_sign = 1;
1840 if (src & SLJIT_IMM) {
1841 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
1842 src = TMP_REG1;
1843 invert_sign = 0;
1845 else if (!FAST_IS_REG(src)) {
1846 FAIL_IF(emit_op_mem2(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1847 src = TMP_REG1;
1850 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1851 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1852 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1853 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1854 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1855 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1856 if (invert_sign)
1857 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1858 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1859 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI));
1860 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1861 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1862 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1863 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1865 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1867 if (dst & SLJIT_MEM)
1868 return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
1869 if (op & SLJIT_F32_OP)
1870 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1871 return SLJIT_SUCCESS;
1873 #endif
1876 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1877 sljit_s32 src1, sljit_sw src1w,
1878 sljit_s32 src2, sljit_sw src2w)
1880 if (src1 & SLJIT_MEM) {
1881 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
1882 src1 = TMP_FREG1;
1885 if (src2 & SLJIT_MEM) {
1886 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
1887 src2 = TMP_FREG2;
1890 return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
1893 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1894 sljit_s32 dst, sljit_sw dstw,
1895 sljit_s32 src, sljit_sw srcw)
1897 sljit_s32 dst_r;
1899 CHECK_ERROR();
1900 compiler->cache_arg = 0;
1901 compiler->cache_argw = 0;
1903 SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1904 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1906 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1907 op ^= SLJIT_F32_OP;
1909 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1911 if (src & SLJIT_MEM) {
1912 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
1913 src = dst_r;
1916 switch (GET_OPCODE(op)) {
1917 case SLJIT_CONV_F64_FROM_F32:
1918 op ^= SLJIT_F32_OP;
1919 if (op & SLJIT_F32_OP) {
1920 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1921 break;
1923 /* Fall through. */
1924 case SLJIT_MOV_F64:
1925 if (src != dst_r) {
1926 if (dst_r != TMP_FREG1)
1927 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1928 else
1929 dst_r = src;
1931 break;
1932 case SLJIT_NEG_F64:
1933 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1934 break;
1935 case SLJIT_ABS_F64:
1936 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1937 break;
1940 if (dst & SLJIT_MEM)
1941 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));
1942 return SLJIT_SUCCESS;
1945 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1946 sljit_s32 dst, sljit_sw dstw,
1947 sljit_s32 src1, sljit_sw src1w,
1948 sljit_s32 src2, sljit_sw src2w)
1950 sljit_s32 dst_r, flags = 0;
1952 CHECK_ERROR();
1953 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1954 ADJUST_LOCAL_OFFSET(dst, dstw);
1955 ADJUST_LOCAL_OFFSET(src1, src1w);
1956 ADJUST_LOCAL_OFFSET(src2, src2w);
1958 compiler->cache_arg = 0;
1959 compiler->cache_argw = 0;
1961 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1963 if (src1 & SLJIT_MEM) {
1964 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
1965 FAIL_IF(compiler->error);
1966 src1 = TMP_FREG1;
1967 } else
1968 flags |= ALT_FORM1;
1971 if (src2 & SLJIT_MEM) {
1972 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
1973 FAIL_IF(compiler->error);
1974 src2 = TMP_FREG2;
1975 } else
1976 flags |= ALT_FORM2;
1979 if ((flags & (ALT_FORM1 | ALT_FORM2)) == (ALT_FORM1 | ALT_FORM2)) {
1980 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1981 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
1982 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
1984 else {
1985 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
1986 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
1989 else if (flags & ALT_FORM1)
1990 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
1991 else if (flags & ALT_FORM2)
1992 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
1994 if (flags & ALT_FORM1)
1995 src1 = TMP_FREG1;
1996 if (flags & ALT_FORM2)
1997 src2 = TMP_FREG2;
1999 switch (GET_OPCODE(op)) {
2000 case SLJIT_ADD_F64:
2001 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
2002 break;
2004 case SLJIT_SUB_F64:
2005 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
2006 break;
2008 case SLJIT_MUL_F64:
2009 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
2010 break;
2012 case SLJIT_DIV_F64:
2013 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
2014 break;
2017 if (dst_r == TMP_FREG2)
2018 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
2020 return SLJIT_SUCCESS;
2023 #undef FLOAT_DATA
2024 #undef SELECT_FOP
2026 /* --------------------------------------------------------------------- */
2027 /* Other instructions */
2028 /* --------------------------------------------------------------------- */
2030 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2032 CHECK_ERROR();
2033 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2034 ADJUST_LOCAL_OFFSET(dst, dstw);
2036 /* For UNUSED dst. Uncommon, but possible. */
2037 if (dst == SLJIT_UNUSED)
2038 return SLJIT_SUCCESS;
2040 if (FAST_IS_REG(dst))
2041 return push_inst(compiler, MFLR | D(dst));
2043 /* Memory. */
2044 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
2045 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2048 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
2050 CHECK_ERROR();
2051 CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
2052 ADJUST_LOCAL_OFFSET(src, srcw);
2054 if (FAST_IS_REG(src))
2055 FAIL_IF(push_inst(compiler, MTLR | S(src)));
2056 else {
2057 if (src & SLJIT_MEM)
2058 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
2059 else if (src & SLJIT_IMM)
2060 FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
2061 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
2063 return push_inst(compiler, BLR);
2066 /* --------------------------------------------------------------------- */
2067 /* Conditional instructions */
2068 /* --------------------------------------------------------------------- */
2070 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2072 struct sljit_label *label;
2074 CHECK_ERROR_PTR();
2075 CHECK_PTR(check_sljit_emit_label(compiler));
2077 if (compiler->last_label && compiler->last_label->size == compiler->size)
2078 return compiler->last_label;
2080 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2081 PTR_FAIL_IF(!label);
2082 set_label(label, compiler);
2083 return label;
2086 static sljit_ins get_bo_bi_flags(sljit_s32 type)
2088 switch (type) {
2089 case SLJIT_EQUAL:
2090 return (12 << 21) | (2 << 16);
2092 case SLJIT_NOT_EQUAL:
2093 return (4 << 21) | (2 << 16);
2095 case SLJIT_LESS:
2096 case SLJIT_LESS_F64:
2097 return (12 << 21) | ((4 + 0) << 16);
2099 case SLJIT_GREATER_EQUAL:
2100 case SLJIT_GREATER_EQUAL_F64:
2101 return (4 << 21) | ((4 + 0) << 16);
2103 case SLJIT_GREATER:
2104 case SLJIT_GREATER_F64:
2105 return (12 << 21) | ((4 + 1) << 16);
2107 case SLJIT_LESS_EQUAL:
2108 case SLJIT_LESS_EQUAL_F64:
2109 return (4 << 21) | ((4 + 1) << 16);
2111 case SLJIT_SIG_LESS:
2112 return (12 << 21) | (0 << 16);
2114 case SLJIT_SIG_GREATER_EQUAL:
2115 return (4 << 21) | (0 << 16);
2117 case SLJIT_SIG_GREATER:
2118 return (12 << 21) | (1 << 16);
2120 case SLJIT_SIG_LESS_EQUAL:
2121 return (4 << 21) | (1 << 16);
2123 case SLJIT_OVERFLOW:
2124 case SLJIT_MUL_OVERFLOW:
2125 return (12 << 21) | (3 << 16);
2127 case SLJIT_NOT_OVERFLOW:
2128 case SLJIT_MUL_NOT_OVERFLOW:
2129 return (4 << 21) | (3 << 16);
2131 case SLJIT_EQUAL_F64:
2132 return (12 << 21) | ((4 + 2) << 16);
2134 case SLJIT_NOT_EQUAL_F64:
2135 return (4 << 21) | ((4 + 2) << 16);
2137 case SLJIT_UNORDERED_F64:
2138 return (12 << 21) | ((4 + 3) << 16);
2140 case SLJIT_ORDERED_F64:
2141 return (4 << 21) | ((4 + 3) << 16);
2143 default:
2144 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3);
2145 return (20 << 21);
2149 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2151 struct sljit_jump *jump;
2152 sljit_ins bo_bi_flags;
2154 CHECK_ERROR_PTR();
2155 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2157 bo_bi_flags = get_bo_bi_flags(type & 0xff);
2158 if (!bo_bi_flags)
2159 return NULL;
2161 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2162 PTR_FAIL_IF(!jump);
2163 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2164 type &= 0xff;
2166 /* In PPC, we don't need to touch the arguments. */
2167 if (type < SLJIT_JUMP)
2168 jump->flags |= IS_COND;
2169 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2170 if (type >= SLJIT_CALL0)
2171 jump->flags |= IS_CALL;
2172 #endif
2174 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2175 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
2176 jump->addr = compiler->size;
2177 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2178 return jump;
2181 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2183 struct sljit_jump *jump = NULL;
2184 sljit_s32 src_r;
2186 CHECK_ERROR();
2187 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2188 ADJUST_LOCAL_OFFSET(src, srcw);
2190 if (FAST_IS_REG(src)) {
2191 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2192 if (type >= SLJIT_CALL0) {
2193 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2194 src_r = TMP_CALL_REG;
2196 else
2197 src_r = src;
2198 #else
2199 src_r = src;
2200 #endif
2201 } else if (src & SLJIT_IMM) {
2202 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2203 FAIL_IF(!jump);
2204 set_jump(jump, compiler, JUMP_ADDR);
2205 jump->u.target = srcw;
2206 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2207 if (type >= SLJIT_CALL0)
2208 jump->flags |= IS_CALL;
2209 #endif
2210 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2211 src_r = TMP_CALL_REG;
2213 else {
2214 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2215 src_r = TMP_CALL_REG;
2218 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2219 if (jump)
2220 jump->addr = compiler->size;
2221 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2224 /* Get a bit from CR, all other bits are zeroed. */
2225 #define GET_CR_BIT(bit, dst) \
2226 FAIL_IF(push_inst(compiler, MFCR | D(dst))); \
2227 FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1)));
2229 #define INVERT_BIT(dst) \
2230 FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1));
2232 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2233 sljit_s32 dst, sljit_sw dstw,
2234 sljit_s32 src, sljit_sw srcw,
2235 sljit_s32 type)
2237 sljit_s32 reg, input_flags;
2238 sljit_s32 flags = GET_ALL_FLAGS(op);
2239 sljit_sw original_dstw = dstw;
2241 CHECK_ERROR();
2242 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
2243 ADJUST_LOCAL_OFFSET(dst, dstw);
2245 if (dst == SLJIT_UNUSED)
2246 return SLJIT_SUCCESS;
2248 op = GET_OPCODE(op);
2249 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2251 compiler->cache_arg = 0;
2252 compiler->cache_argw = 0;
2253 if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
2254 ADJUST_LOCAL_OFFSET(src, srcw);
2255 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2256 input_flags = (flags & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
2257 #else
2258 input_flags = WORD_DATA;
2259 #endif
2260 FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
2261 src = TMP_REG1;
2262 srcw = 0;
2265 switch (type & 0xff) {
2266 case SLJIT_EQUAL:
2267 GET_CR_BIT(2, reg);
2268 break;
2270 case SLJIT_NOT_EQUAL:
2271 GET_CR_BIT(2, reg);
2272 INVERT_BIT(reg);
2273 break;
2275 case SLJIT_LESS:
2276 case SLJIT_LESS_F64:
2277 GET_CR_BIT(4 + 0, reg);
2278 break;
2280 case SLJIT_GREATER_EQUAL:
2281 case SLJIT_GREATER_EQUAL_F64:
2282 GET_CR_BIT(4 + 0, reg);
2283 INVERT_BIT(reg);
2284 break;
2286 case SLJIT_GREATER:
2287 case SLJIT_GREATER_F64:
2288 GET_CR_BIT(4 + 1, reg);
2289 break;
2291 case SLJIT_LESS_EQUAL:
2292 case SLJIT_LESS_EQUAL_F64:
2293 GET_CR_BIT(4 + 1, reg);
2294 INVERT_BIT(reg);
2295 break;
2297 case SLJIT_SIG_LESS:
2298 GET_CR_BIT(0, reg);
2299 break;
2301 case SLJIT_SIG_GREATER_EQUAL:
2302 GET_CR_BIT(0, reg);
2303 INVERT_BIT(reg);
2304 break;
2306 case SLJIT_SIG_GREATER:
2307 GET_CR_BIT(1, reg);
2308 break;
2310 case SLJIT_SIG_LESS_EQUAL:
2311 GET_CR_BIT(1, reg);
2312 INVERT_BIT(reg);
2313 break;
2315 case SLJIT_OVERFLOW:
2316 case SLJIT_MUL_OVERFLOW:
2317 GET_CR_BIT(3, reg);
2318 break;
2320 case SLJIT_NOT_OVERFLOW:
2321 case SLJIT_MUL_NOT_OVERFLOW:
2322 GET_CR_BIT(3, reg);
2323 INVERT_BIT(reg);
2324 break;
2326 case SLJIT_EQUAL_F64:
2327 GET_CR_BIT(4 + 2, reg);
2328 break;
2330 case SLJIT_NOT_EQUAL_F64:
2331 GET_CR_BIT(4 + 2, reg);
2332 INVERT_BIT(reg);
2333 break;
2335 case SLJIT_UNORDERED_F64:
2336 GET_CR_BIT(4 + 3, reg);
2337 break;
2339 case SLJIT_ORDERED_F64:
2340 GET_CR_BIT(4 + 3, reg);
2341 INVERT_BIT(reg);
2342 break;
2344 default:
2345 SLJIT_ASSERT_STOP();
2346 break;
2349 if (op < SLJIT_ADD) {
2350 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2351 if (op == SLJIT_MOV)
2352 input_flags = WORD_DATA;
2353 else {
2354 op = SLJIT_MOV_U32;
2355 input_flags = INT_DATA;
2357 #else
2358 op = SLJIT_MOV;
2359 input_flags = WORD_DATA;
2360 #endif
2361 if (reg != TMP_REG2)
2362 return SLJIT_SUCCESS;
2363 return emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2366 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2367 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2368 compiler->skip_checks = 1;
2369 #endif
2370 return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
2373 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2375 struct sljit_const *const_;
2376 sljit_s32 reg;
2378 CHECK_ERROR_PTR();
2379 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2380 ADJUST_LOCAL_OFFSET(dst, dstw);
2382 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2383 PTR_FAIL_IF(!const_);
2384 set_const(const_, compiler);
2386 reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
2388 PTR_FAIL_IF(emit_const(compiler, reg, init_value));
2390 if (dst & SLJIT_MEM)
2391 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2392 return const_;