2 * Stack-less Just-In-Time compiler
4 * Copyright 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
42 #include <sys/cache.h>
45 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
46 #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
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)
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. */
66 __asm__ volatile ( "ics" );
67 # elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
68 # error "Cache flush is not implemented for PowerPC/POWER common mode."
70 /* Cache flush for PowerPC architecture. */
80 __asm__ volatile ( "isync" );
83 # warning "This file may fail to compile if -qfuncsect is used"
85 #elif defined(__xlc__)
86 #error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
88 #error "This platform requires a cache flush implementation."
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_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)
98 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
99 #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)
101 #define TMP_CALL_REG TMP_REG2
104 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
105 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
107 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
108 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12
111 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
112 0, 1, 2, 3, 4, 5, 6, 0, 7
115 /* --------------------------------------------------------------------- */
116 /* Instrucion forms */
117 /* --------------------------------------------------------------------- */
118 #define D(d) (reg_map[d] << 21)
119 #define S(s) (reg_map[s] << 21)
120 #define A(a) (reg_map[a] << 16)
121 #define B(b) (reg_map[b] << 11)
122 #define C(c) (reg_map[c] << 6)
123 #define FD(fd) (freg_map[fd] << 21)
124 #define FS(fs) (freg_map[fs] << 21)
125 #define FA(fa) (freg_map[fa] << 16)
126 #define FB(fb) (freg_map[fb] << 11)
127 #define FC(fc) (freg_map[fc] << 6)
128 #define IMM(imm) ((imm) & 0xffff)
129 #define CRD(d) ((d) << 21)
131 /* Instruction bit sections.
132 OE and Rc flag (see ALT_SET_FLAGS). */
133 #define OE(flags) ((flags) & ALT_SET_FLAGS)
134 /* Rc flag (see ALT_SET_FLAGS). */
135 #define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)
136 #define HI(opcode) ((opcode) << 26)
137 #define LO(opcode) ((opcode) << 1)
139 #define ADD (HI(31) | LO(266))
140 #define ADDC (HI(31) | LO(10))
141 #define ADDE (HI(31) | LO(138))
142 #define ADDI (HI(14))
143 #define ADDIC (HI(13))
144 #define ADDIS (HI(15))
145 #define ADDME (HI(31) | LO(234))
146 #define AND (HI(31) | LO(28))
147 #define ANDI (HI(28))
148 #define ANDIS (HI(29))
151 #define BCCTR (HI(19) | LO(528) | (3 << 11))
152 #define BLR (HI(19) | LO(16) | (0x14 << 21))
153 #define CNTLZD (HI(31) | LO(58))
154 #define CNTLZW (HI(31) | LO(26))
155 #define CMP (HI(31) | LO(0))
156 #define CMPI (HI(11))
157 #define CMPL (HI(31) | LO(32))
158 #define CMPLI (HI(10))
159 #define CROR (HI(19) | LO(449))
160 #define DCBT (HI(31) | LO(278))
161 #define DIVD (HI(31) | LO(489))
162 #define DIVDU (HI(31) | LO(457))
163 #define DIVW (HI(31) | LO(491))
164 #define DIVWU (HI(31) | LO(459))
165 #define EXTSB (HI(31) | LO(954))
166 #define EXTSH (HI(31) | LO(922))
167 #define EXTSW (HI(31) | LO(986))
168 #define FABS (HI(63) | LO(264))
169 #define FADD (HI(63) | LO(21))
170 #define FADDS (HI(59) | LO(21))
171 #define FCFID (HI(63) | LO(846))
172 #define FCMPU (HI(63) | LO(0))
173 #define FCTIDZ (HI(63) | LO(815))
174 #define FCTIWZ (HI(63) | LO(15))
175 #define FDIV (HI(63) | LO(18))
176 #define FDIVS (HI(59) | LO(18))
177 #define FMR (HI(63) | LO(72))
178 #define FMUL (HI(63) | LO(25))
179 #define FMULS (HI(59) | LO(25))
180 #define FNEG (HI(63) | LO(40))
181 #define FRSP (HI(63) | LO(12))
182 #define FSUB (HI(63) | LO(20))
183 #define FSUBS (HI(59) | LO(20))
184 #define LD (HI(58) | 0)
186 #define MFCR (HI(31) | LO(19))
187 #define MFLR (HI(31) | LO(339) | 0x80000)
188 #define MFXER (HI(31) | LO(339) | 0x10000)
189 #define MTCTR (HI(31) | LO(467) | 0x90000)
190 #define MTLR (HI(31) | LO(467) | 0x80000)
191 #define MTXER (HI(31) | LO(467) | 0x10000)
192 #define MULHD (HI(31) | LO(73))
193 #define MULHDU (HI(31) | LO(9))
194 #define MULHW (HI(31) | LO(75))
195 #define MULHWU (HI(31) | LO(11))
196 #define MULLD (HI(31) | LO(233))
197 #define MULLI (HI(7))
198 #define MULLW (HI(31) | LO(235))
199 #define NEG (HI(31) | LO(104))
201 #define NOR (HI(31) | LO(124))
202 #define OR (HI(31) | LO(444))
204 #define ORIS (HI(25))
205 #define RLDICL (HI(30))
206 #define RLWINM (HI(21))
207 #define SLD (HI(31) | LO(27))
208 #define SLW (HI(31) | LO(24))
209 #define SRAD (HI(31) | LO(794))
210 #define SRADI (HI(31) | LO(413 << 1))
211 #define SRAW (HI(31) | LO(792))
212 #define SRAWI (HI(31) | LO(824))
213 #define SRD (HI(31) | LO(539))
214 #define SRW (HI(31) | LO(536))
215 #define STD (HI(62) | 0)
216 #define STDU (HI(62) | 1)
217 #define STDUX (HI(31) | LO(181))
218 #define STFIWX (HI(31) | LO(983))
220 #define STWU (HI(37))
221 #define STWUX (HI(31) | LO(183))
222 #define SUBF (HI(31) | LO(40))
223 #define SUBFC (HI(31) | LO(8))
224 #define SUBFE (HI(31) | LO(136))
225 #define SUBFIC (HI(8))
226 #define XOR (HI(31) | LO(316))
227 #define XORI (HI(26))
228 #define XORIS (HI(27))
230 #define SIMM_MAX (0x7fff)
231 #define SIMM_MIN (-0x8000)
232 #define UIMM_MAX (0xffff)
234 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
235 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
239 *func_ptr = (void*)context;
240 ptrs = (sljit_sw*)func;
241 context->addr = addr ? addr : ptrs[0];
242 context->r2 = ptrs[1];
243 context->r11 = ptrs[2];
247 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
249 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
253 return SLJIT_SUCCESS;
256 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
259 sljit_uw target_addr;
260 sljit_sw extra_jump_flags;
262 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
263 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
266 if (jump->flags & SLJIT_REWRITABLE_JUMP)
270 if (jump->flags & JUMP_ADDR)
271 target_addr = jump->u.target;
273 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
274 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
277 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
278 if (jump->flags & IS_CALL)
282 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
284 extra_jump_flags = 0;
285 if (jump->flags & IS_COND) {
286 if (diff <= 0x7fff && diff >= -0x8000) {
287 jump->flags |= PATCH_B;
290 if (target_addr <= 0xffff) {
291 jump->flags |= PATCH_B | PATCH_ABS_B;
294 extra_jump_flags = REMOVE_COND;
296 diff -= sizeof(sljit_ins);
299 if (diff <= 0x01ffffff && diff >= -0x02000000) {
300 jump->flags |= PATCH_B | extra_jump_flags;
304 if (target_addr <= 0x03ffffff) {
305 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
309 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
310 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
313 if (target_addr <= 0x7fffffff) {
314 jump->flags |= PATCH_ABS32;
318 if (target_addr <= 0x7fffffffffffl) {
319 jump->flags |= PATCH_ABS48;
327 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
329 struct sljit_memory_fragment *buf;
335 sljit_sw executable_offset;
338 struct sljit_label *label;
339 struct sljit_jump *jump;
340 struct sljit_const *const_;
343 CHECK_PTR(check_sljit_generate_code(compiler));
344 reverse_buf(compiler);
346 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
347 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
348 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
350 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
353 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
354 PTR_FAIL_WITH_EXEC_IF(code);
359 executable_offset = SLJIT_EXEC_OFFSET(code);
361 label = compiler->labels;
362 jump = compiler->jumps;
363 const_ = compiler->consts;
366 buf_ptr = (sljit_ins*)buf->memory;
367 buf_end = buf_ptr + (buf->used_size >> 2);
369 *code_ptr = *buf_ptr++;
370 SLJIT_ASSERT(!label || label->size >= word_count);
371 SLJIT_ASSERT(!jump || jump->addr >= word_count);
372 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
373 /* These structures are ordered by their address. */
374 if (label && label->size == word_count) {
375 /* Just recording the address. */
376 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
377 label->size = code_ptr - code;
380 if (jump && jump->addr == word_count) {
381 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
382 jump->addr = (sljit_uw)(code_ptr - 3);
384 jump->addr = (sljit_uw)(code_ptr - 6);
386 if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
387 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
388 code_ptr[-3] = code_ptr[0];
391 if (jump->flags & PATCH_ABS32) {
393 code_ptr[-1] = code_ptr[2];
394 code_ptr[0] = code_ptr[3];
396 else if (jump->flags & PATCH_ABS48) {
398 code_ptr[-1] = code_ptr[0];
399 code_ptr[0] = code_ptr[1];
400 /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
401 SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
402 code_ptr[-3] ^= 0x8422;
404 code_ptr[-2] ^= 0x4000000;
407 code_ptr[-6] = code_ptr[0];
411 if (jump->flags & REMOVE_COND) {
412 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
414 jump->addr += sizeof(sljit_ins);
416 jump->flags -= IS_COND;
421 if (const_ && const_->addr == word_count) {
422 const_->addr = (sljit_uw)code_ptr;
423 const_ = const_->next;
427 } while (buf_ptr < buf_end);
432 if (label && label->size == word_count) {
433 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
434 label->size = code_ptr - code;
438 SLJIT_ASSERT(!label);
440 SLJIT_ASSERT(!const_);
441 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
442 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
444 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
447 jump = compiler->jumps;
450 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
451 buf_ptr = (sljit_ins *)jump->addr;
453 if (jump->flags & PATCH_B) {
454 if (jump->flags & IS_COND) {
455 if (!(jump->flags & PATCH_ABS_B)) {
456 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
457 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
458 *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
461 SLJIT_ASSERT(addr <= 0xffff);
462 *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
466 if (!(jump->flags & PATCH_ABS_B)) {
467 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
468 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
469 *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
472 SLJIT_ASSERT(addr <= 0x03ffffff);
473 *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
479 /* Set the fields of immediate loads. */
480 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
481 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
482 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
484 if (jump->flags & PATCH_ABS32) {
485 SLJIT_ASSERT(addr <= 0x7fffffff);
486 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
487 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
490 if (jump->flags & PATCH_ABS48) {
491 SLJIT_ASSERT(addr <= 0x7fffffffffff);
492 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
493 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
494 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
497 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
498 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
499 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
500 buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
506 compiler->error = SLJIT_ERR_COMPILED;
507 compiler->executable_offset = executable_offset;
508 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
510 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
512 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
513 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
514 if (((sljit_sw)code_ptr) & 0x4)
517 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
520 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
522 SLJIT_CACHE_FLUSH(code, code_ptr);
524 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
531 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
533 switch (feature_type) {
535 #ifdef SLJIT_IS_FPU_AVAILABLE
536 return SLJIT_IS_FPU_AVAILABLE;
538 /* Available by default. */
550 /* --------------------------------------------------------------------- */
552 /* --------------------------------------------------------------------- */
556 /* Creates an index in data_transfer_insts array. */
557 #define LOAD_DATA 0x01
559 #define SIGNED_DATA 0x04
561 #define WORD_DATA 0x00
562 #define BYTE_DATA 0x08
563 #define HALF_DATA 0x10
564 #define INT_DATA 0x18
565 /* Separates integer and floating point registers */
567 #define DOUBLE_DATA 0x20
569 #define MEM_MASK 0x7f
571 /* Other inp_flags. */
573 /* Integer opertion and set flags -> requires exts on 64 bit systems. */
574 #define ALT_SIGN_EXT 0x000100
575 /* This flag affects the RC() and OERC() macros. */
576 #define ALT_SET_FLAGS 0x000400
577 #define ALT_FORM1 0x001000
578 #define ALT_FORM2 0x002000
579 #define ALT_FORM3 0x004000
580 #define ALT_FORM4 0x008000
581 #define ALT_FORM5 0x010000
583 /* Source and destination is register. */
584 #define REG_DEST 0x000001
585 #define REG1_SOURCE 0x000002
586 #define REG2_SOURCE 0x000004
588 ALT_SIGN_EXT 0x000100
589 ALT_SET_FLAGS 0x000200
592 ALT_FORM5 0x010000 */
594 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
595 #include "sljitNativePPC_32.c"
597 #include "sljitNativePPC_64.c"
600 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
601 #define STACK_STORE STW
602 #define STACK_LOAD LWZ
604 #define STACK_STORE STD
605 #define STACK_LOAD LD
608 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
609 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
610 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
612 sljit_s32 args, i, tmp, offs;
615 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
616 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
618 FAIL_IF(push_inst(compiler, MFLR | D(0)));
619 offs = -(sljit_s32)(sizeof(sljit_sw));
620 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
622 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
623 for (i = SLJIT_S0; i >= tmp; i--) {
624 offs -= (sljit_s32)(sizeof(sljit_sw));
625 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
628 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
629 offs -= (sljit_s32)(sizeof(sljit_sw));
630 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
633 SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
635 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
636 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
638 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
641 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
643 args = get_arg_count(arg_types);
646 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
648 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
650 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
652 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
653 local_size = (local_size + 15) & ~0xf;
654 compiler->local_size = local_size;
656 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
657 if (local_size <= SIMM_MAX)
658 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
660 FAIL_IF(load_immediate(compiler, 0, -local_size));
661 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
664 if (local_size <= SIMM_MAX)
665 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
667 FAIL_IF(load_immediate(compiler, 0, -local_size));
668 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
672 return SLJIT_SUCCESS;
675 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
676 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
677 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
680 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
681 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
683 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
684 compiler->local_size = (local_size + 15) & ~0xf;
685 return SLJIT_SUCCESS;
688 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
690 sljit_s32 i, tmp, offs;
693 CHECK(check_sljit_emit_return(compiler, op, src, srcw));
695 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
697 if (compiler->local_size <= SIMM_MAX)
698 FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
700 FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
701 FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
704 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
705 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
707 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
710 offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
712 tmp = compiler->scratches;
713 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
714 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
715 offs += (sljit_s32)(sizeof(sljit_sw));
718 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
719 for (i = tmp; i <= SLJIT_S0; i++) {
720 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
721 offs += (sljit_s32)(sizeof(sljit_sw));
724 FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
725 SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
727 FAIL_IF(push_inst(compiler, MTLR | S(0)));
728 FAIL_IF(push_inst(compiler, BLR));
730 return SLJIT_SUCCESS;
736 /* --------------------------------------------------------------------- */
738 /* --------------------------------------------------------------------- */
740 /* s/l - store/load (1 bit)
741 i/x - immediate/indexed form
742 u/s - signed/unsigned (1 bit)
743 w/b/h/i - word/byte/half/int allowed (2 bit)
745 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
747 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
748 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
749 #define INT_ALIGNED 0x10000
752 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
753 #define ARCH_32_64(a, b) a
754 #define INST_CODE_AND_DST(inst, flags, reg) \
755 ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
757 #define ARCH_32_64(a, b) b
758 #define INST_CODE_AND_DST(inst, flags, reg) \
759 (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
762 static const sljit_ins data_transfer_insts[64 + 16] = {
764 /* -------- Integer -------- */
768 /* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
769 /* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
770 /* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
771 /* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
773 /* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
774 /* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
775 /* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
776 /* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
780 /* b u i s */ HI(38) /* stb */,
781 /* b u i l */ HI(34) /* lbz */,
782 /* b u x s */ HI(31) | LO(215) /* stbx */,
783 /* b u x l */ HI(31) | LO(87) /* lbzx */,
785 /* b s i s */ HI(38) /* stb */,
786 /* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
787 /* b s x s */ HI(31) | LO(215) /* stbx */,
788 /* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
792 /* h u i s */ HI(44) /* sth */,
793 /* h u i l */ HI(40) /* lhz */,
794 /* h u x s */ HI(31) | LO(407) /* sthx */,
795 /* h u x l */ HI(31) | LO(279) /* lhzx */,
797 /* h s i s */ HI(44) /* sth */,
798 /* h s i l */ HI(42) /* lha */,
799 /* h s x s */ HI(31) | LO(407) /* sthx */,
800 /* h s x l */ HI(31) | LO(343) /* lhax */,
804 /* i u i s */ HI(36) /* stw */,
805 /* i u i l */ HI(32) /* lwz */,
806 /* i u x s */ HI(31) | LO(151) /* stwx */,
807 /* i u x l */ HI(31) | LO(23) /* lwzx */,
809 /* i s i s */ HI(36) /* stw */,
810 /* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
811 /* i s x s */ HI(31) | LO(151) /* stwx */,
812 /* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
814 /* -------- Floating point -------- */
816 /* d i s */ HI(54) /* stfd */,
817 /* d i l */ HI(50) /* lfd */,
818 /* d x s */ HI(31) | LO(727) /* stfdx */,
819 /* d x l */ HI(31) | LO(599) /* lfdx */,
821 /* s i s */ HI(52) /* stfs */,
822 /* s i l */ HI(48) /* lfs */,
823 /* s x s */ HI(31) | LO(663) /* stfsx */,
824 /* s x l */ HI(31) | LO(535) /* lfsx */,
827 static const sljit_ins updated_data_transfer_insts[64] = {
829 /* -------- Integer -------- */
833 /* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
834 /* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
835 /* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
836 /* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
838 /* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
839 /* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
840 /* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
841 /* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
845 /* b u i s */ HI(39) /* stbu */,
846 /* b u i l */ HI(35) /* lbzu */,
847 /* b u x s */ HI(31) | LO(247) /* stbux */,
848 /* b u x l */ HI(31) | LO(119) /* lbzux */,
850 /* b s i s */ HI(39) /* stbu */,
851 /* b s i l */ 0 /* no such instruction */,
852 /* b s x s */ HI(31) | LO(247) /* stbux */,
853 /* b s x l */ 0 /* no such instruction */,
857 /* h u i s */ HI(45) /* sthu */,
858 /* h u i l */ HI(41) /* lhzu */,
859 /* h u x s */ HI(31) | LO(439) /* sthux */,
860 /* h u x l */ HI(31) | LO(311) /* lhzux */,
862 /* h s i s */ HI(45) /* sthu */,
863 /* h s i l */ HI(43) /* lhau */,
864 /* h s x s */ HI(31) | LO(439) /* sthux */,
865 /* h s x l */ HI(31) | LO(375) /* lhaux */,
869 /* i u i s */ HI(37) /* stwu */,
870 /* i u i l */ HI(33) /* lwzu */,
871 /* i u x s */ HI(31) | LO(183) /* stwux */,
872 /* i u x l */ HI(31) | LO(55) /* lwzux */,
874 /* i s i s */ HI(37) /* stwu */,
875 /* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
876 /* i s x s */ HI(31) | LO(183) /* stwux */,
877 /* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
879 /* -------- Floating point -------- */
881 /* d i s */ HI(55) /* stfdu */,
882 /* d i l */ HI(51) /* lfdu */,
883 /* d x s */ HI(31) | LO(759) /* stfdux */,
884 /* d x l */ HI(31) | LO(631) /* lfdux */,
886 /* s i s */ HI(53) /* stfsu */,
887 /* s i l */ HI(49) /* lfsu */,
888 /* s x s */ HI(31) | LO(695) /* stfsux */,
889 /* s x l */ HI(31) | LO(567) /* lfsux */,
894 /* Simple cases, (no caching is required). */
895 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
896 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
902 /* Should work when (arg & REG_MASK) == 0. */
903 SLJIT_ASSERT(A(0) == 0);
904 SLJIT_ASSERT(arg & SLJIT_MEM);
906 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
908 offs_reg = OFFS_REG(arg);
911 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
912 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1)));
914 FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));
919 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
921 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
922 SLJIT_ASSERT(!(inst & INT_ALIGNED));
925 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
928 inst = data_transfer_insts[inp_flags & MEM_MASK];
931 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
932 if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
933 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
935 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
936 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
940 if (argw <= SIMM_MAX && argw >= SIMM_MIN)
941 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
943 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
944 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
947 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
949 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
950 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
952 SLJIT_ASSERT(high_short);
955 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));
956 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
958 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
961 /* The rest is PPC-64 only. */
963 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
965 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
966 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
970 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
971 sljit_s32 dst, sljit_sw dstw,
972 sljit_s32 src1, sljit_sw src1w,
973 sljit_s32 src2, sljit_sw src2w)
975 /* arg1 goes to TMP_REG1 or src reg
976 arg2 goes to TMP_REG2, imm or src reg
977 result goes to TMP_REG2, so put result can use TMP_REG1. */
978 sljit_s32 dst_r = TMP_REG2;
981 sljit_s32 sugg_src2_r = TMP_REG2;
982 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
984 /* Destination check. */
985 if (SLOW_IS_REG(dst)) {
989 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
994 if (FAST_IS_REG(src1)) {
996 flags |= REG1_SOURCE;
998 else if (src1 & SLJIT_IMM) {
999 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1003 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1008 if (FAST_IS_REG(src2)) {
1010 flags |= REG2_SOURCE;
1012 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1015 else if (src2 & SLJIT_IMM) {
1016 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1017 src2_r = sugg_src2_r;
1020 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));
1021 src2_r = sugg_src2_r;
1024 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1026 if (!(dst & SLJIT_MEM))
1027 return SLJIT_SUCCESS;
1029 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1032 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1034 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1035 sljit_s32 int_op = op & SLJIT_I32_OP;
1039 CHECK(check_sljit_emit_op0(compiler, op));
1041 op = GET_OPCODE(op);
1043 case SLJIT_BREAKPOINT:
1045 return push_inst(compiler, NOP);
1048 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1049 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1050 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1051 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1053 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1054 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1056 case SLJIT_DIVMOD_UW:
1057 case SLJIT_DIVMOD_SW:
1058 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1059 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1060 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)));
1061 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1063 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1064 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1066 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1069 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1070 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));
1072 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1076 return SLJIT_SUCCESS;
1079 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1080 sljit_s32 src, sljit_sw srcw)
1082 if (!(src & OFFS_REG_MASK)) {
1083 if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
1084 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
1086 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1087 /* Works with SLJIT_MEM0() case as well. */
1088 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1094 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
1096 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1097 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
1099 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
1101 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1104 #define EMIT_MOV(type, type_flags, type_cast) \
1105 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)
1107 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1108 sljit_s32 dst, sljit_sw dstw,
1109 sljit_s32 src, sljit_sw srcw)
1111 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1112 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1115 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1116 ADJUST_LOCAL_OFFSET(dst, dstw);
1117 ADJUST_LOCAL_OFFSET(src, srcw);
1119 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
1120 if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
1121 return emit_prefetch(compiler, src, srcw);
1123 return SLJIT_SUCCESS;
1126 op = GET_OPCODE(op);
1127 if ((src & SLJIT_IMM) && srcw == 0)
1130 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1131 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1133 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1134 if (!TYPE_CAST_NEEDED(op))
1135 return SLJIT_SUCCESS;
1138 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1139 if (op_flags & SLJIT_I32_OP) {
1140 if (op < SLJIT_NOT) {
1141 if (src & SLJIT_MEM) {
1142 if (op == SLJIT_MOV_S32)
1145 else if (src & SLJIT_IMM) {
1146 if (op == SLJIT_MOV_U32)
1151 /* Most operations expect sign extended arguments. */
1152 flags |= INT_DATA | SIGNED_DATA;
1153 if (HAS_FLAGS(op_flags))
1154 flags |= ALT_SIGN_EXT;
1162 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1166 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1168 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1170 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1173 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1177 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1180 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1183 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1186 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1189 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1192 return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
1195 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1196 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1198 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1202 return SLJIT_SUCCESS;
1207 #define TEST_SL_IMM(src, srcw) \
1208 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1210 #define TEST_UL_IMM(src, srcw) \
1211 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1213 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1214 #define TEST_SH_IMM(src, srcw) \
1215 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1217 #define TEST_SH_IMM(src, srcw) \
1218 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1221 #define TEST_UH_IMM(src, srcw) \
1222 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
1224 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1225 #define TEST_ADD_IMM(src, srcw) \
1226 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1228 #define TEST_ADD_IMM(src, srcw) \
1232 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1233 #define TEST_UI_IMM(src, srcw) \
1234 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1236 #define TEST_UI_IMM(src, srcw) \
1240 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1241 sljit_s32 dst, sljit_sw dstw,
1242 sljit_s32 src1, sljit_sw src1w,
1243 sljit_s32 src2, sljit_sw src2w)
1245 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1248 CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1249 ADJUST_LOCAL_OFFSET(dst, dstw);
1250 ADJUST_LOCAL_OFFSET(src1, src1w);
1251 ADJUST_LOCAL_OFFSET(src2, src2w);
1253 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
1254 return SLJIT_SUCCESS;
1256 if ((src1 & SLJIT_IMM) && src1w == 0)
1258 if ((src2 & SLJIT_IMM) && src2w == 0)
1261 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1262 if (op & SLJIT_I32_OP) {
1263 /* Most operations expect sign extended arguments. */
1264 flags |= INT_DATA | SIGNED_DATA;
1265 if (src1 & SLJIT_IMM)
1266 src1w = (sljit_s32)(src1w);
1267 if (src2 & SLJIT_IMM)
1268 src2w = (sljit_s32)(src2w);
1270 flags |= ALT_SIGN_EXT;
1273 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1274 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1276 switch (GET_OPCODE(op)) {
1278 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1279 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1281 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1282 if (TEST_SL_IMM(src2, src2w)) {
1283 compiler->imm = src2w & 0xffff;
1284 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1286 if (TEST_SL_IMM(src1, src1w)) {
1287 compiler->imm = src1w & 0xffff;
1288 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1290 if (TEST_SH_IMM(src2, src2w)) {
1291 compiler->imm = (src2w >> 16) & 0xffff;
1292 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1294 if (TEST_SH_IMM(src1, src1w)) {
1295 compiler->imm = (src1w >> 16) & 0xffff;
1296 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1298 /* Range between -1 and -32768 is covered above. */
1299 if (TEST_ADD_IMM(src2, src2w)) {
1300 compiler->imm = src2w & 0xffffffff;
1301 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1303 if (TEST_ADD_IMM(src1, src1w)) {
1304 compiler->imm = src1w & 0xffffffff;
1305 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1308 if (HAS_FLAGS(op)) {
1309 if (TEST_SL_IMM(src2, src2w)) {
1310 compiler->imm = src2w & 0xffff;
1311 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1313 if (TEST_SL_IMM(src1, src1w)) {
1314 compiler->imm = src1w & 0xffff;
1315 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1318 return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
1321 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1324 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1325 if (dst == SLJIT_UNUSED) {
1326 if (TEST_UL_IMM(src2, src2w)) {
1327 compiler->imm = src2w & 0xffff;
1328 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1330 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1333 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1334 compiler->imm = src2w;
1335 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1337 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1340 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1341 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1343 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1344 if (TEST_SL_IMM(src2, -src2w)) {
1345 compiler->imm = (-src2w) & 0xffff;
1346 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1348 if (TEST_SL_IMM(src1, src1w)) {
1349 compiler->imm = src1w & 0xffff;
1350 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1352 if (TEST_SH_IMM(src2, -src2w)) {
1353 compiler->imm = ((-src2w) >> 16) & 0xffff;
1354 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1356 /* Range between -1 and -32768 is covered above. */
1357 if (TEST_ADD_IMM(src2, -src2w)) {
1358 compiler->imm = -src2w & 0xffffffff;
1359 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1363 if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
1364 if (TEST_SL_IMM(src2, src2w)) {
1365 compiler->imm = src2w & 0xffff;
1366 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1368 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1371 if (TEST_SL_IMM(src2, -src2w)) {
1372 compiler->imm = (-src2w) & 0xffff;
1373 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1375 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1376 return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1379 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1382 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1383 if (op & SLJIT_I32_OP)
1386 if (!HAS_FLAGS(op)) {
1387 if (TEST_SL_IMM(src2, src2w)) {
1388 compiler->imm = src2w & 0xffff;
1389 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1391 if (TEST_SL_IMM(src1, src1w)) {
1392 compiler->imm = src1w & 0xffff;
1393 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1397 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1398 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1403 /* Commutative unsigned operations. */
1404 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1405 if (TEST_UL_IMM(src2, src2w)) {
1406 compiler->imm = src2w;
1407 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1409 if (TEST_UL_IMM(src1, src1w)) {
1410 compiler->imm = src1w;
1411 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1413 if (TEST_UH_IMM(src2, src2w)) {
1414 compiler->imm = (src2w >> 16) & 0xffff;
1415 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1417 if (TEST_UH_IMM(src1, src1w)) {
1418 compiler->imm = (src1w >> 16) & 0xffff;
1419 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1422 if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
1423 /* Unlike or and xor, and resets unwanted bits as well. */
1424 if (TEST_UI_IMM(src2, src2w)) {
1425 compiler->imm = src2w;
1426 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1428 if (TEST_UI_IMM(src1, src1w)) {
1429 compiler->imm = src1w;
1430 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1433 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1438 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1439 if (op & SLJIT_I32_OP)
1442 if (src2 & SLJIT_IMM) {
1443 compiler->imm = src2w;
1444 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1446 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1449 return SLJIT_SUCCESS;
1452 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1454 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1455 return reg_map[reg];
1458 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1460 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1461 return freg_map[reg];
1464 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1465 void *instruction, sljit_s32 size)
1468 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1470 return push_inst(compiler, *(sljit_ins*)instruction);
1473 /* --------------------------------------------------------------------- */
1474 /* Floating point operators */
1475 /* --------------------------------------------------------------------- */
1477 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
1478 #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
1480 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1481 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1483 #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1485 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1486 #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1487 #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1489 #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1490 #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1493 #endif /* SLJIT_CONFIG_PPC_64 */
1495 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1496 sljit_s32 dst, sljit_sw dstw,
1497 sljit_s32 src, sljit_sw srcw)
1499 if (src & SLJIT_MEM) {
1500 /* We can ignore the temporary data store on the stack from caching point of view. */
1501 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1505 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1506 op = GET_OPCODE(op);
1507 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1509 if (op == SLJIT_CONV_SW_FROM_F64) {
1510 if (FAST_IS_REG(dst)) {
1511 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1512 return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1514 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
1517 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1520 if (FAST_IS_REG(dst)) {
1521 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1522 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1523 return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1526 SLJIT_ASSERT(dst & SLJIT_MEM);
1528 if (dst & OFFS_REG_MASK) {
1531 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1532 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
1534 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1539 dstw = OFFS_REG(dst);
1542 if ((dst & REG_MASK) && !dstw) {
1543 dstw = dst & REG_MASK;
1547 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1548 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1553 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1556 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1557 sljit_s32 dst, sljit_sw dstw,
1558 sljit_s32 src, sljit_sw srcw)
1560 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1562 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1564 if (src & SLJIT_IMM) {
1565 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1566 srcw = (sljit_s32)srcw;
1567 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1570 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1571 if (FAST_IS_REG(src))
1572 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1574 FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1578 if (FAST_IS_REG(src)) {
1579 FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1580 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1583 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1585 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1587 if (dst & SLJIT_MEM)
1588 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1589 if (op & SLJIT_F32_OP)
1590 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1591 return SLJIT_SUCCESS;
1595 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1596 sljit_s32 invert_sign = 1;
1598 if (src & SLJIT_IMM) {
1599 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
1603 else if (!FAST_IS_REG(src)) {
1604 FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1608 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1609 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1610 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1611 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1612 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1613 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1615 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1616 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));
1617 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1618 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1619 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1620 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1621 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1623 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1625 if (dst & SLJIT_MEM)
1626 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1627 if (op & SLJIT_F32_OP)
1628 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1629 return SLJIT_SUCCESS;
1634 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1635 sljit_s32 src1, sljit_sw src1w,
1636 sljit_s32 src2, sljit_sw src2w)
1638 if (src1 & SLJIT_MEM) {
1639 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1643 if (src2 & SLJIT_MEM) {
1644 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1648 return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
1651 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1652 sljit_s32 dst, sljit_sw dstw,
1653 sljit_s32 src, sljit_sw srcw)
1659 SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1660 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1662 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1665 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1667 if (src & SLJIT_MEM) {
1668 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
1672 switch (GET_OPCODE(op)) {
1673 case SLJIT_CONV_F64_FROM_F32:
1675 if (op & SLJIT_F32_OP) {
1676 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1682 if (dst_r != TMP_FREG1)
1683 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1689 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1692 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1696 if (dst & SLJIT_MEM)
1697 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
1698 return SLJIT_SUCCESS;
1701 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1702 sljit_s32 dst, sljit_sw dstw,
1703 sljit_s32 src1, sljit_sw src1w,
1704 sljit_s32 src2, sljit_sw src2w)
1709 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1710 ADJUST_LOCAL_OFFSET(dst, dstw);
1711 ADJUST_LOCAL_OFFSET(src1, src1w);
1712 ADJUST_LOCAL_OFFSET(src2, src2w);
1714 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1716 if (src1 & SLJIT_MEM) {
1717 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1721 if (src2 & SLJIT_MEM) {
1722 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1726 switch (GET_OPCODE(op)) {
1728 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
1732 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
1736 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
1740 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
1744 if (dst & SLJIT_MEM)
1745 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
1747 return SLJIT_SUCCESS;
1752 /* --------------------------------------------------------------------- */
1753 /* Other instructions */
1754 /* --------------------------------------------------------------------- */
1756 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1759 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1760 ADJUST_LOCAL_OFFSET(dst, dstw);
1762 if (FAST_IS_REG(dst))
1763 return push_inst(compiler, MFLR | D(dst));
1766 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
1767 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
1770 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
1773 CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
1774 ADJUST_LOCAL_OFFSET(src, srcw);
1776 if (FAST_IS_REG(src))
1777 FAIL_IF(push_inst(compiler, MTLR | S(src)));
1779 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
1780 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
1783 return push_inst(compiler, BLR);
1786 /* --------------------------------------------------------------------- */
1787 /* Conditional instructions */
1788 /* --------------------------------------------------------------------- */
1790 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1792 struct sljit_label *label;
1795 CHECK_PTR(check_sljit_emit_label(compiler));
1797 if (compiler->last_label && compiler->last_label->size == compiler->size)
1798 return compiler->last_label;
1800 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1801 PTR_FAIL_IF(!label);
1802 set_label(label, compiler);
1806 static sljit_ins get_bo_bi_flags(sljit_s32 type)
1810 return (12 << 21) | (2 << 16);
1812 case SLJIT_NOT_EQUAL:
1813 return (4 << 21) | (2 << 16);
1816 case SLJIT_SIG_LESS:
1817 return (12 << 21) | (0 << 16);
1819 case SLJIT_GREATER_EQUAL:
1820 case SLJIT_SIG_GREATER_EQUAL:
1821 return (4 << 21) | (0 << 16);
1824 case SLJIT_SIG_GREATER:
1825 return (12 << 21) | (1 << 16);
1827 case SLJIT_LESS_EQUAL:
1828 case SLJIT_SIG_LESS_EQUAL:
1829 return (4 << 21) | (1 << 16);
1831 case SLJIT_LESS_F64:
1832 return (12 << 21) | ((4 + 0) << 16);
1834 case SLJIT_GREATER_EQUAL_F64:
1835 return (4 << 21) | ((4 + 0) << 16);
1837 case SLJIT_GREATER_F64:
1838 return (12 << 21) | ((4 + 1) << 16);
1840 case SLJIT_LESS_EQUAL_F64:
1841 return (4 << 21) | ((4 + 1) << 16);
1843 case SLJIT_OVERFLOW:
1844 case SLJIT_MUL_OVERFLOW:
1845 return (12 << 21) | (3 << 16);
1847 case SLJIT_NOT_OVERFLOW:
1848 case SLJIT_MUL_NOT_OVERFLOW:
1849 return (4 << 21) | (3 << 16);
1851 case SLJIT_EQUAL_F64:
1852 return (12 << 21) | ((4 + 2) << 16);
1854 case SLJIT_NOT_EQUAL_F64:
1855 return (4 << 21) | ((4 + 2) << 16);
1857 case SLJIT_UNORDERED_F64:
1858 return (12 << 21) | ((4 + 3) << 16);
1860 case SLJIT_ORDERED_F64:
1861 return (4 << 21) | ((4 + 3) << 16);
1864 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
1869 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
1871 struct sljit_jump *jump;
1872 sljit_ins bo_bi_flags;
1875 CHECK_PTR(check_sljit_emit_jump(compiler, type));
1877 bo_bi_flags = get_bo_bi_flags(type & 0xff);
1881 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1883 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
1886 /* In PPC, we don't need to touch the arguments. */
1887 if (type < SLJIT_JUMP)
1888 jump->flags |= IS_COND;
1889 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
1890 if (type >= SLJIT_CALL)
1891 jump->flags |= IS_CALL;
1894 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
1895 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
1896 jump->addr = compiler->size;
1897 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
1901 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
1902 sljit_s32 arg_types)
1905 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
1907 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1908 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
1911 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1912 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1913 compiler->skip_checks = 1;
1916 return sljit_emit_jump(compiler, type);
1919 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
1921 struct sljit_jump *jump = NULL;
1925 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
1926 ADJUST_LOCAL_OFFSET(src, srcw);
1928 if (FAST_IS_REG(src)) {
1929 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
1930 if (type >= SLJIT_CALL) {
1931 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
1932 src_r = TMP_CALL_REG;
1939 } else if (src & SLJIT_IMM) {
1940 /* These jumps are converted to jump/call instructions when possible. */
1941 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1943 set_jump(jump, compiler, JUMP_ADDR);
1944 jump->u.target = srcw;
1945 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
1946 if (type >= SLJIT_CALL)
1947 jump->flags |= IS_CALL;
1949 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
1950 src_r = TMP_CALL_REG;
1953 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
1954 src_r = TMP_CALL_REG;
1957 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
1959 jump->addr = compiler->size;
1960 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
1963 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
1964 sljit_s32 arg_types,
1965 sljit_s32 src, sljit_sw srcw)
1968 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
1970 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1971 if (src & SLJIT_MEM) {
1972 ADJUST_LOCAL_OFFSET(src, srcw);
1973 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
1977 FAIL_IF(call_with_args(compiler, arg_types, &src));
1980 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1981 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1982 compiler->skip_checks = 1;
1985 return sljit_emit_ijump(compiler, type, src, srcw);
1988 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
1989 sljit_s32 dst, sljit_sw dstw,
1992 sljit_s32 reg, input_flags, cr_bit, invert;
1993 sljit_s32 saved_op = op;
1994 sljit_sw saved_dstw = dstw;
1997 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
1998 ADJUST_LOCAL_OFFSET(dst, dstw);
2000 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2001 input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
2003 input_flags = WORD_DATA;
2006 op = GET_OPCODE(op);
2007 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2009 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2010 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
2015 switch (type & 0xff) {
2017 case SLJIT_SIG_LESS:
2020 case SLJIT_GREATER_EQUAL:
2021 case SLJIT_SIG_GREATER_EQUAL:
2026 case SLJIT_SIG_GREATER:
2030 case SLJIT_LESS_EQUAL:
2031 case SLJIT_SIG_LESS_EQUAL:
2040 case SLJIT_NOT_EQUAL:
2045 case SLJIT_OVERFLOW:
2046 case SLJIT_MUL_OVERFLOW:
2050 case SLJIT_NOT_OVERFLOW:
2051 case SLJIT_MUL_NOT_OVERFLOW:
2056 case SLJIT_LESS_F64:
2060 case SLJIT_GREATER_EQUAL_F64:
2065 case SLJIT_GREATER_F64:
2069 case SLJIT_LESS_EQUAL_F64:
2074 case SLJIT_EQUAL_F64:
2078 case SLJIT_NOT_EQUAL_F64:
2083 case SLJIT_UNORDERED_F64:
2087 case SLJIT_ORDERED_F64:
2093 SLJIT_UNREACHABLE();
2097 FAIL_IF(push_inst(compiler, MFCR | D(reg)));
2098 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
2101 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2103 if (op < SLJIT_ADD) {
2104 if (!(dst & SLJIT_MEM))
2105 return SLJIT_SUCCESS;
2106 return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
2109 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2110 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2111 compiler->skip_checks = 1;
2113 if (dst & SLJIT_MEM)
2114 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2115 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2118 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2120 sljit_s32 src, sljit_sw srcw)
2123 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2125 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2128 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2130 sljit_s32 mem, sljit_sw memw)
2132 sljit_s32 mem_flags;
2136 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2138 if (type & SLJIT_MEM_POST)
2139 return SLJIT_ERR_UNSUPPORTED;
2141 switch (type & 0xff) {
2144 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2148 mem_flags = WORD_DATA;
2151 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2153 mem_flags = INT_DATA;
2157 mem_flags = INT_DATA;
2159 if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) {
2160 if (mem & OFFS_REG_MASK)
2161 mem_flags |= SIGNED_DATA;
2163 return SLJIT_ERR_UNSUPPORTED;
2170 mem_flags = BYTE_DATA;
2174 mem_flags = HALF_DATA;
2178 mem_flags = HALF_DATA | SIGNED_DATA;
2182 SLJIT_UNREACHABLE();
2183 mem_flags = WORD_DATA;
2187 if (!(type & SLJIT_MEM_STORE))
2188 mem_flags |= LOAD_DATA;
2190 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2192 return SLJIT_ERR_UNSUPPORTED;
2194 if (type & SLJIT_MEM_SUPP)
2195 return SLJIT_SUCCESS;
2197 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2198 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
2201 if (memw > SIMM_MAX || memw < SIMM_MIN)
2202 return SLJIT_ERR_UNSUPPORTED;
2204 inst = updated_data_transfer_insts[mem_flags];
2206 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2207 if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
2208 return SLJIT_ERR_UNSUPPORTED;
2211 if (type & SLJIT_MEM_SUPP)
2212 return SLJIT_SUCCESS;
2214 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
2217 if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
2218 return push_inst(compiler, EXTSB | S(reg) | A(reg));
2219 return SLJIT_SUCCESS;
2222 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
2224 sljit_s32 mem, sljit_sw memw)
2226 sljit_s32 mem_flags;
2230 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
2232 if (type & SLJIT_MEM_POST)
2233 return SLJIT_ERR_UNSUPPORTED;
2235 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2237 return SLJIT_ERR_UNSUPPORTED;
2240 if (memw > SIMM_MAX || memw < SIMM_MIN)
2241 return SLJIT_ERR_UNSUPPORTED;
2244 if (type & SLJIT_MEM_SUPP)
2245 return SLJIT_SUCCESS;
2247 mem_flags = FLOAT_DATA(type);
2249 if (!(type & SLJIT_MEM_STORE))
2250 mem_flags |= LOAD_DATA;
2252 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2253 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2254 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
2257 inst = updated_data_transfer_insts[mem_flags];
2258 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
2261 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2263 struct sljit_const *const_;
2267 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2268 ADJUST_LOCAL_OFFSET(dst, dstw);
2270 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2271 PTR_FAIL_IF(!const_);
2272 set_const(const_, compiler);
2274 reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
2276 PTR_FAIL_IF(emit_const(compiler, reg, init_value));
2278 if (dst & SLJIT_MEM)
2279 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));