"Fossies" - the Fresh Open Source Software Archive

Member "pcre-8.44/sljit/sljitNativePPC_64.c" (17 Jul 2019, 17358 Bytes) of package /linux/misc/pcre-8.44.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sljitNativePPC_64.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.43_vs_8.44.

    1 /*
    2  *    Stack-less Just-In-Time compiler
    3  *
    4  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without modification, are
    7  * permitted provided that the following conditions are met:
    8  *
    9  *   1. Redistributions of source code must retain the above copyright notice, this list of
   10  *      conditions and the following disclaimer.
   11  *
   12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
   13  *      of conditions and the following disclaimer in the documentation and/or other materials
   14  *      provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
   17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
   19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
   21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 /* ppc 64-bit arch dependent functions. */
   28 
   29 #if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
   30 #define ASM_SLJIT_CLZ(src, dst) \
   31     __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
   32 #elif defined(__xlc__)
   33 #error "Please enable GCC syntax for inline assembly statements"
   34 #else
   35 #error "Must implement count leading zeroes"
   36 #endif
   37 
   38 #define PUSH_RLDICR(reg, shift) \
   39     push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
   40 
   41 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
   42 {
   43     sljit_uw tmp;
   44     sljit_uw shift;
   45     sljit_uw tmp2;
   46     sljit_uw shift2;
   47 
   48     if (imm <= SIMM_MAX && imm >= SIMM_MIN)
   49         return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
   50 
   51     if (!(imm & ~0xffff))
   52         return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
   53 
   54     if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
   55         FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
   56         return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
   57     }
   58 
   59     /* Count leading zeroes. */
   60     tmp = (imm >= 0) ? imm : ~imm;
   61     ASM_SLJIT_CLZ(tmp, shift);
   62     SLJIT_ASSERT(shift > 0);
   63     shift--;
   64     tmp = (imm << shift);
   65 
   66     if ((tmp & ~0xffff000000000000ul) == 0) {
   67         FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
   68         shift += 15;
   69         return PUSH_RLDICR(reg, shift);
   70     }
   71 
   72     if ((tmp & ~0xffffffff00000000ul) == 0) {
   73         FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));
   74         FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
   75         shift += 31;
   76         return PUSH_RLDICR(reg, shift);
   77     }
   78 
   79     /* Cut out the 16 bit from immediate. */
   80     shift += 15;
   81     tmp2 = imm & ((1ul << (63 - shift)) - 1);
   82 
   83     if (tmp2 <= 0xffff) {
   84         FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
   85         FAIL_IF(PUSH_RLDICR(reg, shift));
   86         return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);
   87     }
   88 
   89     if (tmp2 <= 0xffffffff) {
   90         FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
   91         FAIL_IF(PUSH_RLDICR(reg, shift));
   92         FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));
   93         return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
   94     }
   95 
   96     ASM_SLJIT_CLZ(tmp2, shift2);
   97     tmp2 <<= shift2;
   98 
   99     if ((tmp2 & ~0xffff000000000000ul) == 0) {
  100         FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
  101         shift2 += 15;
  102         shift += (63 - shift2);
  103         FAIL_IF(PUSH_RLDICR(reg, shift));
  104         FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));
  105         return PUSH_RLDICR(reg, shift2);
  106     }
  107 
  108     /* The general version. */
  109     FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));
  110     FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
  111     FAIL_IF(PUSH_RLDICR(reg, 31));
  112     FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
  113     return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
  114 }
  115 
  116 /* Simplified mnemonics: clrldi. */
  117 #define INS_CLEAR_LEFT(dst, src, from) \
  118     (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))
  119 
  120 /* Sign extension for integer operations. */
  121 #define UN_EXTS() \
  122     if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
  123         FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
  124         src2 = TMP_REG2; \
  125     }
  126 
  127 #define BIN_EXTS() \
  128     if (flags & ALT_SIGN_EXT) { \
  129         if (flags & REG1_SOURCE) { \
  130             FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
  131             src1 = TMP_REG1; \
  132         } \
  133         if (flags & REG2_SOURCE) { \
  134             FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
  135             src2 = TMP_REG2; \
  136         } \
  137     }
  138 
  139 #define BIN_IMM_EXTS() \
  140     if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
  141         FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
  142         src1 = TMP_REG1; \
  143     }
  144 
  145 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
  146     sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
  147 {
  148     switch (op) {
  149     case SLJIT_MOV:
  150     case SLJIT_MOV_P:
  151         SLJIT_ASSERT(src1 == TMP_REG1);
  152         if (dst != src2)
  153             return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
  154         return SLJIT_SUCCESS;
  155 
  156     case SLJIT_MOV_U32:
  157     case SLJIT_MOV_S32:
  158         SLJIT_ASSERT(src1 == TMP_REG1);
  159         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  160             if (op == SLJIT_MOV_S32)
  161                 return push_inst(compiler, EXTSW | S(src2) | A(dst));
  162             return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
  163         }
  164         else {
  165             SLJIT_ASSERT(dst == src2);
  166         }
  167         return SLJIT_SUCCESS;
  168 
  169     case SLJIT_MOV_U8:
  170     case SLJIT_MOV_S8:
  171         SLJIT_ASSERT(src1 == TMP_REG1);
  172         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  173             if (op == SLJIT_MOV_S8)
  174                 return push_inst(compiler, EXTSB | S(src2) | A(dst));
  175             return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
  176         }
  177         else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
  178             return push_inst(compiler, EXTSB | S(src2) | A(dst));
  179         else {
  180             SLJIT_ASSERT(dst == src2);
  181         }
  182         return SLJIT_SUCCESS;
  183 
  184     case SLJIT_MOV_U16:
  185     case SLJIT_MOV_S16:
  186         SLJIT_ASSERT(src1 == TMP_REG1);
  187         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  188             if (op == SLJIT_MOV_S16)
  189                 return push_inst(compiler, EXTSH | S(src2) | A(dst));
  190             return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
  191         }
  192         else {
  193             SLJIT_ASSERT(dst == src2);
  194         }
  195         return SLJIT_SUCCESS;
  196 
  197     case SLJIT_NOT:
  198         SLJIT_ASSERT(src1 == TMP_REG1);
  199         UN_EXTS();
  200         return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
  201 
  202     case SLJIT_NEG:
  203         SLJIT_ASSERT(src1 == TMP_REG1);
  204 
  205         if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
  206             FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
  207             FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
  208             return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
  209         }
  210 
  211         UN_EXTS();
  212         /* Setting XER SO is not enough, CR SO is also needed. */
  213         return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
  214 
  215     case SLJIT_CLZ:
  216         SLJIT_ASSERT(src1 == TMP_REG1);
  217         if (flags & ALT_FORM1)
  218             return push_inst(compiler, CNTLZW | S(src2) | A(dst));
  219         return push_inst(compiler, CNTLZD | S(src2) | A(dst));
  220 
  221     case SLJIT_ADD:
  222         if (flags & ALT_FORM1) {
  223             if (flags & ALT_SIGN_EXT) {
  224                 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
  225                 src1 = TMP_REG1;
  226                 FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
  227                 src2 = TMP_REG2;
  228             }
  229             /* Setting XER SO is not enough, CR SO is also needed. */
  230             FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
  231             if (flags & ALT_SIGN_EXT)
  232                 return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
  233             return SLJIT_SUCCESS;
  234         }
  235 
  236         if (flags & ALT_FORM2) {
  237             /* Flags does not set: BIN_IMM_EXTS unnecessary. */
  238             SLJIT_ASSERT(src2 == TMP_REG2);
  239 
  240             if (flags & ALT_FORM3)
  241                 return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
  242 
  243             if (flags & ALT_FORM4) {
  244                 FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
  245                 src1 = dst;
  246             }
  247 
  248             return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
  249         }
  250         if (flags & ALT_FORM3) {
  251             SLJIT_ASSERT(src2 == TMP_REG2);
  252             BIN_IMM_EXTS();
  253             return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
  254         }
  255         if (!(flags & ALT_SET_FLAGS))
  256             return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
  257         BIN_EXTS();
  258         if (flags & ALT_FORM4)
  259             return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
  260         return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
  261 
  262     case SLJIT_ADDC:
  263         BIN_EXTS();
  264         return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
  265 
  266     case SLJIT_SUB:
  267         if (flags & ALT_FORM1) {
  268             if (flags & ALT_FORM2) {
  269                 FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
  270                 if (!(flags & ALT_FORM3))
  271                     return SLJIT_SUCCESS;
  272                 return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
  273             }
  274             FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
  275             if (!(flags & ALT_FORM3))
  276                 return SLJIT_SUCCESS;
  277             return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
  278         }
  279 
  280         if (flags & ALT_FORM2) {
  281             if (flags & ALT_SIGN_EXT) {
  282                 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
  283                 src1 = TMP_REG1;
  284                 FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
  285                 src2 = TMP_REG2;
  286             }
  287             /* Setting XER SO is not enough, CR SO is also needed. */
  288             FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
  289             if (flags & ALT_SIGN_EXT)
  290                 return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
  291             return SLJIT_SUCCESS;
  292         }
  293 
  294         if (flags & ALT_FORM3) {
  295             /* Flags does not set: BIN_IMM_EXTS unnecessary. */
  296             SLJIT_ASSERT(src2 == TMP_REG2);
  297             return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
  298         }
  299 
  300         if (flags & ALT_FORM4) {
  301             if (flags & ALT_FORM5) {
  302                 SLJIT_ASSERT(src2 == TMP_REG2);
  303                 return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
  304             }
  305             return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
  306         }
  307 
  308         if (!(flags & ALT_SET_FLAGS))
  309             return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
  310         BIN_EXTS();
  311         if (flags & ALT_FORM5)
  312             return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
  313         return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
  314 
  315     case SLJIT_SUBC:
  316         BIN_EXTS();
  317         return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
  318 
  319     case SLJIT_MUL:
  320         if (flags & ALT_FORM1) {
  321             SLJIT_ASSERT(src2 == TMP_REG2);
  322             return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
  323         }
  324         BIN_EXTS();
  325         if (flags & ALT_FORM2)
  326             return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
  327         return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
  328 
  329     case SLJIT_AND:
  330         if (flags & ALT_FORM1) {
  331             SLJIT_ASSERT(src2 == TMP_REG2);
  332             return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
  333         }
  334         if (flags & ALT_FORM2) {
  335             SLJIT_ASSERT(src2 == TMP_REG2);
  336             return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
  337         }
  338         return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
  339 
  340     case SLJIT_OR:
  341         if (flags & ALT_FORM1) {
  342             SLJIT_ASSERT(src2 == TMP_REG2);
  343             return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
  344         }
  345         if (flags & ALT_FORM2) {
  346             SLJIT_ASSERT(src2 == TMP_REG2);
  347             return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
  348         }
  349         if (flags & ALT_FORM3) {
  350             SLJIT_ASSERT(src2 == TMP_REG2);
  351             FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
  352             return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
  353         }
  354         return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
  355 
  356     case SLJIT_XOR:
  357         if (flags & ALT_FORM1) {
  358             SLJIT_ASSERT(src2 == TMP_REG2);
  359             return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
  360         }
  361         if (flags & ALT_FORM2) {
  362             SLJIT_ASSERT(src2 == TMP_REG2);
  363             return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
  364         }
  365         if (flags & ALT_FORM3) {
  366             SLJIT_ASSERT(src2 == TMP_REG2);
  367             FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
  368             return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
  369         }
  370         return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
  371 
  372     case SLJIT_SHL:
  373         if (flags & ALT_FORM1) {
  374             SLJIT_ASSERT(src2 == TMP_REG2);
  375             if (flags & ALT_FORM2) {
  376                 compiler->imm &= 0x1f;
  377                 return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
  378             }
  379             compiler->imm &= 0x3f;
  380             return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
  381         }
  382         return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
  383 
  384     case SLJIT_LSHR:
  385         if (flags & ALT_FORM1) {
  386             SLJIT_ASSERT(src2 == TMP_REG2);
  387             if (flags & ALT_FORM2) {
  388                 compiler->imm &= 0x1f;
  389                 return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
  390             }
  391             compiler->imm &= 0x3f;
  392             return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
  393         }
  394         return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
  395 
  396     case SLJIT_ASHR:
  397         if (flags & ALT_FORM1) {
  398             SLJIT_ASSERT(src2 == TMP_REG2);
  399             if (flags & ALT_FORM2) {
  400                 compiler->imm &= 0x1f;
  401                 return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
  402             }
  403             compiler->imm &= 0x3f;
  404             return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
  405         }
  406         return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
  407     }
  408 
  409     SLJIT_UNREACHABLE();
  410     return SLJIT_SUCCESS;
  411 }
  412 
  413 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
  414 {
  415     sljit_s32 arg_count = 0;
  416     sljit_s32 word_arg_count = 0;
  417     sljit_s32 types = 0;
  418     sljit_s32 reg = 0;
  419 
  420     if (src)
  421         reg = *src & REG_MASK;
  422 
  423     arg_types >>= SLJIT_DEF_SHIFT;
  424 
  425     while (arg_types) {
  426         types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
  427 
  428         switch (arg_types & SLJIT_DEF_MASK) {
  429         case SLJIT_ARG_TYPE_F32:
  430         case SLJIT_ARG_TYPE_F64:
  431             arg_count++;
  432             break;
  433         default:
  434             arg_count++;
  435             word_arg_count++;
  436 
  437             if (arg_count != word_arg_count && arg_count == reg) {
  438                 FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
  439                 *src = TMP_CALL_REG;
  440             }
  441             break;
  442         }
  443 
  444         arg_types >>= SLJIT_DEF_SHIFT;
  445     }
  446 
  447     while (types) {
  448         switch (types & SLJIT_DEF_MASK) {
  449         case SLJIT_ARG_TYPE_F32:
  450         case SLJIT_ARG_TYPE_F64:
  451             arg_count--;
  452             break;
  453         default:
  454             if (arg_count != word_arg_count)
  455                 FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
  456 
  457             arg_count--;
  458             word_arg_count--;
  459             break;
  460         }
  461 
  462         types >>= SLJIT_DEF_SHIFT;
  463     }
  464 
  465     return SLJIT_SUCCESS;
  466 }
  467 
  468 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
  469 {
  470     FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
  471     FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
  472     FAIL_IF(PUSH_RLDICR(reg, 31));
  473     FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
  474     return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
  475 }
  476 
  477 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
  478 {
  479     sljit_ins *inst = (sljit_ins*)addr;
  480 
  481     inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
  482     inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
  483     inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
  484     inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);
  485     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  486     SLJIT_CACHE_FLUSH(inst, inst + 5);
  487 }
  488 
  489 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
  490 {
  491     sljit_ins *inst = (sljit_ins*)addr;
  492 
  493     inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
  494     inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
  495     inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
  496     inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
  497     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  498     SLJIT_CACHE_FLUSH(inst, inst + 5);
  499 }