Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
9913 views
/*1* Stack-less Just-In-Time compiler2*3* Copyright Zoltan Herczeg ([email protected]). All rights reserved.4*5* Redistribution and use in source and binary forms, with or without modification, are6* permitted provided that the following conditions are met:7*8* 1. Redistributions of source code must retain the above copyright notice, this list of9* conditions and the following disclaimer.10*11* 2. Redistributions in binary form must reproduce the above copyright notice, this list12* of conditions and the following disclaimer in the documentation and/or other materials13* provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT18* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED20* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR21* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN22* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN23* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)27{28return "PowerPC" SLJIT_CPUINFO;29}3031/* Length of an instruction word.32Both for ppc-32 and ppc-64. */33typedef sljit_u32 sljit_ins;3435#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \36|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)37#define SLJIT_PPC_STACK_FRAME_V2 138#endif3940#ifdef _AIX41#include <sys/cache.h>42#endif4344#if (defined _CALL_ELF && _CALL_ELF == 2)45#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 146#endif4748#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)4950static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)51{52#ifdef _AIX53_sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));54#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)55# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)56/* Cache flush for POWER architecture. */57while (from < to) {58__asm__ volatile (59"clf 0, %0\n"60"dcs\n"61: : "r"(from)62);63from++;64}65__asm__ volatile ( "ics" );66# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)67# error "Cache flush is not implemented for PowerPC/POWER common mode."68# else69/* Cache flush for PowerPC architecture. */70while (from < to) {71__asm__ volatile (72"dcbf 0, %0\n"73"sync\n"74"icbi 0, %0\n"75: : "r"(from)76);77from++;78}79__asm__ volatile ( "isync" );80# endif81# ifdef __xlc__82# warning "This file may fail to compile if -qfuncsect is used"83# endif84#elif defined(__xlc__)85#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"86#else87#error "This platform requires a cache flush implementation."88#endif /* _AIX */89}9091#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */9293#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)94#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)95#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)9697#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)98#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)99#else100#define TMP_CALL_REG TMP_REG1101#endif102103#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)104#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)105106static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {1070, 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, 12108};109110static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {1110, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13112};113114/* --------------------------------------------------------------------- */115/* Instrucion forms */116/* --------------------------------------------------------------------- */117#define D(d) ((sljit_ins)reg_map[d] << 21)118#define S(s) ((sljit_ins)reg_map[s] << 21)119#define A(a) ((sljit_ins)reg_map[a] << 16)120#define B(b) ((sljit_ins)reg_map[b] << 11)121#define C(c) ((sljit_ins)reg_map[c] << 6)122#define FD(fd) ((sljit_ins)freg_map[fd] << 21)123#define FS(fs) ((sljit_ins)freg_map[fs] << 21)124#define FA(fa) ((sljit_ins)freg_map[fa] << 16)125#define FB(fb) ((sljit_ins)freg_map[fb] << 11)126#define FC(fc) ((sljit_ins)freg_map[fc] << 6)127#define IMM(imm) ((sljit_ins)(imm) & 0xffff)128#define CRD(d) ((sljit_ins)(d) << 21)129130/* Instruction bit sections.131OE and Rc flag (see ALT_SET_FLAGS). */132#define OE(flags) ((flags) & ALT_SET_FLAGS)133/* Rc flag (see ALT_SET_FLAGS). */134#define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10)135#define HI(opcode) ((sljit_ins)(opcode) << 26)136#define LO(opcode) ((sljit_ins)(opcode) << 1)137138#define ADD (HI(31) | LO(266))139#define ADDC (HI(31) | LO(10))140#define ADDE (HI(31) | LO(138))141#define ADDI (HI(14))142#define ADDIC (HI(13))143#define ADDIS (HI(15))144#define ADDME (HI(31) | LO(234))145#define AND (HI(31) | LO(28))146#define ANDI (HI(28))147#define ANDIS (HI(29))148#define Bx (HI(18))149#define BCx (HI(16))150#define BCCTR (HI(19) | LO(528) | (3 << 11))151#define BLR (HI(19) | LO(16) | (0x14 << 21))152#if defined(_ARCH_PWR10) && _ARCH_PWR10153#define BRD (HI(31) | LO(187))154#endif /* POWER10 */155#define CNTLZD (HI(31) | LO(58))156#define CNTLZW (HI(31) | LO(26))157#define CMP (HI(31) | LO(0))158#define CMPI (HI(11))159#define CMPL (HI(31) | LO(32))160#define CMPLI (HI(10))161#define CROR (HI(19) | LO(449))162#define DCBT (HI(31) | LO(278))163#define DIVD (HI(31) | LO(489))164#define DIVDU (HI(31) | LO(457))165#define DIVW (HI(31) | LO(491))166#define DIVWU (HI(31) | LO(459))167#define EXTSB (HI(31) | LO(954))168#define EXTSH (HI(31) | LO(922))169#define EXTSW (HI(31) | LO(986))170#define FABS (HI(63) | LO(264))171#define FADD (HI(63) | LO(21))172#define FADDS (HI(59) | LO(21))173#define FCFID (HI(63) | LO(846))174#define FCMPU (HI(63) | LO(0))175#define FCTIDZ (HI(63) | LO(815))176#define FCTIWZ (HI(63) | LO(15))177#define FDIV (HI(63) | LO(18))178#define FDIVS (HI(59) | LO(18))179#define FMR (HI(63) | LO(72))180#define FMUL (HI(63) | LO(25))181#define FMULS (HI(59) | LO(25))182#define FNEG (HI(63) | LO(40))183#define FRSP (HI(63) | LO(12))184#define FSUB (HI(63) | LO(20))185#define FSUBS (HI(59) | LO(20))186#define LD (HI(58) | 0)187#define LFD (HI(50))188#define LFS (HI(48))189#define LDARX (HI(31) | LO(84))190#if defined(_ARCH_PWR7) && _ARCH_PWR7191#define LDBRX (HI(31) | LO(532))192#endif /* POWER7 */193#define LHBRX (HI(31) | LO(790))194#define LWARX (HI(31) | LO(20))195#define LWBRX (HI(31) | LO(534))196#define LWZ (HI(32))197#define MFCR (HI(31) | LO(19))198#define MFLR (HI(31) | LO(339) | 0x80000)199#define MFXER (HI(31) | LO(339) | 0x10000)200#define MTCTR (HI(31) | LO(467) | 0x90000)201#define MTLR (HI(31) | LO(467) | 0x80000)202#define MTXER (HI(31) | LO(467) | 0x10000)203#define MULHD (HI(31) | LO(73))204#define MULHDU (HI(31) | LO(9))205#define MULHW (HI(31) | LO(75))206#define MULHWU (HI(31) | LO(11))207#define MULLD (HI(31) | LO(233))208#define MULLI (HI(7))209#define MULLW (HI(31) | LO(235))210#define NEG (HI(31) | LO(104))211#define NOP (HI(24))212#define NOR (HI(31) | LO(124))213#define OR (HI(31) | LO(444))214#define ORI (HI(24))215#define ORIS (HI(25))216#define RLDCL (HI(30) | LO(8))217#define RLDICL (HI(30) | LO(0 << 1))218#define RLDICR (HI(30) | LO(1 << 1))219#define RLDIMI (HI(30) | LO(3 << 1))220#define RLWIMI (HI(20))221#define RLWINM (HI(21))222#define RLWNM (HI(23))223#define SLD (HI(31) | LO(27))224#define SLW (HI(31) | LO(24))225#define SRAD (HI(31) | LO(794))226#define SRADI (HI(31) | LO(413 << 1))227#define SRAW (HI(31) | LO(792))228#define SRAWI (HI(31) | LO(824))229#define SRD (HI(31) | LO(539))230#define SRW (HI(31) | LO(536))231#define STD (HI(62) | 0)232#if defined(_ARCH_PWR7) && _ARCH_PWR7233#define STDBRX (HI(31) | LO(660))234#endif /* POWER7 */235#define STDCX (HI(31) | LO(214))236#define STDU (HI(62) | 1)237#define STDUX (HI(31) | LO(181))238#define STFD (HI(54))239#define STFIWX (HI(31) | LO(983))240#define STFS (HI(52))241#define STHBRX (HI(31) | LO(918))242#define STW (HI(36))243#define STWBRX (HI(31) | LO(662))244#define STWCX (HI(31) | LO(150))245#define STWU (HI(37))246#define STWUX (HI(31) | LO(183))247#define SUBF (HI(31) | LO(40))248#define SUBFC (HI(31) | LO(8))249#define SUBFE (HI(31) | LO(136))250#define SUBFIC (HI(8))251#define SYNC (HI(31) | LO(598))252#define XOR (HI(31) | LO(316))253#define XORI (HI(26))254#define XORIS (HI(27))255256#define SIMM_MAX (0x7fff)257#define SIMM_MIN (-0x8000)258#define UIMM_MAX (0xffff)259260/* Shift helpers. */261#define RLWI_SH(sh) ((sljit_ins)(sh) << 11)262#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1))263#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4))264#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))265#define RLDI_ME(me) RLDI_MB(me)266267#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift)))268#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift)))269/* shift > 0 */270#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31))271#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift))272273#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)274#define SLWI_W(shift) SLWI(shift)275#define TMP_MEM_OFFSET (2 * sizeof(sljit_sw))276#else /* !SLJIT_CONFIG_PPC_32 */277#define SLWI_W(shift) SLDI(shift)278#define TMP_MEM_OFFSET (6 * sizeof(sljit_sw))279#endif /* SLJIT_CONFIG_PPC_32 */280281#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)282#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET)283#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32))284#define LWBRX_FIRST_REG S(TMP_REG1)285#define LWBRX_SECOND_REG S(dst)286#else /* !SLJIT_LITTLE_ENDIAN */287#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32))288#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET)289#define LWBRX_FIRST_REG S(dst)290#define LWBRX_SECOND_REG S(TMP_REG1)291#endif /* SLJIT_LITTLE_ENDIAN */292293#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)294SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)295{296sljit_uw* ptrs;297298if (func_ptr)299*func_ptr = (void*)context;300301ptrs = (sljit_uw*)func;302context->addr = addr ? addr : ptrs[0];303context->r2 = ptrs[1];304context->r11 = ptrs[2];305}306#endif307308static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)309{310sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));311FAIL_IF(!ptr);312*ptr = ins;313compiler->size++;314return SLJIT_SUCCESS;315}316317static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)318{319sljit_sw diff;320sljit_uw target_addr;321sljit_uw jump_addr = (sljit_uw)code_ptr;322sljit_uw orig_addr = jump->addr;323SLJIT_UNUSED_ARG(executable_offset);324325jump->addr = jump_addr;326#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)327if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))328goto exit;329#else330if (jump->flags & SLJIT_REWRITABLE_JUMP)331goto exit;332#endif333334if (jump->flags & JUMP_ADDR)335target_addr = jump->u.target;336else {337SLJIT_ASSERT(jump->u.label != NULL);338target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;339340if (jump->u.label->size > orig_addr)341jump_addr = (sljit_uw)(code + orig_addr);342}343344#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)345if (jump->flags & IS_CALL)346goto keep_address;347#endif348349diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);350351if (jump->flags & IS_COND) {352if (diff <= 0x7fff && diff >= -0x8000) {353jump->flags |= PATCH_B;354return code_ptr;355}356if (target_addr <= 0xffff) {357jump->flags |= PATCH_B | PATCH_ABS_B;358return code_ptr;359}360361diff -= SSIZE_OF(ins);362}363364if (diff <= 0x01ffffff && diff >= -0x02000000) {365jump->flags |= PATCH_B;366} else if (target_addr <= 0x01ffffff) {367jump->flags |= PATCH_B | PATCH_ABS_B;368}369370if (jump->flags & PATCH_B) {371if (!(jump->flags & IS_COND))372return code_ptr;373374code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);375code_ptr[1] = Bx;376jump->addr += sizeof(sljit_ins);377jump->flags -= IS_COND;378return code_ptr + 1;379}380381#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)382#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)383keep_address:384#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */385if (target_addr < 0x80000000l) {386jump->flags |= PATCH_ABS32;387code_ptr[2] = MTCTR | S(TMP_CALL_REG);388code_ptr[3] = code_ptr[0];389return code_ptr + 3;390}391392if (target_addr < 0x800000000000l) {393jump->flags |= PATCH_ABS48;394code_ptr[4] = MTCTR | S(TMP_CALL_REG);395code_ptr[5] = code_ptr[0];396return code_ptr + 5;397}398#endif /* SLJIT_CONFIG_PPC_64 */399400exit:401#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)402code_ptr[2] = MTCTR | S(TMP_CALL_REG);403code_ptr[3] = code_ptr[0];404#else /* !SLJIT_CONFIG_PPC_32 */405code_ptr[5] = MTCTR | S(TMP_CALL_REG);406code_ptr[6] = code_ptr[0];407#endif /* SLJIT_CONFIG_PPC_32 */408return code_ptr + JUMP_MAX_SIZE - 1;409}410411#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)412413static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)414{415sljit_uw addr;416SLJIT_UNUSED_ARG(executable_offset);417418SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));419if (jump->flags & JUMP_ADDR)420addr = jump->u.target;421else422addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);423424if (addr < 0x80000000l) {425SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));426jump->flags |= PATCH_ABS32;427return 1;428}429430if (addr < 0x800000000000l) {431SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));432jump->flags |= PATCH_ABS48;433return 3;434}435436SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));437return 4;438}439440#endif /* SLJIT_CONFIG_PPC_64 */441442static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)443{444sljit_uw flags = jump->flags;445sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;446sljit_ins *ins = (sljit_ins*)jump->addr;447sljit_s32 reg;448SLJIT_UNUSED_ARG(executable_offset);449450if (flags & PATCH_B) {451if (flags & IS_COND) {452if (!(flags & PATCH_ABS_B)) {453addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);454SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);455ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001);456} else {457SLJIT_ASSERT(addr <= 0xffff);458ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001);459}460return;461}462463if (!(flags & PATCH_ABS_B)) {464addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);465SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);466ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1);467} else {468SLJIT_ASSERT(addr <= 0x03ffffff);469ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1);470}471return;472}473474reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG;475476#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)477ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);478ins[1] = ORI | S(reg) | A(reg) | IMM(addr);479#else /* !SLJIT_CONFIG_PPC_32 */480481/* The TMP_ZERO cannot be used because it is restored for tail calls. */482if (flags & PATCH_ABS32) {483SLJIT_ASSERT(addr < 0x80000000l);484ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);485ins[1] = ORI | S(reg) | A(reg) | IMM(addr);486return;487}488489if (flags & PATCH_ABS48) {490SLJIT_ASSERT(addr < 0x800000000000l);491ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32);492ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16);493ins[2] = SLDI(16) | S(reg) | A(reg);494ins[3] = ORI | S(reg) | A(reg) | IMM(addr);495return;496}497498ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48);499ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32);500ins[2] = SLDI(32) | S(reg) | A(reg);501ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16);502ins[4] = ORI | S(reg) | A(reg) | IMM(addr);503#endif /* SLJIT_CONFIG_PPC_32 */504}505506static void reduce_code_size(struct sljit_compiler *compiler)507{508struct sljit_label *label;509struct sljit_jump *jump;510struct sljit_const *const_;511SLJIT_NEXT_DEFINE_TYPES;512sljit_uw total_size;513sljit_uw size_reduce = 0;514sljit_sw diff;515516label = compiler->labels;517jump = compiler->jumps;518const_ = compiler->consts;519SLJIT_NEXT_INIT_TYPES();520521while (1) {522SLJIT_GET_NEXT_MIN();523524if (next_min_addr == SLJIT_MAX_ADDRESS)525break;526527if (next_min_addr == next_label_size) {528label->size -= size_reduce;529530label = label->next;531next_label_size = SLJIT_GET_NEXT_SIZE(label);532}533534if (next_min_addr == next_const_addr) {535const_->addr -= size_reduce;536const_ = const_->next;537next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);538continue;539}540541if (next_min_addr != next_jump_addr)542continue;543544jump->addr -= size_reduce;545if (!(jump->flags & JUMP_MOV_ADDR)) {546total_size = JUMP_MAX_SIZE - 1;547548if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {549if (jump->flags & JUMP_ADDR) {550if (jump->u.target <= 0x01ffffff)551total_size = 1 - 1;552#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)553else if (jump->u.target < 0x80000000l)554total_size = 4 - 1;555else if (jump->u.target < 0x800000000000l)556total_size = 6 - 1;557#endif /* SLJIT_CONFIG_PPC_64 */558} else {559/* Unit size: instruction. */560diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;561if (jump->u.label->size > jump->addr) {562SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);563diff -= (sljit_sw)size_reduce;564}565566if (jump->flags & IS_COND) {567if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins)))568total_size = 1 - 1;569else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins)))570total_size = 2 - 1;571} else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))572total_size = 1 - 1;573}574}575576size_reduce += (JUMP_MAX_SIZE - 1) - total_size;577jump->flags |= total_size << JUMP_SIZE_SHIFT;578#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)579} else {580total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;581582if (jump->flags & JUMP_ADDR) {583if (jump->u.target < 0x80000000l) {584total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;585size_reduce += 3;586} else if (jump->u.target < 0x800000000000l) {587total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;588size_reduce += 1;589}590}591jump->flags |= total_size;592#endif /* SLJIT_CONFIG_PPC_64 */593}594595jump = jump->next;596next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);597}598599compiler->size -= size_reduce;600}601602SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)603{604struct sljit_memory_fragment *buf;605sljit_ins *code;606sljit_ins *code_ptr;607sljit_ins *buf_ptr;608sljit_ins *buf_end;609sljit_uw word_count;610#if (defined SLJIT_DEBUG && SLJIT_DEBUG)611sljit_uw jump_addr;612#endif613SLJIT_NEXT_DEFINE_TYPES;614sljit_sw executable_offset;615616struct sljit_label *label;617struct sljit_jump *jump;618struct sljit_const *const_;619620CHECK_ERROR_PTR();621CHECK_PTR(check_sljit_generate_code(compiler));622623reduce_code_size(compiler);624625#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)626/* add to compiler->size additional instruction space to hold the trampoline and padding */627#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)628compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));629#else630compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));631#endif632#endif633code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);634PTR_FAIL_WITH_EXEC_IF(code);635636reverse_buf(compiler);637buf = compiler->buf;638639code_ptr = code;640word_count = 0;641label = compiler->labels;642jump = compiler->jumps;643const_ = compiler->consts;644SLJIT_NEXT_INIT_TYPES();645SLJIT_GET_NEXT_MIN();646647do {648buf_ptr = (sljit_ins*)buf->memory;649buf_end = buf_ptr + (buf->used_size >> 2);650do {651*code_ptr = *buf_ptr++;652if (next_min_addr == word_count) {653SLJIT_ASSERT(!label || label->size >= word_count);654SLJIT_ASSERT(!jump || jump->addr >= word_count);655SLJIT_ASSERT(!const_ || const_->addr >= word_count);656657/* These structures are ordered by their address. */658if (next_min_addr == next_label_size) {659/* Just recording the address. */660label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);661label->size = (sljit_uw)(code_ptr - code);662label = label->next;663next_label_size = SLJIT_GET_NEXT_SIZE(label);664}665666if (next_min_addr == next_jump_addr) {667if (!(jump->flags & JUMP_MOV_ADDR)) {668word_count += jump->flags >> JUMP_SIZE_SHIFT;669#if (defined SLJIT_DEBUG && SLJIT_DEBUG)670jump_addr = (sljit_uw)code_ptr;671#endif672code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);673SLJIT_ASSERT(((sljit_uw)code_ptr - jump_addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));674} else {675jump->addr = (sljit_uw)code_ptr;676#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)677word_count += jump->flags >> JUMP_SIZE_SHIFT;678code_ptr += mov_addr_get_length(jump, code, executable_offset);679#else /* !SLJIT_CONFIG_PPC_64 */680word_count++;681code_ptr++;682#endif /* SLJIT_CONFIG_PPC_64 */683}684jump = jump->next;685next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);686} else if (next_min_addr == next_const_addr) {687const_->addr = (sljit_uw)code_ptr;688const_ = const_->next;689next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);690}691692SLJIT_GET_NEXT_MIN();693}694code_ptr++;695word_count++;696} while (buf_ptr < buf_end);697698buf = buf->next;699} while (buf);700701if (label && label->size == word_count) {702label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);703label->size = (sljit_uw)(code_ptr - code);704label = label->next;705}706707SLJIT_ASSERT(!label);708SLJIT_ASSERT(!jump);709SLJIT_ASSERT(!const_);710711#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)712SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));713#else714SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);715#endif716717jump = compiler->jumps;718while (jump) {719generate_jump_or_mov_addr(jump, executable_offset);720jump = jump->next;721}722723compiler->error = SLJIT_ERR_COMPILED;724compiler->executable_offset = executable_offset;725726code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);727728#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)729#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)730if (((sljit_sw)code_ptr) & 0x4)731code_ptr++;732#endif733sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);734#endif735736code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);737738SLJIT_CACHE_FLUSH(code, code_ptr);739SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);740741#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)742compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);743return code_ptr;744#else745compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);746return code;747#endif748}749750SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)751{752switch (feature_type) {753case SLJIT_HAS_FPU:754#ifdef SLJIT_IS_FPU_AVAILABLE755return (SLJIT_IS_FPU_AVAILABLE) != 0;756#else757/* Available by default. */758return 1;759#endif760case SLJIT_HAS_REV:761#if defined(_ARCH_PWR10) && _ARCH_PWR10762return 1;763#else /* !POWER10 */764return 2;765#endif /* POWER10 */766/* A saved register is set to a zero value. */767case SLJIT_HAS_ZERO_REGISTER:768case SLJIT_HAS_CLZ:769case SLJIT_HAS_ROT:770case SLJIT_HAS_PREFETCH:771case SLJIT_HAS_ATOMIC:772case SLJIT_HAS_MEMORY_BARRIER:773return 1;774775case SLJIT_HAS_CTZ:776return 2;777778default:779return 0;780}781}782783SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)784{785switch (type) {786case SLJIT_UNORDERED_OR_EQUAL:787case SLJIT_ORDERED_NOT_EQUAL:788case SLJIT_UNORDERED_OR_LESS:789case SLJIT_ORDERED_GREATER_EQUAL:790case SLJIT_UNORDERED_OR_GREATER:791case SLJIT_ORDERED_LESS_EQUAL:792return 1;793}794795return 0;796}797798/* --------------------------------------------------------------------- */799/* Entry, exit */800/* --------------------------------------------------------------------- */801802/* inp_flags: */803804/* Creates an index in data_transfer_insts array. */805#define LOAD_DATA 0x01806#define INDEXED 0x02807#define SIGNED_DATA 0x04808809#define WORD_DATA 0x00810#define BYTE_DATA 0x08811#define HALF_DATA 0x10812#define INT_DATA 0x18813/* Separates integer and floating point registers */814#define GPR_REG 0x1f815#define DOUBLE_DATA 0x20816817#define MEM_MASK 0x7f818819#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))820821/* Other inp_flags. */822823/* Integer opertion and set flags -> requires exts on 64 bit systems. */824#define ALT_SIGN_EXT 0x000100825/* This flag affects the RC() and OERC() macros. */826#define ALT_SET_FLAGS 0x000400827#define ALT_FORM1 0x001000828#define ALT_FORM2 0x002000829#define ALT_FORM3 0x004000830#define ALT_FORM4 0x008000831#define ALT_FORM5 0x010000832833/* Source and destination is register. */834#define REG_DEST 0x000001835#define REG1_SOURCE 0x000002836#define REG2_SOURCE 0x000004837/*838ALT_SIGN_EXT 0x000100839ALT_SET_FLAGS 0x000200840ALT_FORM1 0x001000841...842ALT_FORM5 0x010000 */843844static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,845sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);846847#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)848#include "sljitNativePPC_32.c"849#else850#include "sljitNativePPC_64.c"851#endif852853#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)854#define STACK_STORE STW855#define STACK_LOAD LWZ856#else857#define STACK_STORE STD858#define STACK_LOAD LD859#endif860861#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)862#define LR_SAVE_OFFSET (2 * SSIZE_OF(sw))863#else864#define LR_SAVE_OFFSET SSIZE_OF(sw)865#endif866867#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)868869SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,870sljit_s32 options, sljit_s32 arg_types,871sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)872{873sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);874sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);875sljit_s32 i, tmp, base, offset;876sljit_s32 word_arg_count = 0;877sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);878#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)879sljit_s32 arg_count = 0;880#endif881882CHECK_ERROR();883CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));884set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);885886scratches = ENTER_GET_REGS(scratches);887saveds = ENTER_GET_REGS(saveds);888local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)889+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);890891if (!(options & SLJIT_ENTER_REG_ARG))892local_size += SSIZE_OF(sw);893894local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;895compiler->local_size = local_size;896897FAIL_IF(push_inst(compiler, MFLR | D(0)));898899base = SLJIT_SP;900offset = local_size;901902if (local_size <= STACK_MAX_DISTANCE) {903#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)904FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));905#else906FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));907#endif908} else {909base = TMP_REG1;910FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));911FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));912#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)913FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));914#else915FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));916#endif917local_size = 0;918offset = 0;919}920921tmp = SLJIT_FS0 - fsaveds;922for (i = SLJIT_FS0; i > tmp; i--) {923offset -= SSIZE_OF(f64);924FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));925}926927for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {928offset -= SSIZE_OF(f64);929FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));930}931932if (!(options & SLJIT_ENTER_REG_ARG)) {933offset -= SSIZE_OF(sw);934FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));935}936937tmp = SLJIT_S0 - saveds;938for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {939offset -= SSIZE_OF(sw);940FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));941}942943for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {944offset -= SSIZE_OF(sw);945FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));946}947948FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));949950if (options & SLJIT_ENTER_REG_ARG)951return SLJIT_SUCCESS;952953FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));954955arg_types >>= SLJIT_ARG_SHIFT;956saved_arg_count = 0;957958while (arg_types > 0) {959if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {960#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)961do {962if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {963tmp = SLJIT_S0 - saved_arg_count;964saved_arg_count++;965} else if (arg_count != word_arg_count)966tmp = SLJIT_R0 + word_arg_count;967else968break;969970FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));971} while (0);972#else973if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {974FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));975saved_arg_count++;976}977#endif978word_arg_count++;979}980981#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)982arg_count++;983#endif984arg_types >>= SLJIT_ARG_SHIFT;985}986987return SLJIT_SUCCESS;988}989990SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,991sljit_s32 options, sljit_s32 arg_types,992sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)993{994sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);995sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);996997CHECK_ERROR();998CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));999set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);10001001scratches = ENTER_GET_REGS(scratches);1002saveds = ENTER_GET_REGS(saveds);1003local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)1004+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);10051006if (!(options & SLJIT_ENTER_REG_ARG))1007local_size += SSIZE_OF(sw);10081009compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;1010return SLJIT_SUCCESS;1011}10121013static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)1014{1015sljit_s32 i, tmp, base, offset;1016sljit_s32 local_size = compiler->local_size;10171018SLJIT_ASSERT(TMP_CALL_REG != TMP_REG2);10191020base = SLJIT_SP;1021if (local_size > STACK_MAX_DISTANCE) {1022base = TMP_REG2;1023if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {1024FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));1025local_size = 0;1026} else {1027FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));1028local_size = STACK_MAX_DISTANCE;1029}1030}10311032offset = local_size;1033if (!is_return_to)1034FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));10351036tmp = SLJIT_FS0 - compiler->fsaveds;1037for (i = SLJIT_FS0; i > tmp; i--) {1038offset -= SSIZE_OF(f64);1039FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));1040}10411042for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1043offset -= SSIZE_OF(f64);1044FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));1045}10461047if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {1048offset -= SSIZE_OF(sw);1049FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));1050}10511052tmp = SLJIT_S0 - compiler->saveds;1053for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {1054offset -= SSIZE_OF(sw);1055FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));1056}10571058for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {1059offset -= SSIZE_OF(sw);1060FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));1061}10621063if (!is_return_to)1064push_inst(compiler, MTLR | S(0));10651066if (local_size > 0)1067return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));10681069SLJIT_ASSERT(base == TMP_REG2);1070return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));1071}10721073#undef STACK_STORE1074#undef STACK_LOAD10751076SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)1077{1078CHECK_ERROR();1079CHECK(check_sljit_emit_return_void(compiler));10801081FAIL_IF(emit_stack_frame_release(compiler, 0));1082return push_inst(compiler, BLR);1083}10841085SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,1086sljit_s32 src, sljit_sw srcw)1087{1088CHECK_ERROR();1089CHECK(check_sljit_emit_return_to(compiler, src, srcw));10901091if (src & SLJIT_MEM) {1092ADJUST_LOCAL_OFFSET(src, srcw);1093FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));1094src = TMP_CALL_REG;1095srcw = 0;1096} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {1097FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));1098src = TMP_CALL_REG;1099srcw = 0;1100}11011102FAIL_IF(emit_stack_frame_release(compiler, 1));11031104SLJIT_SKIP_CHECKS(compiler);1105return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);1106}11071108/* --------------------------------------------------------------------- */1109/* Operators */1110/* --------------------------------------------------------------------- */11111112/* s/l - store/load (1 bit)1113i/x - immediate/indexed form1114u/s - signed/unsigned (1 bit)1115w/b/h/i - word/byte/half/int allowed (2 bit)11161117Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */11181119/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */1120#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1121#define INT_ALIGNED 0x100001122#endif11231124#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)1125#define ARCH_32_64(a, b) a1126#define INST_CODE_AND_DST(inst, flags, reg) \1127((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))1128#else1129#define ARCH_32_64(a, b) b1130#define INST_CODE_AND_DST(inst, flags, reg) \1131(((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))1132#endif11331134static const sljit_ins data_transfer_insts[64 + 16] = {11351136/* -------- Integer -------- */11371138/* Word. */11391140/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),1141/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),1142/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),1143/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),11441145/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),1146/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),1147/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),1148/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),11491150/* Byte. */11511152/* b u i s */ HI(38) /* stb */,1153/* b u i l */ HI(34) /* lbz */,1154/* b u x s */ HI(31) | LO(215) /* stbx */,1155/* b u x l */ HI(31) | LO(87) /* lbzx */,11561157/* b s i s */ HI(38) /* stb */,1158/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,1159/* b s x s */ HI(31) | LO(215) /* stbx */,1160/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,11611162/* Half. */11631164/* h u i s */ HI(44) /* sth */,1165/* h u i l */ HI(40) /* lhz */,1166/* h u x s */ HI(31) | LO(407) /* sthx */,1167/* h u x l */ HI(31) | LO(279) /* lhzx */,11681169/* h s i s */ HI(44) /* sth */,1170/* h s i l */ HI(42) /* lha */,1171/* h s x s */ HI(31) | LO(407) /* sthx */,1172/* h s x l */ HI(31) | LO(343) /* lhax */,11731174/* Int. */11751176/* i u i s */ HI(36) /* stw */,1177/* i u i l */ HI(32) /* lwz */,1178/* i u x s */ HI(31) | LO(151) /* stwx */,1179/* i u x l */ HI(31) | LO(23) /* lwzx */,11801181/* i s i s */ HI(36) /* stw */,1182/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),1183/* i s x s */ HI(31) | LO(151) /* stwx */,1184/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),11851186/* -------- Floating point -------- */11871188/* d i s */ HI(54) /* stfd */,1189/* d i l */ HI(50) /* lfd */,1190/* d x s */ HI(31) | LO(727) /* stfdx */,1191/* d x l */ HI(31) | LO(599) /* lfdx */,11921193/* s i s */ HI(52) /* stfs */,1194/* s i l */ HI(48) /* lfs */,1195/* s x s */ HI(31) | LO(663) /* stfsx */,1196/* s x l */ HI(31) | LO(535) /* lfsx */,1197};11981199static const sljit_ins updated_data_transfer_insts[64] = {12001201/* -------- Integer -------- */12021203/* Word. */12041205/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),1206/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),1207/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),1208/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),12091210/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),1211/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),1212/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),1213/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),12141215/* Byte. */12161217/* b u i s */ HI(39) /* stbu */,1218/* b u i l */ HI(35) /* lbzu */,1219/* b u x s */ HI(31) | LO(247) /* stbux */,1220/* b u x l */ HI(31) | LO(119) /* lbzux */,12211222/* b s i s */ HI(39) /* stbu */,1223/* b s i l */ 0 /* no such instruction */,1224/* b s x s */ HI(31) | LO(247) /* stbux */,1225/* b s x l */ 0 /* no such instruction */,12261227/* Half. */12281229/* h u i s */ HI(45) /* sthu */,1230/* h u i l */ HI(41) /* lhzu */,1231/* h u x s */ HI(31) | LO(439) /* sthux */,1232/* h u x l */ HI(31) | LO(311) /* lhzux */,12331234/* h s i s */ HI(45) /* sthu */,1235/* h s i l */ HI(43) /* lhau */,1236/* h s x s */ HI(31) | LO(439) /* sthux */,1237/* h s x l */ HI(31) | LO(375) /* lhaux */,12381239/* Int. */12401241/* i u i s */ HI(37) /* stwu */,1242/* i u i l */ HI(33) /* lwzu */,1243/* i u x s */ HI(31) | LO(183) /* stwux */,1244/* i u x l */ HI(31) | LO(55) /* lwzux */,12451246/* i s i s */ HI(37) /* stwu */,1247/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),1248/* i s x s */ HI(31) | LO(183) /* stwux */,1249/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),12501251/* -------- Floating point -------- */12521253/* d i s */ HI(55) /* stfdu */,1254/* d i l */ HI(51) /* lfdu */,1255/* d x s */ HI(31) | LO(759) /* stfdux */,1256/* d x l */ HI(31) | LO(631) /* lfdux */,12571258/* s i s */ HI(53) /* stfsu */,1259/* s i l */ HI(49) /* lfsu */,1260/* s x s */ HI(31) | LO(695) /* stfsux */,1261/* s x l */ HI(31) | LO(567) /* lfsux */,1262};12631264#undef ARCH_32_6412651266/* Simple cases, (no caching is required). */1267static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,1268sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)1269{1270sljit_ins inst;1271sljit_s32 offs_reg;12721273/* Should work when (arg & REG_MASK) == 0. */1274SLJIT_ASSERT(A(0) == 0);1275SLJIT_ASSERT(arg & SLJIT_MEM);12761277if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1278argw &= 0x3;1279offs_reg = OFFS_REG(arg);12801281if (argw != 0) {1282FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg)));1283offs_reg = tmp_reg;1284}12851286inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];12871288#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1289SLJIT_ASSERT(!(inst & INT_ALIGNED));1290#endif /* SLJIT_CONFIG_PPC_64 */12911292return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));1293}12941295inst = data_transfer_insts[inp_flags & MEM_MASK];1296arg &= REG_MASK;12971298#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1299if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {1300FAIL_IF(load_immediate(compiler, tmp_reg, argw));13011302inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];1303return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));1304}1305#endif /* SLJIT_CONFIG_PPC_64 */13061307if (argw <= SIMM_MAX && argw >= SIMM_MIN)1308return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));13091310#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1311if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {1312#endif /* SLJIT_CONFIG_PPC_64 */1313FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16)));1314return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));1315#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1316}13171318FAIL_IF(load_immediate(compiler, tmp_reg, argw));13191320inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];1321return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));1322#endif /* SLJIT_CONFIG_PPC_64 */1323}13241325static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,1326sljit_s32 dst, sljit_sw dstw,1327sljit_s32 src1, sljit_sw src1w,1328sljit_s32 src2, sljit_sw src2w)1329{1330/* arg1 goes to TMP_REG1 or src reg1331arg2 goes to TMP_REG2, imm or src reg1332result goes to TMP_REG2, so put result can use TMP_REG1. */1333sljit_s32 dst_r = TMP_REG2;1334sljit_s32 src1_r;1335sljit_s32 src2_r;1336sljit_s32 src2_tmp_reg = (!(input_flags & ALT_SIGN_EXT) && GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;1337sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);13381339/* Destination check. */1340if (FAST_IS_REG(dst)) {1341dst_r = dst;1342/* The REG_DEST is only used by SLJIT_MOV operations, although1343* it is set for op2 operations with unset destination. */1344flags |= REG_DEST;13451346if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)1347src2_tmp_reg = dst_r;1348}13491350/* Source 2. */1351if (FAST_IS_REG(src2)) {1352src2_r = src2;1353flags |= REG2_SOURCE;13541355if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)1356dst_r = src2_r;1357} else if (src2 == SLJIT_IMM) {1358src2_r = TMP_ZERO;1359if (src2w != 0) {1360FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));1361src2_r = src2_tmp_reg;1362}1363} else {1364FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, src2_tmp_reg, src2, src2w, TMP_REG1));1365src2_r = src2_tmp_reg;1366}13671368/* Source 1. */1369if (FAST_IS_REG(src1)) {1370src1_r = src1;1371flags |= REG1_SOURCE;1372} else if (src1 == SLJIT_IMM) {1373src1_r = TMP_ZERO;1374if (src1w != 0) {1375FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));1376src1_r = TMP_REG1;1377}1378} else {1379FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));1380src1_r = TMP_REG1;1381}13821383FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));13841385if (!(dst & SLJIT_MEM))1386return SLJIT_SUCCESS;13871388return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);1389}13901391SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)1392{1393#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1394sljit_s32 int_op = op & SLJIT_32;1395#endif13961397CHECK_ERROR();1398CHECK(check_sljit_emit_op0(compiler, op));13991400op = GET_OPCODE(op);1401switch (op) {1402case SLJIT_BREAKPOINT:1403case SLJIT_NOP:1404return push_inst(compiler, NOP);1405case SLJIT_LMUL_UW:1406case SLJIT_LMUL_SW:1407FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));1408#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1409FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));1410return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));1411#else1412FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));1413return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));1414#endif1415case SLJIT_DIVMOD_UW:1416case SLJIT_DIVMOD_SW:1417FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));1418#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1419FAIL_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)));1420FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));1421#else1422FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));1423FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));1424#endif1425return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));1426case SLJIT_DIV_UW:1427case SLJIT_DIV_SW:1428#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1429return 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));1430#else1431return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));1432#endif1433case SLJIT_MEMORY_BARRIER:1434return push_inst(compiler, SYNC);1435case SLJIT_ENDBR:1436case SLJIT_SKIP_FRAMES_BEFORE_RETURN:1437return SLJIT_SUCCESS;1438}14391440return SLJIT_SUCCESS;1441}14421443static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op,1444sljit_s32 dst, sljit_sw dstw,1445sljit_s32 src, sljit_sw srcw)1446{1447sljit_s32 mem, offs_reg, inp_flags;1448sljit_sw memw;1449#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1450sljit_s32 is_32 = op & SLJIT_32;14511452op = GET_OPCODE(op);1453#endif /* SLJIT_CONFIG_PPC_64 */14541455if (!((dst | src) & SLJIT_MEM)) {1456/* Both are registers. */1457if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {1458if (src == dst) {1459FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15)));1460FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31)));1461} else {1462FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23)));1463FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31)));1464}14651466if (op == SLJIT_REV_U16)1467return SLJIT_SUCCESS;1468return push_inst(compiler, EXTSH | S(dst) | A(dst));1469}14701471#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1472if (!is_32) {1473#if defined(_ARCH_PWR10) && _ARCH_PWR101474return push_inst(compiler, BRD | S(src) | A(dst));1475#else /* !POWER10 */1476FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI)));1477FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));1478FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));1479FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO)));1480FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2)));1481return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);1482#endif /* POWER10 */1483}1484#endif /* SLJIT_CONFIG_PPC_64 */14851486FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET)));1487FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));1488FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET));14891490#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1491if (op == SLJIT_REV_S32)1492return push_inst(compiler, EXTSW | S(dst) | A(dst));1493#endif /* SLJIT_CONFIG_PPC_64 */1494return SLJIT_SUCCESS;1495}14961497mem = src;1498memw = srcw;14991500if (dst & SLJIT_MEM) {1501mem = dst;1502memw = dstw;15031504if (src & SLJIT_MEM) {1505inp_flags = HALF_DATA | LOAD_DATA;15061507if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) {1508#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1509inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA;1510#else /* !SLJIT_CONFIG_PPC_64 */1511inp_flags = WORD_DATA | LOAD_DATA;1512#endif /* SLJIT_CONFIG_PPC_64 */1513}15141515FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2));1516src = TMP_REG1;1517}1518}15191520if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {1521offs_reg = OFFS_REG(mem);1522mem &= REG_MASK;1523memw &= 0x3;15241525if (memw != 0) {1526FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2)));1527offs_reg = TMP_REG2;1528}1529#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1530} else if (memw > 0x7fff7fffl || memw < -0x80000000l) {1531FAIL_IF(load_immediate(compiler, TMP_REG2, memw));1532offs_reg = TMP_REG2;1533mem &= REG_MASK;1534#endif /* SLJIT_CONFIG_PPC_64 */1535} else {1536FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw)));1537if (memw > SIMM_MAX || memw < SIMM_MIN)1538FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16)));15391540mem = 0;1541offs_reg = TMP_REG2;1542}15431544if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {1545if (dst & SLJIT_MEM)1546return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg));15471548FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg)));15491550if (op == SLJIT_REV_U16)1551return SLJIT_SUCCESS;1552return push_inst(compiler, EXTSH | S(dst) | A(dst));1553}15541555#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1556if (!is_32) {1557if (dst & SLJIT_MEM) {1558#if defined(_ARCH_PWR7) && _ARCH_PWR71559return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg));1560#else /* !POWER7 */1561#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN1562FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));1563FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg)));1564FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));1565return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2));1566#else /* !SLJIT_LITTLE_ENDIAN */1567FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)));1568FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));1569FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));1570return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2));1571#endif /* SLJIT_LITTLE_ENDIAN */1572#endif /* POWER7 */1573}1574#if defined(_ARCH_PWR7) && _ARCH_PWR71575return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg));1576#else /* !POWER7 */1577FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg)));1578FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));1579FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2)));1580return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0));1581#endif /* POWER7 */1582}1583#endif /* SLJIT_CONFIG_PPC_64 */15841585if (dst & SLJIT_MEM)1586return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg));15871588FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)));1589#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1590if (op == SLJIT_REV_S32)1591return push_inst(compiler, EXTSW | S(dst) | A(dst));1592#endif /* SLJIT_CONFIG_PPC_64 */1593return SLJIT_SUCCESS;1594}15951596#define EMIT_MOV(type, type_flags, type_cast) \1597emit_op(compiler, (src == SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? type_cast srcw : srcw)15981599SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,1600sljit_s32 dst, sljit_sw dstw,1601sljit_s32 src, sljit_sw srcw)1602{1603sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;1604sljit_s32 op_flags = GET_ALL_FLAGS(op);16051606CHECK_ERROR();1607CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));1608ADJUST_LOCAL_OFFSET(dst, dstw);1609ADJUST_LOCAL_OFFSET(src, srcw);16101611op = GET_OPCODE(op);16121613if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)1614FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));16151616if (op <= SLJIT_MOV_P && FAST_IS_REG(src) && src == dst) {1617if (!TYPE_CAST_NEEDED(op))1618return SLJIT_SUCCESS;1619}16201621#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1622if (op_flags & SLJIT_32) {1623if (op <= SLJIT_MOV_P) {1624if (src & SLJIT_MEM) {1625if (op == SLJIT_MOV_S32)1626op = SLJIT_MOV_U32;1627}1628else if (src == SLJIT_IMM) {1629if (op == SLJIT_MOV_U32)1630op = SLJIT_MOV_S32;1631}1632}1633else {1634/* Most operations expect sign extended arguments. */1635flags |= INT_DATA | SIGNED_DATA;1636if (HAS_FLAGS(op_flags))1637flags |= ALT_SIGN_EXT;1638}1639}1640#endif16411642switch (op) {1643case SLJIT_MOV:1644#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)1645case SLJIT_MOV_U32:1646case SLJIT_MOV_S32:1647case SLJIT_MOV32:1648#endif1649case SLJIT_MOV_P:1650return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);16511652#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1653case SLJIT_MOV_U32:1654return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));16551656case SLJIT_MOV_S32:1657case SLJIT_MOV32:1658return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));1659#endif16601661case SLJIT_MOV_U8:1662return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));16631664case SLJIT_MOV_S8:1665return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));16661667case SLJIT_MOV_U16:1668return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));16691670case SLJIT_MOV_S16:1671return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));16721673case SLJIT_CLZ:1674case SLJIT_CTZ:1675#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1676if (op_flags & SLJIT_32)1677flags |= ALT_FORM1;1678#endif /* SLJIT_CONFIG_PPC_64 */1679return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);1680case SLJIT_REV_U32:1681case SLJIT_REV_S32:1682#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1683op |= SLJIT_32;1684#endif /* SLJIT_CONFIG_PPC_64 */1685/* fallthrough */1686case SLJIT_REV:1687case SLJIT_REV_U16:1688case SLJIT_REV_S16:1689#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1690op |= (op_flags & SLJIT_32);1691#endif /* SLJIT_CONFIG_PPC_64 */1692return emit_rev(compiler, op, dst, dstw, src, srcw);1693}16941695return SLJIT_SUCCESS;1696}16971698#undef EMIT_MOV16991700/* Macros for checking different operand types / values. */1701#define TEST_SL_IMM(src, srcw) \1702((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)1703#define TEST_UL_IMM(src, srcw) \1704((src) == SLJIT_IMM && !((srcw) & ~0xffff))1705#define TEST_UH_IMM(src, srcw) \1706((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000))17071708#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1709#define TEST_SH_IMM(src, srcw) \1710((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)1711#define TEST_ADD_IMM(src, srcw) \1712((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)1713#define TEST_UI_IMM(src, srcw) \1714((src) == SLJIT_IMM && !((srcw) & ~0xffffffff))17151716#define TEST_ADD_FORM1(op) \1717(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \1718|| (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))1719#define TEST_SUB_FORM2(op) \1720((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \1721|| (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))1722#define TEST_SUB_FORM3(op) \1723(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \1724|| (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))17251726#else /* !SLJIT_CONFIG_PPC_64 */1727#define TEST_SH_IMM(src, srcw) \1728((src) == SLJIT_IMM && !((srcw) & 0xffff))1729#define TEST_ADD_IMM(src, srcw) \1730((src) == SLJIT_IMM)1731#define TEST_UI_IMM(src, srcw) \1732((src) == SLJIT_IMM)17331734#define TEST_ADD_FORM1(op) \1735(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)1736#define TEST_SUB_FORM2(op) \1737(GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)1738#define TEST_SUB_FORM3(op) \1739(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)1740#endif /* SLJIT_CONFIG_PPC_64 */17411742SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,1743sljit_s32 dst, sljit_sw dstw,1744sljit_s32 src1, sljit_sw src1w,1745sljit_s32 src2, sljit_sw src2w)1746{1747sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;17481749CHECK_ERROR();1750CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));1751ADJUST_LOCAL_OFFSET(dst, dstw);1752ADJUST_LOCAL_OFFSET(src1, src1w);1753ADJUST_LOCAL_OFFSET(src2, src2w);17541755#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1756if (op & SLJIT_32) {1757/* Most operations expect sign extended arguments. */1758flags |= INT_DATA | SIGNED_DATA;1759if (src1 == SLJIT_IMM)1760src1w = (sljit_s32)(src1w);1761if (src2 == SLJIT_IMM)1762src2w = (sljit_s32)(src2w);1763if (HAS_FLAGS(op))1764flags |= ALT_SIGN_EXT;1765}1766#endif1767if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)1768FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));17691770switch (GET_OPCODE(op)) {1771case SLJIT_ADD:1772compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;17731774if (TEST_ADD_FORM1(op))1775return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);17761777if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) {1778if (TEST_SL_IMM(src2, src2w)) {1779compiler->imm = (sljit_ins)src2w & 0xffff;1780return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);1781}1782if (TEST_SL_IMM(src1, src1w)) {1783compiler->imm = (sljit_ins)src1w & 0xffff;1784return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);1785}1786if (TEST_SH_IMM(src2, src2w)) {1787compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;1788return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1789}1790if (TEST_SH_IMM(src1, src1w)) {1791compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;1792return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);1793}1794/* Range between -1 and -32768 is covered above. */1795if (TEST_ADD_IMM(src2, src2w)) {1796compiler->imm = (sljit_ins)src2w & 0xffffffff;1797return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);1798}1799if (TEST_ADD_IMM(src1, src1w)) {1800compiler->imm = (sljit_ins)src1w & 0xffffffff;1801return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);1802}1803}18041805#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1806if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {1807if (TEST_SL_IMM(src2, src2w)) {1808compiler->imm = (sljit_ins)src2w & 0xffff;1809return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);1810}1811if (TEST_SL_IMM(src1, src1w)) {1812compiler->imm = (sljit_ins)src1w & 0xffff;1813return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);1814}1815return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);1816}1817#endif1818if (HAS_FLAGS(op)) {1819if (TEST_SL_IMM(src2, src2w)) {1820compiler->imm = (sljit_ins)src2w & 0xffff;1821return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1822}1823if (TEST_SL_IMM(src1, src1w)) {1824compiler->imm = (sljit_ins)src1w & 0xffff;1825return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);1826}1827}1828return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);18291830case SLJIT_ADDC:1831compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;1832return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);18331834case SLJIT_SUB:1835compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;18361837if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {1838if (dst == TMP_REG1) {1839if (TEST_UL_IMM(src2, src2w)) {1840compiler->imm = (sljit_ins)src2w & 0xffff;1841return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);1842}1843return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);1844}18451846if (src2 == SLJIT_IMM && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {1847compiler->imm = (sljit_ins)src2w;1848return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1849}1850return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);1851}18521853if (dst == TMP_REG1 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {1854if (TEST_SL_IMM(src2, src2w)) {1855compiler->imm = (sljit_ins)src2w & 0xffff;1856return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1857}1858return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);1859}18601861if (TEST_SUB_FORM2(op)) {1862if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {1863compiler->imm = (sljit_ins)src2w & 0xffff;1864return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);1865}1866return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);1867}18681869if (TEST_SUB_FORM3(op))1870return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);18711872if (TEST_SL_IMM(src2, -src2w)) {1873compiler->imm = (sljit_ins)(-src2w) & 0xffff;1874return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);1875}18761877if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {1878compiler->imm = (sljit_ins)src1w & 0xffff;1879return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);1880}18811882if (!HAS_FLAGS(op)) {1883if (TEST_SH_IMM(src2, -src2w)) {1884compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;1885return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1886}1887/* Range between -1 and -32768 is covered above. */1888if (TEST_ADD_IMM(src2, -src2w)) {1889compiler->imm = (sljit_ins)-src2w;1890return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);1891}1892}18931894/* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */1895return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);18961897case SLJIT_SUBC:1898compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;1899return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);19001901case SLJIT_MUL:1902#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1903if (op & SLJIT_32)1904flags |= ALT_FORM2;1905#endif1906if (!HAS_FLAGS(op)) {1907if (TEST_SL_IMM(src2, src2w)) {1908compiler->imm = (sljit_ins)src2w & 0xffff;1909return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);1910}1911if (TEST_SL_IMM(src1, src1w)) {1912compiler->imm = (sljit_ins)src1w & 0xffff;1913return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);1914}1915}1916else1917FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));1918return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);19191920case SLJIT_XOR:1921if (src2 == SLJIT_IMM && src2w == -1) {1922return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w);1923}1924if (src1 == SLJIT_IMM && src1w == -1) {1925return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);1926}1927/* fallthrough */1928case SLJIT_AND:1929case SLJIT_OR:1930/* Commutative unsigned operations. */1931if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {1932if (TEST_UL_IMM(src2, src2w)) {1933compiler->imm = (sljit_ins)src2w;1934return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);1935}1936if (TEST_UL_IMM(src1, src1w)) {1937compiler->imm = (sljit_ins)src1w;1938return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);1939}1940if (TEST_UH_IMM(src2, src2w)) {1941compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;1942return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);1943}1944if (TEST_UH_IMM(src1, src1w)) {1945compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;1946return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);1947}1948}1949if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {1950/* Unlike or and xor, the and resets unwanted bits as well. */1951if (TEST_UI_IMM(src2, src2w)) {1952compiler->imm = (sljit_ins)src2w;1953return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);1954}1955if (TEST_UI_IMM(src1, src1w)) {1956compiler->imm = (sljit_ins)src1w;1957return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);1958}1959}1960return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);19611962case SLJIT_SHL:1963case SLJIT_MSHL:1964case SLJIT_LSHR:1965case SLJIT_MLSHR:1966case SLJIT_ASHR:1967case SLJIT_MASHR:1968case SLJIT_ROTL:1969case SLJIT_ROTR:1970#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)1971if (op & SLJIT_32)1972flags |= ALT_FORM2;1973#endif1974if (src2 == SLJIT_IMM) {1975compiler->imm = (sljit_ins)src2w;1976return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);1977}1978return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);1979}19801981return SLJIT_SUCCESS;1982}19831984SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,1985sljit_s32 src1, sljit_sw src1w,1986sljit_s32 src2, sljit_sw src2w)1987{1988CHECK_ERROR();1989CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));19901991SLJIT_SKIP_CHECKS(compiler);1992return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);1993}19941995#undef TEST_ADD_FORM11996#undef TEST_SUB_FORM21997#undef TEST_SUB_FORM319981999SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,2000sljit_s32 dst_reg,2001sljit_s32 src1, sljit_sw src1w,2002sljit_s32 src2, sljit_sw src2w)2003{2004CHECK_ERROR();2005CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));20062007switch (GET_OPCODE(op)) {2008case SLJIT_MULADD:2009SLJIT_SKIP_CHECKS(compiler);2010FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));2011return push_inst(compiler, ADD | D(dst_reg) | A(dst_reg) | B(TMP_REG2));2012}20132014return SLJIT_SUCCESS;2015}20162017SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,2018sljit_s32 dst_reg,2019sljit_s32 src1_reg,2020sljit_s32 src2_reg,2021sljit_s32 src3, sljit_sw src3w)2022{2023sljit_s32 is_right;2024#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2025sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2026sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;2027#else /* !SLJIT_CONFIG_PPC_64 */2028sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;2029sljit_sw bit_length = 32;2030#endif /* SLJIT_CONFIG_PPC_64 */20312032CHECK_ERROR();2033CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));20342035is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);20362037if (src1_reg == src2_reg) {2038SLJIT_SKIP_CHECKS(compiler);2039return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);2040}20412042ADJUST_LOCAL_OFFSET(src3, src3w);20432044if (src3 == SLJIT_IMM) {2045src3w &= bit_length - 1;20462047if (src3w == 0)2048return SLJIT_SUCCESS;20492050#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2051if (!(op & SLJIT_32)) {2052if (is_right) {2053FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg)));2054return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0));2055}20562057FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg)));2058/* Computes SRDI(64 - src2w). */2059FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w)));2060return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));2061}2062#endif /* SLJIT_CONFIG_PPC_64 */20632064if (is_right) {2065FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg)));2066return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1));2067}20682069FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg)));2070return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31));2071}20722073if (src3 & SLJIT_MEM) {2074FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2));2075src3 = TMP_REG2;2076}20772078#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2079if (!(op & SLJIT_32)) {2080if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {2081FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f));2082src3 = TMP_REG2;2083}20842085FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3)));2086FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1)));2087FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f));2088FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));2089return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));2090}2091#endif /* SLJIT_CONFIG_PPC_64 */20922093if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {2094FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f));2095src3 = TMP_REG2;2096}20972098FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3)));2099FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1)));2100FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f));2101FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));2102return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));2103}21042105static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,2106sljit_s32 src, sljit_sw srcw)2107{2108if (!(src & OFFS_REG_MASK)) {2109if (srcw == 0 && (src & REG_MASK))2110return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));21112112FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));2113/* Works with SLJIT_MEM0() case as well. */2114return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));2115}21162117srcw &= 0x3;21182119if (srcw == 0)2120return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));21212122FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1)));2123return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));2124}21252126SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,2127sljit_s32 src, sljit_sw srcw)2128{2129CHECK_ERROR();2130CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));2131ADJUST_LOCAL_OFFSET(src, srcw);21322133switch (op) {2134case SLJIT_FAST_RETURN:2135if (FAST_IS_REG(src))2136FAIL_IF(push_inst(compiler, MTLR | S(src)));2137else {2138FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));2139FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));2140}21412142return push_inst(compiler, BLR);2143case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:2144return SLJIT_SUCCESS;2145case SLJIT_PREFETCH_L1:2146case SLJIT_PREFETCH_L2:2147case SLJIT_PREFETCH_L3:2148case SLJIT_PREFETCH_ONCE:2149return emit_prefetch(compiler, src, srcw);2150}21512152return SLJIT_SUCCESS;2153}21542155SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,2156sljit_s32 dst, sljit_sw dstw)2157{2158sljit_s32 dst_r;21592160CHECK_ERROR();2161CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));2162ADJUST_LOCAL_OFFSET(dst, dstw);21632164switch (op) {2165case SLJIT_FAST_ENTER:2166if (FAST_IS_REG(dst))2167return push_inst(compiler, MFLR | D(dst));21682169FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1)));2170break;2171case SLJIT_GET_RETURN_ADDRESS:2172dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;2173FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2));2174break;2175}21762177if (dst & SLJIT_MEM)2178return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);21792180return SLJIT_SUCCESS;2181}21822183SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)2184{2185CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));21862187if (type == SLJIT_GP_REGISTER)2188return reg_map[reg];21892190if (type != SLJIT_FLOAT_REGISTER)2191return -1;21922193return freg_map[reg];2194}21952196SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,2197void *instruction, sljit_u32 size)2198{2199SLJIT_UNUSED_ARG(size);22002201CHECK_ERROR();2202CHECK(check_sljit_emit_op_custom(compiler, instruction, size));22032204return push_inst(compiler, *(sljit_ins*)instruction);2205}22062207/* --------------------------------------------------------------------- */2208/* Floating point operators */2209/* --------------------------------------------------------------------- */22102211#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))22122213static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,2214sljit_s32 dst, sljit_sw dstw,2215sljit_s32 src, sljit_sw srcw)2216{2217if (src & SLJIT_MEM) {2218/* We can ignore the temporary data store on the stack from caching point of view. */2219FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));2220src = TMP_FREG1;2221}22222223#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2224op = GET_OPCODE(op);2225FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));22262227if (op == SLJIT_CONV_SW_FROM_F64) {2228if (FAST_IS_REG(dst)) {2229FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));2230return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);2231}2232return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);2233}2234#else /* !SLJIT_CONFIG_PPC_64 */2235FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));2236#endif /* SLJIT_CONFIG_PPC_64 */22372238if (FAST_IS_REG(dst)) {2239FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET));2240FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));2241return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);2242}22432244SLJIT_ASSERT(dst & SLJIT_MEM);22452246if (dst & OFFS_REG_MASK) {2247dstw &= 0x3;2248if (dstw) {2249FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1)));2250dstw = TMP_REG1;2251} else2252dstw = OFFS_REG(dst);2253}2254else {2255if ((dst & REG_MASK) && !dstw) {2256dstw = dst & REG_MASK;2257dst = 0;2258} else {2259/* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */2260FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));2261dstw = TMP_REG1;2262}2263}22642265return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));2266}22672268static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,2269sljit_s32 src1, sljit_sw src1w,2270sljit_s32 src2, sljit_sw src2w)2271{2272if (src1 & SLJIT_MEM) {2273FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));2274src1 = TMP_FREG1;2275}22762277if (src2 & SLJIT_MEM) {2278FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));2279src2 = TMP_FREG2;2280}22812282FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));22832284switch (GET_FLAG_TYPE(op)) {2285case SLJIT_UNORDERED_OR_EQUAL:2286return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));2287case SLJIT_UNORDERED_OR_LESS:2288return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));2289case SLJIT_UNORDERED_OR_GREATER:2290return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));2291}22922293return SLJIT_SUCCESS;2294}22952296SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,2297sljit_s32 dst, sljit_sw dstw,2298sljit_s32 src, sljit_sw srcw)2299{2300sljit_s32 dst_r;23012302CHECK_ERROR();23032304SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);2305SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);23062307if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)2308op ^= SLJIT_32;23092310dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;23112312if (src & SLJIT_MEM) {2313FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));2314src = dst_r;2315}23162317switch (GET_OPCODE(op)) {2318case SLJIT_CONV_F64_FROM_F32:2319op ^= SLJIT_32;2320if (op & SLJIT_32) {2321FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));2322break;2323}2324/* Fall through. */2325case SLJIT_MOV_F64:2326if (src != dst_r) {2327if (!(dst & SLJIT_MEM))2328FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));2329else2330dst_r = src;2331}2332break;2333case SLJIT_NEG_F64:2334FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));2335break;2336case SLJIT_ABS_F64:2337FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));2338break;2339}23402341if (dst & SLJIT_MEM)2342FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));2343return SLJIT_SUCCESS;2344}23452346SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,2347sljit_s32 dst, sljit_sw dstw,2348sljit_s32 src1, sljit_sw src1w,2349sljit_s32 src2, sljit_sw src2w)2350{2351sljit_s32 dst_r;23522353CHECK_ERROR();2354CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));2355ADJUST_LOCAL_OFFSET(dst, dstw);2356ADJUST_LOCAL_OFFSET(src1, src1w);2357ADJUST_LOCAL_OFFSET(src2, src2w);23582359dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;23602361if (src1 & SLJIT_MEM) {2362FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));2363src1 = TMP_FREG1;2364}23652366if (src2 & SLJIT_MEM) {2367FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG1));2368src2 = TMP_FREG2;2369}23702371switch (GET_OPCODE(op)) {2372case SLJIT_ADD_F64:2373FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));2374break;2375case SLJIT_SUB_F64:2376FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));2377break;2378case SLJIT_MUL_F64:2379FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));2380break;2381case SLJIT_DIV_F64:2382FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));2383break;2384case SLJIT_COPYSIGN_F64:2385FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET));2386#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)2387FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI)));2388#else /* !SLJIT_CONFIG_PPC_32 */2389FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));2390#endif /* SLJIT_CONFIG_PPC_32 */2391FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1)));2392#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)2393FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0));2394#else /* !SLJIT_CONFIG_PPC_32 */2395FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0));2396#endif /* SLJIT_CONFIG_PPC_32 */2397FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8));2398return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r));2399}24002401if (dst & SLJIT_MEM)2402FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));24032404return SLJIT_SUCCESS;2405}24062407#undef SELECT_FOP24082409SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,2410sljit_s32 freg, sljit_f32 value)2411{2412union {2413sljit_s32 imm;2414sljit_f32 value;2415} u;24162417CHECK_ERROR();2418CHECK(check_sljit_emit_fset32(compiler, freg, value));24192420u.value = value;24212422if (u.imm != 0)2423FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));24242425FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));2426return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);2427}24282429/* --------------------------------------------------------------------- */2430/* Conditional instructions */2431/* --------------------------------------------------------------------- */24322433SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)2434{2435struct sljit_label *label;24362437CHECK_ERROR_PTR();2438CHECK_PTR(check_sljit_emit_label(compiler));24392440if (compiler->last_label && compiler->last_label->size == compiler->size)2441return compiler->last_label;24422443label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));2444PTR_FAIL_IF(!label);2445set_label(label, compiler);2446return label;2447}24482449static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)2450{2451switch (type) {2452case SLJIT_NOT_CARRY:2453if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)2454return (4 << 21) | (2 << 16);2455/* fallthrough */24562457case SLJIT_EQUAL:2458case SLJIT_ATOMIC_STORED:2459return (12 << 21) | (2 << 16);24602461case SLJIT_CARRY:2462if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)2463return (12 << 21) | (2 << 16);2464/* fallthrough */24652466case SLJIT_NOT_EQUAL:2467case SLJIT_ATOMIC_NOT_STORED:2468return (4 << 21) | (2 << 16);24692470case SLJIT_LESS:2471case SLJIT_SIG_LESS:2472return (12 << 21) | (0 << 16);24732474case SLJIT_GREATER_EQUAL:2475case SLJIT_SIG_GREATER_EQUAL:2476return (4 << 21) | (0 << 16);24772478case SLJIT_GREATER:2479case SLJIT_SIG_GREATER:2480return (12 << 21) | (1 << 16);24812482case SLJIT_LESS_EQUAL:2483case SLJIT_SIG_LESS_EQUAL:2484return (4 << 21) | (1 << 16);24852486case SLJIT_OVERFLOW:2487return (12 << 21) | (3 << 16);24882489case SLJIT_NOT_OVERFLOW:2490return (4 << 21) | (3 << 16);24912492case SLJIT_F_LESS:2493case SLJIT_ORDERED_LESS:2494case SLJIT_UNORDERED_OR_LESS:2495return (12 << 21) | ((4 + 0) << 16);24962497case SLJIT_F_GREATER_EQUAL:2498case SLJIT_ORDERED_GREATER_EQUAL:2499case SLJIT_UNORDERED_OR_GREATER_EQUAL:2500return (4 << 21) | ((4 + 0) << 16);25012502case SLJIT_F_GREATER:2503case SLJIT_ORDERED_GREATER:2504case SLJIT_UNORDERED_OR_GREATER:2505return (12 << 21) | ((4 + 1) << 16);25062507case SLJIT_F_LESS_EQUAL:2508case SLJIT_ORDERED_LESS_EQUAL:2509case SLJIT_UNORDERED_OR_LESS_EQUAL:2510return (4 << 21) | ((4 + 1) << 16);25112512case SLJIT_F_EQUAL:2513case SLJIT_ORDERED_EQUAL:2514case SLJIT_UNORDERED_OR_EQUAL:2515return (12 << 21) | ((4 + 2) << 16);25162517case SLJIT_F_NOT_EQUAL:2518case SLJIT_ORDERED_NOT_EQUAL:2519case SLJIT_UNORDERED_OR_NOT_EQUAL:2520return (4 << 21) | ((4 + 2) << 16);25212522case SLJIT_UNORDERED:2523return (12 << 21) | ((4 + 3) << 16);25242525case SLJIT_ORDERED:2526return (4 << 21) | ((4 + 3) << 16);25272528default:2529SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);2530return (20 << 21);2531}2532}25332534SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)2535{2536struct sljit_jump *jump;2537sljit_ins bo_bi_flags;25382539CHECK_ERROR_PTR();2540CHECK_PTR(check_sljit_emit_jump(compiler, type));25412542bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);2543if (!bo_bi_flags)2544return NULL;25452546jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));2547PTR_FAIL_IF(!jump);2548set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);2549type &= 0xff;25502551if ((type | 0x1) == SLJIT_NOT_CARRY)2552PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG2) | A(TMP_ZERO) | B(TMP_ZERO)));25532554/* In PPC, we don't need to touch the arguments. */2555if (type < SLJIT_JUMP)2556jump->flags |= IS_COND;2557#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)2558if (type >= SLJIT_CALL)2559jump->flags |= IS_CALL;2560#endif25612562jump->addr = compiler->size;2563PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));25642565/* Maximum number of instructions required for generating a constant. */2566compiler->size += JUMP_MAX_SIZE - 1;2567return jump;2568}25692570SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,2571sljit_s32 arg_types)2572{2573SLJIT_UNUSED_ARG(arg_types);25742575CHECK_ERROR_PTR();2576CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));25772578#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2579if ((type & 0xff) != SLJIT_CALL_REG_ARG)2580PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));2581#endif25822583if (type & SLJIT_CALL_RETURN) {2584PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));2585type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);2586}25872588SLJIT_SKIP_CHECKS(compiler);2589return sljit_emit_jump(compiler, type);2590}25912592SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)2593{2594struct sljit_jump *jump = NULL;2595sljit_s32 src_r;25962597CHECK_ERROR();2598CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));25992600if (src == SLJIT_IMM) {2601/* These jumps are converted to jump/call instructions when possible. */2602jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));2603FAIL_IF(!jump);2604set_jump(jump, compiler, JUMP_ADDR);2605jump->u.target = (sljit_uw)srcw;26062607#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)2608if (type >= SLJIT_CALL)2609jump->flags |= IS_CALL;2610#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */26112612jump->addr = compiler->size;2613FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)));26142615/* Maximum number of instructions required for generating a constant. */2616compiler->size += JUMP_MAX_SIZE - 1;2617return SLJIT_SUCCESS;2618}26192620if (FAST_IS_REG(src)) {2621#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)2622if (type >= SLJIT_CALL && src != TMP_CALL_REG) {2623FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));2624src_r = TMP_CALL_REG;2625} else2626src_r = src;2627#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */2628src_r = src;2629#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */2630} else {2631ADJUST_LOCAL_OFFSET(src, srcw);2632FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));2633src_r = TMP_CALL_REG;2634}26352636FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));2637return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));2638}26392640SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,2641sljit_s32 arg_types,2642sljit_s32 src, sljit_sw srcw)2643{2644SLJIT_UNUSED_ARG(arg_types);26452646CHECK_ERROR();2647CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));26482649if (src & SLJIT_MEM) {2650ADJUST_LOCAL_OFFSET(src, srcw);2651FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));2652src = TMP_CALL_REG;2653}26542655if (type & SLJIT_CALL_RETURN) {2656if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {2657FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));2658src = TMP_CALL_REG;2659}26602661FAIL_IF(emit_stack_frame_release(compiler, 0));2662type = SLJIT_JUMP;2663}26642665#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2666if ((type & 0xff) != SLJIT_CALL_REG_ARG)2667FAIL_IF(call_with_args(compiler, arg_types, &src));2668#endif26692670SLJIT_SKIP_CHECKS(compiler);2671return sljit_emit_ijump(compiler, type, src, srcw);2672}26732674SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,2675sljit_s32 dst, sljit_sw dstw,2676sljit_s32 type)2677{2678sljit_s32 reg, invert;2679sljit_u32 bit, from_xer;2680sljit_s32 saved_op = op;2681sljit_sw saved_dstw = dstw;2682#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2683sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;2684#else2685sljit_s32 input_flags = WORD_DATA;2686#endif26872688CHECK_ERROR();2689CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));2690ADJUST_LOCAL_OFFSET(dst, dstw);26912692op = GET_OPCODE(op);2693reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;26942695if (op >= SLJIT_ADD && (dst & SLJIT_MEM))2696FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));26972698invert = 0;2699bit = 0;2700from_xer = 0;27012702switch (type) {2703case SLJIT_LESS:2704case SLJIT_SIG_LESS:2705break;27062707case SLJIT_GREATER_EQUAL:2708case SLJIT_SIG_GREATER_EQUAL:2709invert = 1;2710break;27112712case SLJIT_GREATER:2713case SLJIT_SIG_GREATER:2714bit = 1;2715break;27162717case SLJIT_LESS_EQUAL:2718case SLJIT_SIG_LESS_EQUAL:2719bit = 1;2720invert = 1;2721break;27222723case SLJIT_EQUAL:2724case SLJIT_ATOMIC_STORED:2725bit = 2;2726break;27272728case SLJIT_NOT_EQUAL:2729case SLJIT_ATOMIC_NOT_STORED:2730bit = 2;2731invert = 1;2732break;27332734case SLJIT_OVERFLOW:2735from_xer = 1;2736bit = 1;2737break;27382739case SLJIT_NOT_OVERFLOW:2740from_xer = 1;2741bit = 1;2742invert = 1;2743break;27442745case SLJIT_CARRY:2746from_xer = 1;2747bit = 2;2748invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;2749break;27502751case SLJIT_NOT_CARRY:2752from_xer = 1;2753bit = 2;2754invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;2755break;27562757case SLJIT_F_LESS:2758case SLJIT_ORDERED_LESS:2759case SLJIT_UNORDERED_OR_LESS:2760bit = 4 + 0;2761break;27622763case SLJIT_F_GREATER_EQUAL:2764case SLJIT_ORDERED_GREATER_EQUAL:2765case SLJIT_UNORDERED_OR_GREATER_EQUAL:2766bit = 4 + 0;2767invert = 1;2768break;27692770case SLJIT_F_GREATER:2771case SLJIT_ORDERED_GREATER:2772case SLJIT_UNORDERED_OR_GREATER:2773bit = 4 + 1;2774break;27752776case SLJIT_F_LESS_EQUAL:2777case SLJIT_ORDERED_LESS_EQUAL:2778case SLJIT_UNORDERED_OR_LESS_EQUAL:2779bit = 4 + 1;2780invert = 1;2781break;27822783case SLJIT_F_EQUAL:2784case SLJIT_ORDERED_EQUAL:2785case SLJIT_UNORDERED_OR_EQUAL:2786bit = 4 + 2;2787break;27882789case SLJIT_F_NOT_EQUAL:2790case SLJIT_ORDERED_NOT_EQUAL:2791case SLJIT_UNORDERED_OR_NOT_EQUAL:2792bit = 4 + 2;2793invert = 1;2794break;27952796case SLJIT_UNORDERED:2797bit = 4 + 3;2798break;27992800case SLJIT_ORDERED:2801bit = 4 + 3;2802invert = 1;2803break;28042805default:2806SLJIT_UNREACHABLE();2807break;2808}28092810FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));2811/* Simplified mnemonics: extrwi. */2812FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31)));28132814if (invert)2815FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));28162817if (op < SLJIT_ADD) {2818if (!(dst & SLJIT_MEM))2819return SLJIT_SUCCESS;2820return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);2821}28222823SLJIT_SKIP_CHECKS(compiler);28242825if (dst & SLJIT_MEM)2826return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);2827return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);2828}28292830SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,2831sljit_s32 dst_reg,2832sljit_s32 src1, sljit_sw src1w,2833sljit_s32 src2_reg)2834{2835sljit_ins *ptr;2836sljit_uw size;2837#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2838sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2839#else /* !SLJIT_CONFIG_PPC_64 */2840sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;2841#endif /* SLJIT_CONFIG_PPC_64 */28422843CHECK_ERROR();2844CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));28452846ADJUST_LOCAL_OFFSET(src1, src1w);28472848if (dst_reg != src2_reg) {2849if (dst_reg == src1) {2850src1 = src2_reg;2851src1w = 0;2852type ^= 0x1;2853} else {2854if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {2855FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG1) | B(dst_reg)));28562857if ((src1 & REG_MASK) == dst_reg)2858src1 = (src1 & ~REG_MASK) | TMP_REG1;28592860if (OFFS_REG(src1) == dst_reg)2861src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);2862}28632864FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg)));2865}2866}28672868if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)2869FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));28702871size = compiler->size;28722873ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));2874FAIL_IF(!ptr);2875compiler->size++;28762877if (src1 & SLJIT_MEM) {2878FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));2879} else if (src1 == SLJIT_IMM) {2880#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2881if (type & SLJIT_32)2882src1w = (sljit_s32)src1w;2883#endif /* SLJIT_CONFIG_RISCV_64 */2884FAIL_IF(load_immediate(compiler, dst_reg, src1w));2885} else2886FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));28872888*ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);2889return SLJIT_SUCCESS;2890}28912892SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,2893sljit_s32 dst_freg,2894sljit_s32 src1, sljit_sw src1w,2895sljit_s32 src2_freg)2896{2897sljit_ins *ptr;2898sljit_uw size;28992900CHECK_ERROR();2901CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));29022903ADJUST_LOCAL_OFFSET(src1, src1w);29042905if (dst_freg != src2_freg) {2906if (dst_freg == src1) {2907src1 = src2_freg;2908src1w = 0;2909type ^= 0x1;2910} else2911FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg)));2912}29132914if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)2915FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));29162917size = compiler->size;29182919ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));2920FAIL_IF(!ptr);2921compiler->size++;29222923if (src1 & SLJIT_MEM)2924FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1));2925else2926FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1)));29272928*ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);2929return SLJIT_SUCCESS;2930}29312932#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)29332934#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \2935((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw))29362937#else /* !SLJIT_CONFIG_PPC_32 */29382939#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \2940((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \2941|| ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \2942|| ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \29432944#endif /* SLJIT_CONFIG_PPC_32 */29452946SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,2947sljit_s32 reg,2948sljit_s32 mem, sljit_sw memw)2949{2950sljit_ins inst;29512952CHECK_ERROR();2953CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));29542955if (!(reg & REG_PAIR_MASK))2956return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);29572958ADJUST_LOCAL_OFFSET(mem, memw);29592960inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)];29612962if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {2963memw &= 0x3;29642965if (memw != 0) {2966FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1)));2967FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK)));2968} else2969FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem))));29702971mem = TMP_REG1;2972memw = 0;2973} else {2974if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) {2975if ((mem & REG_MASK) != 0) {2976SLJIT_SKIP_CHECKS(compiler);2977FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw));2978} else2979FAIL_IF(load_immediate(compiler, TMP_REG1, memw));29802981memw = 0;2982mem = TMP_REG1;2983} else if (memw > SIMM_MAX || memw < SIMM_MIN) {2984FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16)));29852986memw &= 0xffff;2987mem = TMP_REG1;2988} else {2989memw &= 0xffff;2990mem &= REG_MASK;2991}2992}29932994SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff));29952996#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)2997inst &= (sljit_ins)~INT_ALIGNED;2998#endif /* SLJIT_CONFIG_PPC_64 */29993000if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {3001FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))));3002return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw));3003}30043005FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)));3006return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)));3007}30083009#undef EMIT_MEM_LOAD_IMM30103011SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,3012sljit_s32 reg,3013sljit_s32 mem, sljit_sw memw)3014{3015sljit_s32 mem_flags;3016sljit_ins inst;30173018CHECK_ERROR();3019CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));30203021if (type & SLJIT_MEM_POST)3022return SLJIT_ERR_UNSUPPORTED;30233024switch (type & 0xff) {3025case SLJIT_MOV:3026case SLJIT_MOV_P:3027#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)3028case SLJIT_MOV_U32:3029case SLJIT_MOV_S32:3030case SLJIT_MOV32:3031#endif3032mem_flags = WORD_DATA;3033break;30343035#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)3036case SLJIT_MOV_U32:3037case SLJIT_MOV32:3038mem_flags = INT_DATA;3039break;30403041case SLJIT_MOV_S32:3042mem_flags = INT_DATA;30433044if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {3045if (mem & OFFS_REG_MASK)3046mem_flags |= SIGNED_DATA;3047else3048return SLJIT_ERR_UNSUPPORTED;3049}3050break;3051#endif30523053case SLJIT_MOV_U8:3054case SLJIT_MOV_S8:3055mem_flags = BYTE_DATA;3056break;30573058case SLJIT_MOV_U16:3059mem_flags = HALF_DATA;3060break;30613062case SLJIT_MOV_S16:3063mem_flags = HALF_DATA | SIGNED_DATA;3064break;30653066default:3067SLJIT_UNREACHABLE();3068mem_flags = WORD_DATA;3069break;3070}30713072if (!(type & SLJIT_MEM_STORE))3073mem_flags |= LOAD_DATA;30743075if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {3076if (memw != 0)3077return SLJIT_ERR_UNSUPPORTED;30783079if (type & SLJIT_MEM_SUPP)3080return SLJIT_SUCCESS;30813082inst = updated_data_transfer_insts[mem_flags | INDEXED];3083FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));3084}3085else {3086if (memw > SIMM_MAX || memw < SIMM_MIN)3087return SLJIT_ERR_UNSUPPORTED;30883089inst = updated_data_transfer_insts[mem_flags];30903091#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)3092if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)3093return SLJIT_ERR_UNSUPPORTED;3094#endif30953096if (type & SLJIT_MEM_SUPP)3097return SLJIT_SUCCESS;30983099FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));3100}31013102if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)3103return push_inst(compiler, EXTSB | S(reg) | A(reg));3104return SLJIT_SUCCESS;3105}31063107SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,3108sljit_s32 freg,3109sljit_s32 mem, sljit_sw memw)3110{3111sljit_s32 mem_flags;3112sljit_ins inst;31133114CHECK_ERROR();3115CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));31163117if (type & SLJIT_MEM_POST)3118return SLJIT_ERR_UNSUPPORTED;31193120if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {3121if (memw != 0)3122return SLJIT_ERR_UNSUPPORTED;3123}3124else {3125if (memw > SIMM_MAX || memw < SIMM_MIN)3126return SLJIT_ERR_UNSUPPORTED;3127}31283129if (type & SLJIT_MEM_SUPP)3130return SLJIT_SUCCESS;31313132mem_flags = FLOAT_DATA(type);31333134if (!(type & SLJIT_MEM_STORE))3135mem_flags |= LOAD_DATA;31363137if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {3138inst = updated_data_transfer_insts[mem_flags | INDEXED];3139return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));3140}31413142inst = updated_data_transfer_insts[mem_flags];3143return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));3144}31453146SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,3147sljit_s32 dst_reg,3148sljit_s32 mem_reg)3149{3150sljit_ins ins;31513152CHECK_ERROR();3153CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));31543155if (op & SLJIT_ATOMIC_USE_CAS)3156return SLJIT_ERR_UNSUPPORTED;31573158switch (GET_OPCODE(op)) {3159case SLJIT_MOV:3160case SLJIT_MOV_P:3161#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)3162ins = LDARX;3163break;3164#endif /* SLJIT_CONFIG_RISCV_64 */3165case SLJIT_MOV_U32:3166case SLJIT_MOV32:3167ins = LWARX;3168break;31693170default:3171return SLJIT_ERR_UNSUPPORTED;3172}31733174if (op & SLJIT_ATOMIC_TEST)3175return SLJIT_SUCCESS;31763177return push_inst(compiler, ins | D(dst_reg) | B(mem_reg));3178}31793180SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,3181sljit_s32 src_reg,3182sljit_s32 mem_reg,3183sljit_s32 temp_reg)3184{3185sljit_ins ins;31863187/* temp_reg == mem_reg is undefined so use another temp register */3188SLJIT_UNUSED_ARG(temp_reg);31893190CHECK_ERROR();3191CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));31923193if (op & SLJIT_ATOMIC_USE_CAS)3194return SLJIT_ERR_UNSUPPORTED;31953196switch (GET_OPCODE(op)) {3197case SLJIT_MOV:3198case SLJIT_MOV_P:3199#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)3200ins = STDCX | 0x1;3201break;3202#endif /* SLJIT_CONFIG_RISCV_64 */3203case SLJIT_MOV_U32:3204case SLJIT_MOV32:3205ins = STWCX | 0x1;3206break;32073208default:3209return SLJIT_ERR_UNSUPPORTED;3210}32113212if (op & SLJIT_ATOMIC_TEST)3213return SLJIT_SUCCESS;32143215return push_inst(compiler, ins | D(src_reg) | B(mem_reg));3216}32173218SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)3219{3220struct sljit_const *const_;3221sljit_s32 dst_r;32223223CHECK_ERROR_PTR();3224CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));3225ADJUST_LOCAL_OFFSET(dst, dstw);32263227const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));3228PTR_FAIL_IF(!const_);3229set_const(const_, compiler);32303231dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;3232PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));32333234if (dst & SLJIT_MEM)3235PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));32363237return const_;3238}32393240SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)3241{3242struct sljit_jump *jump;3243sljit_s32 dst_r;32443245CHECK_ERROR_PTR();3246CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));3247ADJUST_LOCAL_OFFSET(dst, dstw);32483249jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3250PTR_FAIL_IF(!jump);3251set_mov_addr(jump, compiler, 0);32523253dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;3254PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));3255#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)3256compiler->size++;3257#else3258compiler->size += 4;3259#endif32603261if (dst & SLJIT_MEM)3262PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));32633264return jump;3265}32663267SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)3268{3269sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);3270}327132723273