Annotation of embedaddon/pcre/sljit/sljitNativeARM_v5.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Stack-less Just-In-Time compiler
! 3: *
! 4: * Copyright 2009-2010 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: SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
! 28: {
! 29: #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
! 30: return "arm-v7";
! 31: #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 32: return "arm-v5";
! 33: #else
! 34: #error "Internal error: Unknown ARM architecture"
! 35: #endif
! 36: }
! 37:
! 38: /* Last register + 1. */
! 39: #define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
! 40: #define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
! 41: #define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
! 42: #define TMP_PC (SLJIT_NO_REGISTERS + 4)
! 43:
! 44: #define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1)
! 45: #define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2)
! 46:
! 47: /* In ARM instruction words.
! 48: Cache lines are usually 32 byte aligned. */
! 49: #define CONST_POOL_ALIGNMENT 8
! 50: #define CONST_POOL_EMPTY 0xffffffff
! 51:
! 52: #define ALIGN_INSTRUCTION(ptr) \
! 53: (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))
! 54: #define MAX_DIFFERENCE(max_diff) \
! 55: (((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
! 56:
! 57: /* See sljit_emit_enter if you want to change them. */
! 58: static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
! 59: 0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
! 60: };
! 61:
! 62: #define RM(rm) (reg_map[rm])
! 63: #define RD(rd) (reg_map[rd] << 12)
! 64: #define RN(rn) (reg_map[rn] << 16)
! 65:
! 66: /* --------------------------------------------------------------------- */
! 67: /* Instrucion forms */
! 68: /* --------------------------------------------------------------------- */
! 69:
! 70: /* The instruction includes the AL condition.
! 71: INST_NAME - CONDITIONAL remove this flag. */
! 72: #define COND_MASK 0xf0000000
! 73: #define CONDITIONAL 0xe0000000
! 74: #define PUSH_POOL 0xff000000
! 75:
! 76: /* DP - Data Processing instruction (use with EMIT_DATA_PROCESS_INS). */
! 77: #define ADC_DP 0x5
! 78: #define ADD_DP 0x4
! 79: #define AND_DP 0x0
! 80: #define B 0xea000000
! 81: #define BIC_DP 0xe
! 82: #define BL 0xeb000000
! 83: #define BLX 0xe12fff30
! 84: #define BX 0xe12fff10
! 85: #define CLZ 0xe16f0f10
! 86: #define CMP_DP 0xa
! 87: #define DEBUGGER 0xe1200070
! 88: #define EOR_DP 0x1
! 89: #define MOV_DP 0xd
! 90: #define MUL 0xe0000090
! 91: #define MVN_DP 0xf
! 92: #define NOP 0xe1a00000
! 93: #define ORR_DP 0xc
! 94: #define PUSH 0xe92d0000
! 95: #define POP 0xe8bd0000
! 96: #define RSB_DP 0x3
! 97: #define RSC_DP 0x7
! 98: #define SBC_DP 0x6
! 99: #define SMULL 0xe0c00090
! 100: #define SUB_DP 0x2
! 101: #define VABS_F64 0xeeb00bc0
! 102: #define VADD_F64 0xee300b00
! 103: #define VCMP_F64 0xeeb40b40
! 104: #define VDIV_F64 0xee800b00
! 105: #define VMOV_F64 0xeeb00b40
! 106: #define VMRS 0xeef1fa10
! 107: #define VMUL_F64 0xee200b00
! 108: #define VNEG_F64 0xeeb10b40
! 109: #define VSTR 0xed000b00
! 110: #define VSUB_F64 0xee300b40
! 111:
! 112: #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
! 113: /* Arm v7 specific instructions. */
! 114: #define MOVW 0xe3000000
! 115: #define MOVT 0xe3400000
! 116: #define SXTB 0xe6af0070
! 117: #define SXTH 0xe6bf0070
! 118: #define UXTB 0xe6ef0070
! 119: #define UXTH 0xe6ff0070
! 120: #endif
! 121:
! 122: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 123:
! 124: static int push_cpool(struct sljit_compiler *compiler)
! 125: {
! 126: /* Pushing the constant pool into the instruction stream. */
! 127: sljit_uw* inst;
! 128: sljit_uw* cpool_ptr;
! 129: sljit_uw* cpool_end;
! 130: int i;
! 131:
! 132: /* The label could point the address after the constant pool. */
! 133: if (compiler->last_label && compiler->last_label->size == compiler->size)
! 134: compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;
! 135:
! 136: SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);
! 137: inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 138: FAIL_IF(!inst);
! 139: compiler->size++;
! 140: *inst = 0xff000000 | compiler->cpool_fill;
! 141:
! 142: for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {
! 143: inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 144: FAIL_IF(!inst);
! 145: compiler->size++;
! 146: *inst = 0;
! 147: }
! 148:
! 149: cpool_ptr = compiler->cpool;
! 150: cpool_end = cpool_ptr + compiler->cpool_fill;
! 151: while (cpool_ptr < cpool_end) {
! 152: inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 153: FAIL_IF(!inst);
! 154: compiler->size++;
! 155: *inst = *cpool_ptr++;
! 156: }
! 157: compiler->cpool_diff = CONST_POOL_EMPTY;
! 158: compiler->cpool_fill = 0;
! 159: return SLJIT_SUCCESS;
! 160: }
! 161:
! 162: static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
! 163: {
! 164: sljit_uw* ptr;
! 165:
! 166: if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
! 167: FAIL_IF(push_cpool(compiler));
! 168:
! 169: ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 170: FAIL_IF(!ptr);
! 171: compiler->size++;
! 172: *ptr = inst;
! 173: return SLJIT_SUCCESS;
! 174: }
! 175:
! 176: static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
! 177: {
! 178: sljit_uw* ptr;
! 179: sljit_uw cpool_index = CPOOL_SIZE;
! 180: sljit_uw* cpool_ptr;
! 181: sljit_uw* cpool_end;
! 182: sljit_ub* cpool_unique_ptr;
! 183:
! 184: if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
! 185: FAIL_IF(push_cpool(compiler));
! 186: else if (compiler->cpool_fill > 0) {
! 187: cpool_ptr = compiler->cpool;
! 188: cpool_end = cpool_ptr + compiler->cpool_fill;
! 189: cpool_unique_ptr = compiler->cpool_unique;
! 190: do {
! 191: if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
! 192: cpool_index = cpool_ptr - compiler->cpool;
! 193: break;
! 194: }
! 195: cpool_ptr++;
! 196: cpool_unique_ptr++;
! 197: } while (cpool_ptr < cpool_end);
! 198: }
! 199:
! 200: if (cpool_index == CPOOL_SIZE) {
! 201: /* Must allocate a new entry in the literal pool. */
! 202: if (compiler->cpool_fill < CPOOL_SIZE) {
! 203: cpool_index = compiler->cpool_fill;
! 204: compiler->cpool_fill++;
! 205: }
! 206: else {
! 207: FAIL_IF(push_cpool(compiler));
! 208: cpool_index = 0;
! 209: compiler->cpool_fill = 1;
! 210: }
! 211: }
! 212:
! 213: SLJIT_ASSERT((inst & 0xfff) == 0);
! 214: ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 215: FAIL_IF(!ptr);
! 216: compiler->size++;
! 217: *ptr = inst | cpool_index;
! 218:
! 219: compiler->cpool[cpool_index] = literal;
! 220: compiler->cpool_unique[cpool_index] = 0;
! 221: if (compiler->cpool_diff == CONST_POOL_EMPTY)
! 222: compiler->cpool_diff = compiler->size;
! 223: return SLJIT_SUCCESS;
! 224: }
! 225:
! 226: static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
! 227: {
! 228: sljit_uw* ptr;
! 229: if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
! 230: FAIL_IF(push_cpool(compiler));
! 231:
! 232: SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);
! 233: ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 234: FAIL_IF(!ptr);
! 235: compiler->size++;
! 236: *ptr = inst | compiler->cpool_fill;
! 237:
! 238: compiler->cpool[compiler->cpool_fill] = literal;
! 239: compiler->cpool_unique[compiler->cpool_fill] = 1;
! 240: compiler->cpool_fill++;
! 241: if (compiler->cpool_diff == CONST_POOL_EMPTY)
! 242: compiler->cpool_diff = compiler->size;
! 243: return SLJIT_SUCCESS;
! 244: }
! 245:
! 246: static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler)
! 247: {
! 248: /* Place for at least two instruction (doesn't matter whether the first has a literal). */
! 249: if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
! 250: return push_cpool(compiler);
! 251: return SLJIT_SUCCESS;
! 252: }
! 253:
! 254: static SLJIT_INLINE int emit_blx(struct sljit_compiler *compiler)
! 255: {
! 256: /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
! 257: SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
! 258: return push_inst(compiler, BLX | RM(TMP_REG1));
! 259: }
! 260:
! 261: static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
! 262: {
! 263: sljit_uw diff;
! 264: sljit_uw ind;
! 265: sljit_uw counter = 0;
! 266: sljit_uw* clear_const_pool = const_pool;
! 267: sljit_uw* clear_const_pool_end = const_pool + cpool_size;
! 268:
! 269: SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);
! 270: /* Set unused flag for all literals in the constant pool.
! 271: I.e.: unused literals can belong to branches, which can be encoded as B or BL.
! 272: We can "compress" the constant pool by discarding these literals. */
! 273: while (clear_const_pool < clear_const_pool_end)
! 274: *clear_const_pool++ = (sljit_uw)(-1);
! 275:
! 276: while (last_pc_patch < code_ptr) {
! 277: /* Data transfer instruction with Rn == r15. */
! 278: if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {
! 279: diff = const_pool - last_pc_patch;
! 280: ind = (*last_pc_patch) & 0xfff;
! 281:
! 282: /* Must be a load instruction with immediate offset. */
! 283: SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
! 284: if ((int)const_pool[ind] < 0) {
! 285: const_pool[ind] = counter;
! 286: ind = counter;
! 287: counter++;
! 288: }
! 289: else
! 290: ind = const_pool[ind];
! 291:
! 292: SLJIT_ASSERT(diff >= 1);
! 293: if (diff >= 2 || ind > 0) {
! 294: diff = (diff + ind - 2) << 2;
! 295: SLJIT_ASSERT(diff <= 0xfff);
! 296: *last_pc_patch = (*last_pc_patch & ~0xfff) | diff;
! 297: }
! 298: else
! 299: *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004;
! 300: }
! 301: last_pc_patch++;
! 302: }
! 303: return counter;
! 304: }
! 305:
! 306: /* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
! 307: struct future_patch {
! 308: struct future_patch* next;
! 309: int index;
! 310: int value;
! 311: };
! 312:
! 313: static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
! 314: {
! 315: int value;
! 316: struct future_patch *curr_patch, *prev_patch;
! 317:
! 318: /* Using the values generated by patch_pc_relative_loads. */
! 319: if (!*first_patch)
! 320: value = (int)cpool_start_address[cpool_current_index];
! 321: else {
! 322: curr_patch = *first_patch;
! 323: prev_patch = 0;
! 324: while (1) {
! 325: if (!curr_patch) {
! 326: value = (int)cpool_start_address[cpool_current_index];
! 327: break;
! 328: }
! 329: if ((sljit_uw)curr_patch->index == cpool_current_index) {
! 330: value = curr_patch->value;
! 331: if (prev_patch)
! 332: prev_patch->next = curr_patch->next;
! 333: else
! 334: *first_patch = curr_patch->next;
! 335: SLJIT_FREE(curr_patch);
! 336: break;
! 337: }
! 338: prev_patch = curr_patch;
! 339: curr_patch = curr_patch->next;
! 340: }
! 341: }
! 342:
! 343: if (value >= 0) {
! 344: if ((sljit_uw)value > cpool_current_index) {
! 345: curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch));
! 346: if (!curr_patch) {
! 347: while (*first_patch) {
! 348: curr_patch = *first_patch;
! 349: *first_patch = (*first_patch)->next;
! 350: SLJIT_FREE(curr_patch);
! 351: }
! 352: return SLJIT_ERR_ALLOC_FAILED;
! 353: }
! 354: curr_patch->next = *first_patch;
! 355: curr_patch->index = value;
! 356: curr_patch->value = cpool_start_address[value];
! 357: *first_patch = curr_patch;
! 358: }
! 359: cpool_start_address[value] = *buf_ptr;
! 360: }
! 361: return SLJIT_SUCCESS;
! 362: }
! 363:
! 364: #else
! 365:
! 366: static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
! 367: {
! 368: sljit_uw* ptr;
! 369:
! 370: ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
! 371: FAIL_IF(!ptr);
! 372: compiler->size++;
! 373: *ptr = inst;
! 374: return SLJIT_SUCCESS;
! 375: }
! 376:
! 377: static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit_w imm)
! 378: {
! 379: FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
! 380: return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
! 381: }
! 382:
! 383: #endif
! 384:
! 385: static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
! 386: {
! 387: sljit_w diff;
! 388:
! 389: if (jump->flags & SLJIT_REWRITABLE_JUMP)
! 390: return 0;
! 391:
! 392: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 393: if (jump->flags & IS_BL)
! 394: code_ptr--;
! 395:
! 396: if (jump->flags & JUMP_ADDR)
! 397: diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2));
! 398: else {
! 399: SLJIT_ASSERT(jump->flags & JUMP_LABEL);
! 400: diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2));
! 401: }
! 402:
! 403: /* Branch to Thumb code has not been optimized yet. */
! 404: if (diff & 0x3)
! 405: return 0;
! 406:
! 407: diff >>= 2;
! 408: if (jump->flags & IS_BL) {
! 409: if (diff <= 0x01ffffff && diff >= -0x02000000) {
! 410: *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);
! 411: jump->flags |= PATCH_B;
! 412: return 1;
! 413: }
! 414: }
! 415: else {
! 416: if (diff <= 0x01ffffff && diff >= -0x02000000) {
! 417: *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);
! 418: jump->flags |= PATCH_B;
! 419: }
! 420: }
! 421: #else
! 422: if (jump->flags & JUMP_ADDR)
! 423: diff = ((sljit_w)jump->u.target - (sljit_w)code_ptr);
! 424: else {
! 425: SLJIT_ASSERT(jump->flags & JUMP_LABEL);
! 426: diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)code_ptr);
! 427: }
! 428:
! 429: /* Branch to Thumb code has not been optimized yet. */
! 430: if (diff & 0x3)
! 431: return 0;
! 432:
! 433: diff >>= 2;
! 434: if (diff <= 0x01ffffff && diff >= -0x02000000) {
! 435: code_ptr -= 2;
! 436: *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK);
! 437: jump->flags |= PATCH_B;
! 438: return 1;
! 439: }
! 440: #endif
! 441: return 0;
! 442: }
! 443:
! 444: static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush)
! 445: {
! 446: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 447: sljit_uw *ptr = (sljit_uw*)addr;
! 448: sljit_uw *inst = (sljit_uw*)ptr[0];
! 449: sljit_uw mov_pc = ptr[1];
! 450: int bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
! 451: sljit_w diff = (sljit_w)(((sljit_w)new_addr - (sljit_w)(inst + 2)) >> 2);
! 452:
! 453: if (diff <= 0x7fffff && diff >= -0x800000) {
! 454: /* Turn to branch. */
! 455: if (!bl) {
! 456: inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
! 457: if (flush) {
! 458: SLJIT_CACHE_FLUSH(inst, inst + 1);
! 459: }
! 460: } else {
! 461: inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
! 462: inst[1] = NOP;
! 463: if (flush) {
! 464: SLJIT_CACHE_FLUSH(inst, inst + 2);
! 465: }
! 466: }
! 467: } else {
! 468: /* Get the position of the constant. */
! 469: if (mov_pc & (1 << 23))
! 470: ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;
! 471: else
! 472: ptr = inst + 1;
! 473:
! 474: if (*inst != mov_pc) {
! 475: inst[0] = mov_pc;
! 476: if (!bl) {
! 477: if (flush) {
! 478: SLJIT_CACHE_FLUSH(inst, inst + 1);
! 479: }
! 480: } else {
! 481: inst[1] = BLX | RM(TMP_REG1);
! 482: if (flush) {
! 483: SLJIT_CACHE_FLUSH(inst, inst + 2);
! 484: }
! 485: }
! 486: }
! 487: *ptr = new_addr;
! 488: }
! 489: #else
! 490: sljit_uw *inst = (sljit_uw*)addr;
! 491: SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
! 492: inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
! 493: inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
! 494: if (flush) {
! 495: SLJIT_CACHE_FLUSH(inst, inst + 2);
! 496: }
! 497: #endif
! 498: }
! 499:
! 500: static sljit_uw get_immediate(sljit_uw imm);
! 501:
! 502: static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, int flush)
! 503: {
! 504: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 505: sljit_uw *ptr = (sljit_uw*)addr;
! 506: sljit_uw *inst = (sljit_uw*)ptr[0];
! 507: sljit_uw ldr_literal = ptr[1];
! 508: sljit_uw src2;
! 509:
! 510: src2 = get_immediate(new_constant);
! 511: if (src2) {
! 512: *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
! 513: if (flush) {
! 514: SLJIT_CACHE_FLUSH(inst, inst + 1);
! 515: }
! 516: return;
! 517: }
! 518:
! 519: src2 = get_immediate(~new_constant);
! 520: if (src2) {
! 521: *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
! 522: if (flush) {
! 523: SLJIT_CACHE_FLUSH(inst, inst + 1);
! 524: }
! 525: return;
! 526: }
! 527:
! 528: if (ldr_literal & (1 << 23))
! 529: ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;
! 530: else
! 531: ptr = inst + 1;
! 532:
! 533: if (*inst != ldr_literal) {
! 534: *inst = ldr_literal;
! 535: if (flush) {
! 536: SLJIT_CACHE_FLUSH(inst, inst + 1);
! 537: }
! 538: }
! 539: *ptr = new_constant;
! 540: #else
! 541: sljit_uw *inst = (sljit_uw*)addr;
! 542: SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
! 543: inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
! 544: inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
! 545: if (flush) {
! 546: SLJIT_CACHE_FLUSH(inst, inst + 2);
! 547: }
! 548: #endif
! 549: }
! 550:
! 551: SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
! 552: {
! 553: struct sljit_memory_fragment *buf;
! 554: sljit_uw *code;
! 555: sljit_uw *code_ptr;
! 556: sljit_uw *buf_ptr;
! 557: sljit_uw *buf_end;
! 558: sljit_uw size;
! 559: sljit_uw word_count;
! 560: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 561: sljit_uw cpool_size;
! 562: sljit_uw cpool_skip_alignment;
! 563: sljit_uw cpool_current_index;
! 564: sljit_uw *cpool_start_address;
! 565: sljit_uw *last_pc_patch;
! 566: struct future_patch *first_patch;
! 567: #endif
! 568:
! 569: struct sljit_label *label;
! 570: struct sljit_jump *jump;
! 571: struct sljit_const *const_;
! 572:
! 573: CHECK_ERROR_PTR();
! 574: check_sljit_generate_code(compiler);
! 575: reverse_buf(compiler);
! 576:
! 577: /* Second code generation pass. */
! 578: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 579: size = compiler->size + (compiler->patches << 1);
! 580: if (compiler->cpool_fill > 0)
! 581: size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;
! 582: #else
! 583: size = compiler->size;
! 584: #endif
! 585: code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw));
! 586: PTR_FAIL_WITH_EXEC_IF(code);
! 587: buf = compiler->buf;
! 588:
! 589: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 590: cpool_size = 0;
! 591: cpool_skip_alignment = 0;
! 592: cpool_current_index = 0;
! 593: cpool_start_address = NULL;
! 594: first_patch = NULL;
! 595: last_pc_patch = code;
! 596: #endif
! 597:
! 598: code_ptr = code;
! 599: word_count = 0;
! 600:
! 601: label = compiler->labels;
! 602: jump = compiler->jumps;
! 603: const_ = compiler->consts;
! 604:
! 605: if (label && label->size == 0) {
! 606: label->addr = (sljit_uw)code;
! 607: label->size = 0;
! 608: label = label->next;
! 609: }
! 610:
! 611: do {
! 612: buf_ptr = (sljit_uw*)buf->memory;
! 613: buf_end = buf_ptr + (buf->used_size >> 2);
! 614: do {
! 615: word_count++;
! 616: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 617: if (cpool_size > 0) {
! 618: if (cpool_skip_alignment > 0) {
! 619: buf_ptr++;
! 620: cpool_skip_alignment--;
! 621: }
! 622: else {
! 623: if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
! 624: SLJIT_FREE_EXEC(code);
! 625: compiler->error = SLJIT_ERR_ALLOC_FAILED;
! 626: return NULL;
! 627: }
! 628: buf_ptr++;
! 629: if (++cpool_current_index >= cpool_size) {
! 630: SLJIT_ASSERT(!first_patch);
! 631: cpool_size = 0;
! 632: if (label && label->size == word_count) {
! 633: /* Points after the current instruction. */
! 634: label->addr = (sljit_uw)code_ptr;
! 635: label->size = code_ptr - code;
! 636: label = label->next;
! 637: }
! 638: }
! 639: }
! 640: }
! 641: else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
! 642: #endif
! 643: *code_ptr = *buf_ptr++;
! 644: /* These structures are ordered by their address. */
! 645: SLJIT_ASSERT(!label || label->size >= word_count);
! 646: SLJIT_ASSERT(!jump || jump->addr >= word_count);
! 647: SLJIT_ASSERT(!const_ || const_->addr >= word_count);
! 648: if (jump && jump->addr == word_count) {
! 649: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 650: if (detect_jump_type(jump, code_ptr, code))
! 651: code_ptr--;
! 652: jump->addr = (sljit_uw)code_ptr;
! 653: #else
! 654: jump->addr = (sljit_uw)(code_ptr - 2);
! 655: if (detect_jump_type(jump, code_ptr, code))
! 656: code_ptr -= 2;
! 657: #endif
! 658: jump = jump->next;
! 659: }
! 660: if (label && label->size == word_count) {
! 661: /* code_ptr can be affected above. */
! 662: label->addr = (sljit_uw)(code_ptr + 1);
! 663: label->size = (code_ptr + 1) - code;
! 664: label = label->next;
! 665: }
! 666: if (const_ && const_->addr == word_count) {
! 667: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 668: const_->addr = (sljit_uw)code_ptr;
! 669: #else
! 670: const_->addr = (sljit_uw)(code_ptr - 1);
! 671: #endif
! 672: const_ = const_->next;
! 673: }
! 674: code_ptr++;
! 675: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 676: }
! 677: else {
! 678: /* Fortunately, no need to shift. */
! 679: cpool_size = *buf_ptr++ & ~PUSH_POOL;
! 680: SLJIT_ASSERT(cpool_size > 0);
! 681: cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);
! 682: cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
! 683: if (cpool_current_index > 0) {
! 684: /* Unconditional branch. */
! 685: *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
! 686: code_ptr = cpool_start_address + cpool_current_index;
! 687: }
! 688: cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
! 689: cpool_current_index = 0;
! 690: last_pc_patch = code_ptr;
! 691: }
! 692: #endif
! 693: } while (buf_ptr < buf_end);
! 694: buf = buf->next;
! 695: } while (buf);
! 696:
! 697: SLJIT_ASSERT(!label);
! 698: SLJIT_ASSERT(!jump);
! 699: SLJIT_ASSERT(!const_);
! 700:
! 701: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 702: SLJIT_ASSERT(cpool_size == 0);
! 703: if (compiler->cpool_fill > 0) {
! 704: cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
! 705: cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
! 706: if (cpool_current_index > 0)
! 707: code_ptr = cpool_start_address + cpool_current_index;
! 708:
! 709: buf_ptr = compiler->cpool;
! 710: buf_end = buf_ptr + compiler->cpool_fill;
! 711: cpool_current_index = 0;
! 712: while (buf_ptr < buf_end) {
! 713: if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
! 714: SLJIT_FREE_EXEC(code);
! 715: compiler->error = SLJIT_ERR_ALLOC_FAILED;
! 716: return NULL;
! 717: }
! 718: buf_ptr++;
! 719: cpool_current_index++;
! 720: }
! 721: SLJIT_ASSERT(!first_patch);
! 722: }
! 723: #endif
! 724:
! 725: jump = compiler->jumps;
! 726: while (jump) {
! 727: buf_ptr = (sljit_uw*)jump->addr;
! 728:
! 729: if (jump->flags & PATCH_B) {
! 730: if (!(jump->flags & JUMP_ADDR)) {
! 731: SLJIT_ASSERT(jump->flags & JUMP_LABEL);
! 732: SLJIT_ASSERT(((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
! 733: *buf_ptr |= (((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
! 734: }
! 735: else {
! 736: SLJIT_ASSERT(((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
! 737: *buf_ptr |= (((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
! 738: }
! 739: }
! 740: else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
! 741: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 742: jump->addr = (sljit_uw)code_ptr;
! 743: code_ptr[0] = (sljit_uw)buf_ptr;
! 744: code_ptr[1] = *buf_ptr;
! 745: inline_set_jump_addr((sljit_uw)code_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
! 746: code_ptr += 2;
! 747: #else
! 748: inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
! 749: #endif
! 750: }
! 751: else {
! 752: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 753: if (jump->flags & IS_BL)
! 754: buf_ptr--;
! 755: if (*buf_ptr & (1 << 23))
! 756: buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
! 757: else
! 758: buf_ptr += 1;
! 759: *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
! 760: #else
! 761: inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
! 762: #endif
! 763: }
! 764: jump = jump->next;
! 765: }
! 766:
! 767: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 768: const_ = compiler->consts;
! 769: while (const_) {
! 770: buf_ptr = (sljit_uw*)const_->addr;
! 771: const_->addr = (sljit_uw)code_ptr;
! 772:
! 773: code_ptr[0] = (sljit_uw)buf_ptr;
! 774: code_ptr[1] = *buf_ptr;
! 775: if (*buf_ptr & (1 << 23))
! 776: buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
! 777: else
! 778: buf_ptr += 1;
! 779: /* Set the value again (can be a simple constant). */
! 780: inline_set_const((sljit_uw)code_ptr, *buf_ptr, 0);
! 781: code_ptr += 2;
! 782:
! 783: const_ = const_->next;
! 784: }
! 785: #endif
! 786:
! 787: SLJIT_ASSERT(code_ptr - code <= (int)size);
! 788:
! 789: SLJIT_CACHE_FLUSH(code, code_ptr);
! 790: compiler->error = SLJIT_ERR_COMPILED;
! 791: compiler->executable_size = size * sizeof(sljit_uw);
! 792: return code;
! 793: }
! 794:
! 795: /* emit_op inp_flags.
! 796: WRITE_BACK must be the first, since it is a flag. */
! 797: #define WRITE_BACK 0x01
! 798: #define ALLOW_IMM 0x02
! 799: #define ALLOW_INV_IMM 0x04
! 800: #define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
! 801: #define ARG_TEST 0x08
! 802:
! 803: /* Creates an index in data_transfer_insts array. */
! 804: #define WORD_DATA 0x00
! 805: #define BYTE_DATA 0x10
! 806: #define HALF_DATA 0x20
! 807: #define SIGNED_DATA 0x40
! 808: #define LOAD_DATA 0x80
! 809:
! 810: #define EMIT_INSTRUCTION(inst) \
! 811: FAIL_IF(push_inst(compiler, (inst)))
! 812:
! 813: /* Condition: AL. */
! 814: #define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
! 815: (0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2))
! 816:
! 817: static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
! 818: int dst, sljit_w dstw,
! 819: int src1, sljit_w src1w,
! 820: int src2, sljit_w src2w);
! 821:
! 822: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
! 823: {
! 824: int size;
! 825: sljit_uw push;
! 826:
! 827: CHECK_ERROR();
! 828: check_sljit_emit_enter(compiler, args, temporaries, generals, local_size);
! 829:
! 830: compiler->temporaries = temporaries;
! 831: compiler->generals = generals;
! 832:
! 833: /* Push general registers, temporary registers
! 834: stmdb sp!, {..., lr} */
! 835: push = PUSH | (1 << 14);
! 836: if (temporaries >= 5)
! 837: push |= 1 << 11;
! 838: if (temporaries >= 4)
! 839: push |= 1 << 10;
! 840: if (generals >= 5)
! 841: push |= 1 << 8;
! 842: if (generals >= 4)
! 843: push |= 1 << 7;
! 844: if (generals >= 3)
! 845: push |= 1 << 6;
! 846: if (generals >= 2)
! 847: push |= 1 << 5;
! 848: if (generals >= 1)
! 849: push |= 1 << 4;
! 850: EMIT_INSTRUCTION(push);
! 851:
! 852: /* Stack must be aligned to 8 bytes: */
! 853: size = (1 + generals) * sizeof(sljit_uw);
! 854: if (temporaries >= 4)
! 855: size += (temporaries - 3) * sizeof(sljit_uw);
! 856: local_size += size;
! 857: local_size = (local_size + 7) & ~7;
! 858: local_size -= size;
! 859: compiler->local_size = local_size;
! 860: if (local_size > 0)
! 861: FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size));
! 862:
! 863: if (args >= 1)
! 864: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1)));
! 865: if (args >= 2)
! 866: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
! 867: if (args >= 3)
! 868: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_GENERAL_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3)));
! 869:
! 870: return SLJIT_SUCCESS;
! 871: }
! 872:
! 873: SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
! 874: {
! 875: int size;
! 876:
! 877: CHECK_ERROR_VOID();
! 878: check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
! 879:
! 880: compiler->temporaries = temporaries;
! 881: compiler->generals = generals;
! 882:
! 883: size = (1 + generals) * sizeof(sljit_uw);
! 884: if (temporaries >= 4)
! 885: size += (temporaries - 3) * sizeof(sljit_uw);
! 886: local_size += size;
! 887: local_size = (local_size + 7) & ~7;
! 888: local_size -= size;
! 889: compiler->local_size = local_size;
! 890: }
! 891:
! 892: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
! 893: {
! 894: sljit_uw pop;
! 895:
! 896: CHECK_ERROR();
! 897: check_sljit_emit_return(compiler, src, srcw);
! 898:
! 899: if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG)
! 900: FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, SLJIT_RETURN_REG, 0, TMP_REG1, 0, src, srcw));
! 901:
! 902: if (compiler->local_size > 0)
! 903: FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
! 904:
! 905: pop = POP | (1 << 15);
! 906: /* Push general registers, temporary registers
! 907: ldmia sp!, {..., pc} */
! 908: if (compiler->temporaries >= 5)
! 909: pop |= 1 << 11;
! 910: if (compiler->temporaries >= 4)
! 911: pop |= 1 << 10;
! 912: if (compiler->generals >= 5)
! 913: pop |= 1 << 8;
! 914: if (compiler->generals >= 4)
! 915: pop |= 1 << 7;
! 916: if (compiler->generals >= 3)
! 917: pop |= 1 << 6;
! 918: if (compiler->generals >= 2)
! 919: pop |= 1 << 5;
! 920: if (compiler->generals >= 1)
! 921: pop |= 1 << 4;
! 922:
! 923: return push_inst(compiler, pop);
! 924: }
! 925:
! 926: /* --------------------------------------------------------------------- */
! 927: /* Operators */
! 928: /* --------------------------------------------------------------------- */
! 929:
! 930: /* s/l - store/load (1 bit)
! 931: u/s - signed/unsigned (1 bit)
! 932: w/b/h/N - word/byte/half/NOT allowed (2 bit)
! 933: It contans 16 items, but not all are different. */
! 934:
! 935: static sljit_w data_transfer_insts[16] = {
! 936: /* s u w */ 0xe5000000 /* str */,
! 937: /* s u b */ 0xe5400000 /* strb */,
! 938: /* s u h */ 0xe10000b0 /* strh */,
! 939: /* s u N */ 0x00000000 /* not allowed */,
! 940: /* s s w */ 0xe5000000 /* str */,
! 941: /* s s b */ 0xe5400000 /* strb */,
! 942: /* s s h */ 0xe10000b0 /* strh */,
! 943: /* s s N */ 0x00000000 /* not allowed */,
! 944:
! 945: /* l u w */ 0xe5100000 /* ldr */,
! 946: /* l u b */ 0xe5500000 /* ldrb */,
! 947: /* l u h */ 0xe11000b0 /* ldrh */,
! 948: /* l u N */ 0x00000000 /* not allowed */,
! 949: /* l s w */ 0xe5100000 /* ldr */,
! 950: /* l s b */ 0xe11000d0 /* ldrsb */,
! 951: /* l s h */ 0xe11000f0 /* ldrsh */,
! 952: /* l s N */ 0x00000000 /* not allowed */,
! 953: };
! 954:
! 955: #define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \
! 956: (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2))
! 957: /* Normal ldr/str instruction.
! 958: Type2: ldrsb, ldrh, ldrsh */
! 959: #define IS_TYPE1_TRANSFER(type) \
! 960: (data_transfer_insts[(type) >> 4] & 0x04000000)
! 961: #define TYPE2_TRANSFER_IMM(imm) \
! 962: (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
! 963:
! 964: /* flags: */
! 965: /* Arguments are swapped. */
! 966: #define ARGS_SWAPPED 0x01
! 967: /* Inverted immediate. */
! 968: #define INV_IMM 0x02
! 969: /* Source and destination is register. */
! 970: #define REG_DEST 0x04
! 971: #define REG_SOURCE 0x08
! 972: /* One instruction is enough. */
! 973: #define FAST_DEST 0x10
! 974: /* Multiple instructions are required. */
! 975: #define SLOW_DEST 0x20
! 976: /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
! 977: #define SET_FLAGS (1 << 20)
! 978: /* dst: reg
! 979: src1: reg
! 980: src2: reg or imm (if allowed)
! 981: SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
! 982: #define SRC2_IMM (1 << 25)
! 983:
! 984: #define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \
! 985: return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)))
! 986:
! 987: #define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \
! 988: return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2))
! 989:
! 990: #define EMIT_SHIFT_INS_AND_RETURN(opcode) \
! 991: SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
! 992: if (compiler->shift_imm != 0x20) { \
! 993: SLJIT_ASSERT(src1 == TMP_REG1); \
! 994: SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
! 995: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
! 996: } \
! 997: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
! 998:
! 999: static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
! 1000: int dst, int src1, int src2)
! 1001: {
! 1002: sljit_w mul_inst;
! 1003:
! 1004: switch (GET_OPCODE(op)) {
! 1005: case SLJIT_ADD:
! 1006: SLJIT_ASSERT(!(flags & INV_IMM));
! 1007: EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
! 1008:
! 1009: case SLJIT_ADDC:
! 1010: SLJIT_ASSERT(!(flags & INV_IMM));
! 1011: EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP);
! 1012:
! 1013: case SLJIT_SUB:
! 1014: SLJIT_ASSERT(!(flags & INV_IMM));
! 1015: if (!(flags & ARGS_SWAPPED))
! 1016: EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP);
! 1017: EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP);
! 1018:
! 1019: case SLJIT_SUBC:
! 1020: SLJIT_ASSERT(!(flags & INV_IMM));
! 1021: if (!(flags & ARGS_SWAPPED))
! 1022: EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP);
! 1023: EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP);
! 1024:
! 1025: case SLJIT_MUL:
! 1026: SLJIT_ASSERT(!(flags & INV_IMM));
! 1027: SLJIT_ASSERT(!(src2 & SRC2_IMM));
! 1028: if (SLJIT_UNLIKELY(op & SLJIT_SET_O))
! 1029: mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12);
! 1030: else
! 1031: mul_inst = MUL | (reg_map[dst] << 16);
! 1032:
! 1033: if (dst != src2)
! 1034: FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2]));
! 1035: else if (dst != src1)
! 1036: FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1]));
! 1037: else {
! 1038: /* Rm and Rd must not be the same register. */
! 1039: SLJIT_ASSERT(dst != TMP_REG1);
! 1040: FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2])));
! 1041: FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1]));
! 1042: }
! 1043:
! 1044: if (!(op & SLJIT_SET_O))
! 1045: return SLJIT_SUCCESS;
! 1046:
! 1047: /* We need to use TMP_REG3. */
! 1048: compiler->cache_arg = 0;
! 1049: compiler->cache_argw = 0;
! 1050: /* cmp TMP_REG2, dst asr #31. */
! 1051: return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0));
! 1052:
! 1053: case SLJIT_AND:
! 1054: if (!(flags & INV_IMM))
! 1055: EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP);
! 1056: EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP);
! 1057:
! 1058: case SLJIT_OR:
! 1059: SLJIT_ASSERT(!(flags & INV_IMM));
! 1060: EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP);
! 1061:
! 1062: case SLJIT_XOR:
! 1063: SLJIT_ASSERT(!(flags & INV_IMM));
! 1064: EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP);
! 1065:
! 1066: case SLJIT_SHL:
! 1067: EMIT_SHIFT_INS_AND_RETURN(0);
! 1068:
! 1069: case SLJIT_LSHR:
! 1070: EMIT_SHIFT_INS_AND_RETURN(1);
! 1071:
! 1072: case SLJIT_ASHR:
! 1073: EMIT_SHIFT_INS_AND_RETURN(2);
! 1074:
! 1075: case SLJIT_MOV:
! 1076: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
! 1077: if (dst != src2) {
! 1078: if (src2 & SRC2_IMM) {
! 1079: if (flags & INV_IMM)
! 1080: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
! 1081: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
! 1082: }
! 1083: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
! 1084: }
! 1085: return SLJIT_SUCCESS;
! 1086:
! 1087: case SLJIT_MOV_UB:
! 1088: case SLJIT_MOV_SB:
! 1089: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
! 1090: if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
! 1091: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 1092: if (op == SLJIT_MOV_UB)
! 1093: return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
! 1094: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]));
! 1095: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
! 1096: #else
! 1097: return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
! 1098: #endif
! 1099: }
! 1100: else if (dst != src2) {
! 1101: SLJIT_ASSERT(src2 & SRC2_IMM);
! 1102: if (flags & INV_IMM)
! 1103: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
! 1104: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
! 1105: }
! 1106: return SLJIT_SUCCESS;
! 1107:
! 1108: case SLJIT_MOV_UH:
! 1109: case SLJIT_MOV_SH:
! 1110: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
! 1111: if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
! 1112: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 1113: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]));
! 1114: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
! 1115: #else
! 1116: return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
! 1117: #endif
! 1118: }
! 1119: else if (dst != src2) {
! 1120: SLJIT_ASSERT(src2 & SRC2_IMM);
! 1121: if (flags & INV_IMM)
! 1122: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
! 1123: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
! 1124: }
! 1125: return SLJIT_SUCCESS;
! 1126:
! 1127: case SLJIT_NOT:
! 1128: if (src2 & SRC2_IMM) {
! 1129: if (flags & INV_IMM)
! 1130: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
! 1131: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
! 1132: }
! 1133: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
! 1134:
! 1135: case SLJIT_CLZ:
! 1136: SLJIT_ASSERT(!(flags & INV_IMM));
! 1137: SLJIT_ASSERT(!(src2 & SRC2_IMM));
! 1138: FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
! 1139: if (flags & SET_FLAGS)
! 1140: EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
! 1141: return SLJIT_SUCCESS;
! 1142: }
! 1143: SLJIT_ASSERT_STOP();
! 1144: return SLJIT_SUCCESS;
! 1145: }
! 1146:
! 1147: #undef EMIT_DATA_PROCESS_INS_AND_RETURN
! 1148: #undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN
! 1149: #undef EMIT_SHIFT_INS_AND_RETURN
! 1150:
! 1151: /* Tests whether the immediate can be stored in the 12 bit imm field.
! 1152: Returns with 0 if not possible. */
! 1153: static sljit_uw get_immediate(sljit_uw imm)
! 1154: {
! 1155: int rol;
! 1156:
! 1157: if (imm <= 0xff)
! 1158: return SRC2_IMM | imm;
! 1159:
! 1160: if (!(imm & 0xff000000)) {
! 1161: imm <<= 8;
! 1162: rol = 8;
! 1163: }
! 1164: else {
! 1165: imm = (imm << 24) | (imm >> 8);
! 1166: rol = 0;
! 1167: }
! 1168:
! 1169: if (!(imm & 0xff000000)) {
! 1170: imm <<= 8;
! 1171: rol += 4;
! 1172: }
! 1173:
! 1174: if (!(imm & 0xf0000000)) {
! 1175: imm <<= 4;
! 1176: rol += 2;
! 1177: }
! 1178:
! 1179: if (!(imm & 0xc0000000)) {
! 1180: imm <<= 2;
! 1181: rol += 1;
! 1182: }
! 1183:
! 1184: if (!(imm & 0x00ffffff))
! 1185: return SRC2_IMM | (imm >> 24) | (rol << 8);
! 1186: else
! 1187: return 0;
! 1188: }
! 1189:
! 1190: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 1191: static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm, int positive)
! 1192: {
! 1193: sljit_uw mask;
! 1194: sljit_uw imm1;
! 1195: sljit_uw imm2;
! 1196: int rol;
! 1197:
! 1198: /* Step1: Search a zero byte (8 continous zero bit). */
! 1199: mask = 0xff000000;
! 1200: rol = 8;
! 1201: while(1) {
! 1202: if (!(imm & mask)) {
! 1203: /* Rol imm by rol. */
! 1204: imm = (imm << rol) | (imm >> (32 - rol));
! 1205: /* Calculate arm rol. */
! 1206: rol = 4 + (rol >> 1);
! 1207: break;
! 1208: }
! 1209: rol += 2;
! 1210: mask >>= 2;
! 1211: if (mask & 0x3) {
! 1212: /* rol by 8. */
! 1213: imm = (imm << 8) | (imm >> 24);
! 1214: mask = 0xff00;
! 1215: rol = 24;
! 1216: while (1) {
! 1217: if (!(imm & mask)) {
! 1218: /* Rol imm by rol. */
! 1219: imm = (imm << rol) | (imm >> (32 - rol));
! 1220: /* Calculate arm rol. */
! 1221: rol = (rol >> 1) - 8;
! 1222: break;
! 1223: }
! 1224: rol += 2;
! 1225: mask >>= 2;
! 1226: if (mask & 0x3)
! 1227: return 0;
! 1228: }
! 1229: break;
! 1230: }
! 1231: }
! 1232:
! 1233: /* The low 8 bit must be zero. */
! 1234: SLJIT_ASSERT(!(imm & 0xff));
! 1235:
! 1236: if (!(imm & 0xff000000)) {
! 1237: imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
! 1238: imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
! 1239: }
! 1240: else if (imm & 0xc0000000) {
! 1241: imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
! 1242: imm <<= 8;
! 1243: rol += 4;
! 1244:
! 1245: if (!(imm & 0xff000000)) {
! 1246: imm <<= 8;
! 1247: rol += 4;
! 1248: }
! 1249:
! 1250: if (!(imm & 0xf0000000)) {
! 1251: imm <<= 4;
! 1252: rol += 2;
! 1253: }
! 1254:
! 1255: if (!(imm & 0xc0000000)) {
! 1256: imm <<= 2;
! 1257: rol += 1;
! 1258: }
! 1259:
! 1260: if (!(imm & 0x00ffffff))
! 1261: imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
! 1262: else
! 1263: return 0;
! 1264: }
! 1265: else {
! 1266: if (!(imm & 0xf0000000)) {
! 1267: imm <<= 4;
! 1268: rol += 2;
! 1269: }
! 1270:
! 1271: if (!(imm & 0xc0000000)) {
! 1272: imm <<= 2;
! 1273: rol += 1;
! 1274: }
! 1275:
! 1276: imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
! 1277: imm <<= 8;
! 1278: rol += 4;
! 1279:
! 1280: if (!(imm & 0xf0000000)) {
! 1281: imm <<= 4;
! 1282: rol += 2;
! 1283: }
! 1284:
! 1285: if (!(imm & 0xc0000000)) {
! 1286: imm <<= 2;
! 1287: rol += 1;
! 1288: }
! 1289:
! 1290: if (!(imm & 0x00ffffff))
! 1291: imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
! 1292: else
! 1293: return 0;
! 1294: }
! 1295:
! 1296: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1));
! 1297: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2));
! 1298: return 1;
! 1299: }
! 1300: #endif
! 1301:
! 1302: static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm)
! 1303: {
! 1304: sljit_uw tmp;
! 1305:
! 1306: #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
! 1307: if (!(imm & ~0xffff))
! 1308: return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
! 1309: #endif
! 1310:
! 1311: /* Create imm by 1 inst. */
! 1312: tmp = get_immediate(imm);
! 1313: if (tmp) {
! 1314: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp));
! 1315: return SLJIT_SUCCESS;
! 1316: }
! 1317:
! 1318: tmp = get_immediate(~imm);
! 1319: if (tmp) {
! 1320: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp));
! 1321: return SLJIT_SUCCESS;
! 1322: }
! 1323:
! 1324: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 1325: /* Create imm by 2 inst. */
! 1326: FAIL_IF(generate_int(compiler, reg, imm, 1));
! 1327: FAIL_IF(generate_int(compiler, reg, ~imm, 0));
! 1328:
! 1329: /* Load integer. */
! 1330: return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
! 1331: #else
! 1332: return emit_imm(compiler, reg, imm);
! 1333: #endif
! 1334: }
! 1335:
! 1336: /* Can perform an operation using at most 1 instruction. */
! 1337: static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw)
! 1338: {
! 1339: sljit_uw imm;
! 1340:
! 1341: if (arg & SLJIT_IMM) {
! 1342: imm = get_immediate(argw);
! 1343: if (imm) {
! 1344: if (inp_flags & ARG_TEST)
! 1345: return 1;
! 1346: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm));
! 1347: return -1;
! 1348: }
! 1349: imm = get_immediate(~argw);
! 1350: if (imm) {
! 1351: if (inp_flags & ARG_TEST)
! 1352: return 1;
! 1353: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm));
! 1354: return -1;
! 1355: }
! 1356: return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
! 1357: }
! 1358:
! 1359: SLJIT_ASSERT(arg & SLJIT_MEM);
! 1360:
! 1361: /* Fast loads/stores. */
! 1362: if (arg & 0xf) {
! 1363: if (!(arg & 0xf0)) {
! 1364: if (IS_TYPE1_TRANSFER(inp_flags)) {
! 1365: if (argw >= 0 && argw <= 0xfff) {
! 1366: if (inp_flags & ARG_TEST)
! 1367: return 1;
! 1368: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, argw));
! 1369: return -1;
! 1370: }
! 1371: if (argw < 0 && argw >= -0xfff) {
! 1372: if (inp_flags & ARG_TEST)
! 1373: return 1;
! 1374: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, -argw));
! 1375: return -1;
! 1376: }
! 1377: }
! 1378: else {
! 1379: if (argw >= 0 && argw <= 0xff) {
! 1380: if (inp_flags & ARG_TEST)
! 1381: return 1;
! 1382: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
! 1383: return -1;
! 1384: }
! 1385: if (argw < 0 && argw >= -0xff) {
! 1386: if (inp_flags & ARG_TEST)
! 1387: return 1;
! 1388: argw = -argw;
! 1389: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
! 1390: return -1;
! 1391: }
! 1392: }
! 1393: }
! 1394: else if ((argw & 0x3) == 0 || IS_TYPE1_TRANSFER(inp_flags)) {
! 1395: if (inp_flags & ARG_TEST)
! 1396: return 1;
! 1397: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf,
! 1398: RM((arg >> 4) & 0xf) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
! 1399: return -1;
! 1400: }
! 1401: }
! 1402:
! 1403: return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
! 1404: }
! 1405:
! 1406: /* See getput_arg below.
! 1407: Note: can_cache is called only for binary operators. Those
! 1408: operators always uses word arguments without write back. */
! 1409: static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
! 1410: {
! 1411: /* Immediate caching is not supported as it would be an operation on constant arguments. */
! 1412: if (arg & SLJIT_IMM)
! 1413: return 0;
! 1414:
! 1415: /* Always a simple operation. */
! 1416: if (arg & 0xf0)
! 1417: return 0;
! 1418:
! 1419: if (!(arg & 0xf)) {
! 1420: /* Immediate access. */
! 1421: if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
! 1422: return 1;
! 1423: return 0;
! 1424: }
! 1425:
! 1426: if (argw <= 0xfffff && argw >= -0xfffff)
! 1427: return 0;
! 1428:
! 1429: if (argw == next_argw && (next_arg & SLJIT_MEM))
! 1430: return 1;
! 1431:
! 1432: if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
! 1433: return 1;
! 1434:
! 1435: return 0;
! 1436: }
! 1437:
! 1438: #define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \
! 1439: if (max_delta & 0xf00) \
! 1440: FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \
! 1441: else \
! 1442: FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm))));
! 1443:
! 1444: #define TEST_WRITE_BACK() \
! 1445: if (inp_flags & WRITE_BACK) { \
! 1446: tmp_r = arg & 0xf; \
! 1447: if (reg == tmp_r) { \
! 1448: /* This can only happen for stores */ \
! 1449: /* since ldr reg, [reg, ...]! has no meaning */ \
! 1450: SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \
! 1451: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg))); \
! 1452: reg = TMP_REG3; \
! 1453: } \
! 1454: }
! 1455:
! 1456: /* Emit the necessary instructions. See can_cache above. */
! 1457: static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
! 1458: {
! 1459: int tmp_r;
! 1460: sljit_w max_delta;
! 1461: sljit_w sign;
! 1462:
! 1463: if (arg & SLJIT_IMM) {
! 1464: SLJIT_ASSERT(inp_flags & LOAD_DATA);
! 1465: return load_immediate(compiler, reg, argw);
! 1466: }
! 1467:
! 1468: SLJIT_ASSERT(arg & SLJIT_MEM);
! 1469:
! 1470: tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
! 1471: max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
! 1472:
! 1473: if ((arg & 0xf) == SLJIT_UNUSED) {
! 1474: /* Write back is not used. */
! 1475: if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta)) {
! 1476: if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
! 1477: sign = 1;
! 1478: argw = argw - compiler->cache_argw;
! 1479: }
! 1480: else {
! 1481: sign = 0;
! 1482: argw = compiler->cache_argw - argw;
! 1483: }
! 1484:
! 1485: if (max_delta & 0xf00) {
! 1486: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, argw));
! 1487: }
! 1488: else {
! 1489: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, TYPE2_TRANSFER_IMM(argw)));
! 1490: }
! 1491: return SLJIT_SUCCESS;
! 1492: }
! 1493:
! 1494: /* With write back, we can create some sophisticated loads, but
! 1495: it is hard to decide whether we should convert downward (0s) or upward (1s). */
! 1496: if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
! 1497: SLJIT_ASSERT(inp_flags & LOAD_DATA);
! 1498:
! 1499: compiler->cache_arg = SLJIT_IMM;
! 1500: compiler->cache_argw = argw;
! 1501: tmp_r = TMP_REG3;
! 1502: }
! 1503:
! 1504: FAIL_IF(load_immediate(compiler, tmp_r, argw));
! 1505: GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0);
! 1506: return SLJIT_SUCCESS;
! 1507: }
! 1508:
! 1509: /* Extended imm addressing for [reg+imm] format. */
! 1510: sign = (max_delta << 8) | 0xff;
! 1511: if (!(arg & 0xf0) && argw <= sign && argw >= -sign) {
! 1512: TEST_WRITE_BACK();
! 1513: if (argw >= 0) {
! 1514: sign = 1;
! 1515: }
! 1516: else {
! 1517: sign = 0;
! 1518: argw = -argw;
! 1519: }
! 1520:
! 1521: /* Optimization: add is 0x4, sub is 0x2. Sign is 1 for add and 0 for sub. */
! 1522: if (max_delta & 0xf00)
! 1523: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 12) | 0xa00));
! 1524: else
! 1525: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 8) | 0xc00));
! 1526:
! 1527: argw &= max_delta;
! 1528: GETPUT_ARG_DATA_TRANSFER(sign, inp_flags & WRITE_BACK, reg, tmp_r, argw);
! 1529: return SLJIT_SUCCESS;
! 1530: }
! 1531:
! 1532: if (arg & 0xf0) {
! 1533: SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
! 1534: if (inp_flags & WRITE_BACK)
! 1535: tmp_r = arg & 0xf;
! 1536: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
! 1537: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
! 1538: return SLJIT_SUCCESS;
! 1539: }
! 1540:
! 1541: if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
! 1542: SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
! 1543: argw = argw - compiler->cache_argw;
! 1544: GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, argw);
! 1545: return SLJIT_SUCCESS;
! 1546: }
! 1547:
! 1548: if (compiler->cache_arg == arg && ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta) {
! 1549: SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
! 1550: argw = compiler->cache_argw - argw;
! 1551: GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, argw);
! 1552: return SLJIT_SUCCESS;
! 1553: }
! 1554:
! 1555: if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
! 1556: TEST_WRITE_BACK();
! 1557: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
! 1558: return SLJIT_SUCCESS;
! 1559: }
! 1560:
! 1561: if (argw == next_argw && (next_arg & SLJIT_MEM)) {
! 1562: SLJIT_ASSERT(inp_flags & LOAD_DATA);
! 1563: FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
! 1564:
! 1565: compiler->cache_arg = SLJIT_IMM;
! 1566: compiler->cache_argw = argw;
! 1567:
! 1568: TEST_WRITE_BACK();
! 1569: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
! 1570: return SLJIT_SUCCESS;
! 1571: }
! 1572:
! 1573: if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
! 1574: SLJIT_ASSERT(inp_flags & LOAD_DATA);
! 1575: FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
! 1576: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf]));
! 1577:
! 1578: compiler->cache_arg = arg;
! 1579: compiler->cache_argw = argw;
! 1580:
! 1581: GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0);
! 1582: return SLJIT_SUCCESS;
! 1583: }
! 1584:
! 1585: if ((arg & 0xf) == tmp_r) {
! 1586: compiler->cache_arg = SLJIT_IMM;
! 1587: compiler->cache_argw = argw;
! 1588: tmp_r = TMP_REG3;
! 1589: }
! 1590:
! 1591: FAIL_IF(load_immediate(compiler, tmp_r, argw));
! 1592: EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
! 1593: return SLJIT_SUCCESS;
! 1594: }
! 1595:
! 1596: static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
! 1597: int dst, sljit_w dstw,
! 1598: int src1, sljit_w src1w,
! 1599: int src2, sljit_w src2w)
! 1600: {
! 1601: /* arg1 goes to TMP_REG1 or src reg
! 1602: arg2 goes to TMP_REG2, imm or src reg
! 1603: TMP_REG3 can be used for caching
! 1604: result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
! 1605:
! 1606: /* We prefers register and simple consts. */
! 1607: int dst_r;
! 1608: int src1_r;
! 1609: int src2_r = 0;
! 1610: int sugg_src2_r = TMP_REG2;
! 1611: int flags = GET_FLAGS(op) ? SET_FLAGS : 0;
! 1612:
! 1613: compiler->cache_arg = 0;
! 1614: compiler->cache_argw = 0;
! 1615:
! 1616: /* Destination check. */
! 1617: if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) {
! 1618: dst_r = dst;
! 1619: flags |= REG_DEST;
! 1620: if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
! 1621: sugg_src2_r = dst_r;
! 1622: }
! 1623: else if (dst == SLJIT_UNUSED) {
! 1624: if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
! 1625: return SLJIT_SUCCESS;
! 1626: dst_r = TMP_REG2;
! 1627: }
! 1628: else {
! 1629: SLJIT_ASSERT(dst & SLJIT_MEM);
! 1630: if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
! 1631: flags |= FAST_DEST;
! 1632: dst_r = TMP_REG2;
! 1633: }
! 1634: else {
! 1635: flags |= SLOW_DEST;
! 1636: dst_r = 0;
! 1637: }
! 1638: }
! 1639:
! 1640: /* Source 1. */
! 1641: if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3)
! 1642: src1_r = src1;
! 1643: else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
! 1644: flags |= ARGS_SWAPPED;
! 1645: src1_r = src2;
! 1646: src2 = src1;
! 1647: src2w = src1w;
! 1648: }
! 1649: else {
! 1650: if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) {
! 1651: /* The second check will generate a hit. */
! 1652: src2_r = get_immediate(src1w);
! 1653: if (src2_r) {
! 1654: flags |= ARGS_SWAPPED;
! 1655: src1 = src2;
! 1656: src1w = src2w;
! 1657: }
! 1658: if (inp_flags & ALLOW_INV_IMM) {
! 1659: src2_r = get_immediate(~src1w);
! 1660: if (src2_r) {
! 1661: flags |= ARGS_SWAPPED | INV_IMM;
! 1662: src1 = src2;
! 1663: src1w = src2w;
! 1664: }
! 1665: }
! 1666: }
! 1667:
! 1668: src1_r = 0;
! 1669: if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
! 1670: FAIL_IF(compiler->error);
! 1671: src1_r = TMP_REG1;
! 1672: }
! 1673: }
! 1674:
! 1675: /* Source 2. */
! 1676: if (src2_r == 0) {
! 1677: if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
! 1678: src2_r = src2;
! 1679: flags |= REG_SOURCE;
! 1680: if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
! 1681: dst_r = src2_r;
! 1682: }
! 1683: else do { /* do { } while(0) is used because of breaks. */
! 1684: if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) {
! 1685: src2_r = get_immediate(src2w);
! 1686: if (src2_r)
! 1687: break;
! 1688: if (inp_flags & ALLOW_INV_IMM) {
! 1689: src2_r = get_immediate(~src2w);
! 1690: if (src2_r) {
! 1691: flags |= INV_IMM;
! 1692: break;
! 1693: }
! 1694: }
! 1695: }
! 1696:
! 1697: /* src2_r is 0. */
! 1698: if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
! 1699: FAIL_IF(compiler->error);
! 1700: src2_r = sugg_src2_r;
! 1701: }
! 1702: } while (0);
! 1703: }
! 1704:
! 1705: /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero.
! 1706: If they are zero, they must not be registers. */
! 1707: if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
! 1708: if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
! 1709: SLJIT_ASSERT(!(flags & ARGS_SWAPPED));
! 1710: flags |= ARGS_SWAPPED;
! 1711: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w));
! 1712: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw));
! 1713: }
! 1714: else {
! 1715: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
! 1716: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
! 1717: }
! 1718: src1_r = TMP_REG1;
! 1719: src2_r = TMP_REG2;
! 1720: }
! 1721: else if (src1_r == 0 && src2_r == 0) {
! 1722: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
! 1723: src1_r = TMP_REG1;
! 1724: }
! 1725: else if (src1_r == 0 && dst_r == 0) {
! 1726: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
! 1727: src1_r = TMP_REG1;
! 1728: }
! 1729: else if (src2_r == 0 && dst_r == 0) {
! 1730: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
! 1731: src2_r = sugg_src2_r;
! 1732: }
! 1733:
! 1734: if (dst_r == 0)
! 1735: dst_r = TMP_REG2;
! 1736:
! 1737: if (src1_r == 0) {
! 1738: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
! 1739: src1_r = TMP_REG1;
! 1740: }
! 1741:
! 1742: if (src2_r == 0) {
! 1743: FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
! 1744: src2_r = sugg_src2_r;
! 1745: }
! 1746:
! 1747: FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
! 1748:
! 1749: if (flags & (FAST_DEST | SLOW_DEST)) {
! 1750: if (flags & FAST_DEST)
! 1751: FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
! 1752: else
! 1753: FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
! 1754: }
! 1755: return SLJIT_SUCCESS;
! 1756: }
! 1757:
! 1758: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
! 1759: {
! 1760: CHECK_ERROR();
! 1761: check_sljit_emit_op0(compiler, op);
! 1762:
! 1763: op = GET_OPCODE(op);
! 1764: switch (op) {
! 1765: case SLJIT_BREAKPOINT:
! 1766: EMIT_INSTRUCTION(DEBUGGER);
! 1767: break;
! 1768: case SLJIT_NOP:
! 1769: EMIT_INSTRUCTION(NOP);
! 1770: break;
! 1771: }
! 1772:
! 1773: return SLJIT_SUCCESS;
! 1774: }
! 1775:
! 1776: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
! 1777: int dst, sljit_w dstw,
! 1778: int src, sljit_w srcw)
! 1779: {
! 1780: CHECK_ERROR();
! 1781: check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
! 1782:
! 1783: switch (GET_OPCODE(op)) {
! 1784: case SLJIT_MOV:
! 1785: case SLJIT_MOV_UI:
! 1786: case SLJIT_MOV_SI:
! 1787: return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
! 1788:
! 1789: case SLJIT_MOV_UB:
! 1790: return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
! 1791:
! 1792: case SLJIT_MOV_SB:
! 1793: return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
! 1794:
! 1795: case SLJIT_MOV_UH:
! 1796: return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
! 1797:
! 1798: case SLJIT_MOV_SH:
! 1799: return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
! 1800:
! 1801: case SLJIT_MOVU:
! 1802: case SLJIT_MOVU_UI:
! 1803: case SLJIT_MOVU_SI:
! 1804: return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
! 1805:
! 1806: case SLJIT_MOVU_UB:
! 1807: return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
! 1808:
! 1809: case SLJIT_MOVU_SB:
! 1810: return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
! 1811:
! 1812: case SLJIT_MOVU_UH:
! 1813: return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
! 1814:
! 1815: case SLJIT_MOVU_SH:
! 1816: return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
! 1817:
! 1818: case SLJIT_NOT:
! 1819: return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
! 1820:
! 1821: case SLJIT_NEG:
! 1822: #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
! 1823: compiler->skip_checks = 1;
! 1824: #endif
! 1825: return sljit_emit_op2(compiler, SLJIT_SUB | GET_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);
! 1826:
! 1827: case SLJIT_CLZ:
! 1828: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
! 1829: }
! 1830:
! 1831: return SLJIT_SUCCESS;
! 1832: }
! 1833:
! 1834: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
! 1835: int dst, sljit_w dstw,
! 1836: int src1, sljit_w src1w,
! 1837: int src2, sljit_w src2w)
! 1838: {
! 1839: CHECK_ERROR();
! 1840: check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
! 1841:
! 1842: switch (GET_OPCODE(op)) {
! 1843: case SLJIT_ADD:
! 1844: case SLJIT_ADDC:
! 1845: case SLJIT_SUB:
! 1846: case SLJIT_SUBC:
! 1847: case SLJIT_OR:
! 1848: case SLJIT_XOR:
! 1849: return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);
! 1850:
! 1851: case SLJIT_MUL:
! 1852: return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
! 1853:
! 1854: case SLJIT_AND:
! 1855: return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);
! 1856:
! 1857: case SLJIT_SHL:
! 1858: case SLJIT_LSHR:
! 1859: case SLJIT_ASHR:
! 1860: if (src2 & SLJIT_IMM) {
! 1861: compiler->shift_imm = src2w & 0x1f;
! 1862: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);
! 1863: }
! 1864: else {
! 1865: compiler->shift_imm = 0x20;
! 1866: return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
! 1867: }
! 1868: }
! 1869:
! 1870: return SLJIT_SUCCESS;
! 1871: }
! 1872:
! 1873: /* --------------------------------------------------------------------- */
! 1874: /* Floating point operators */
! 1875: /* --------------------------------------------------------------------- */
! 1876:
! 1877: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 1878:
! 1879: /* 0 - no fpu
! 1880: 1 - vfp */
! 1881: static int arm_fpu_type = -1;
! 1882:
! 1883: static void init_compiler()
! 1884: {
! 1885: if (arm_fpu_type != -1)
! 1886: return;
! 1887:
! 1888: /* TODO: Only the OS can help to determine the correct fpu type. */
! 1889: arm_fpu_type = 1;
! 1890: }
! 1891:
! 1892: SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
! 1893: {
! 1894: if (arm_fpu_type == -1)
! 1895: init_compiler();
! 1896: return arm_fpu_type;
! 1897: }
! 1898:
! 1899: #else
! 1900:
! 1901: #define arm_fpu_type 1
! 1902:
! 1903: SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
! 1904: {
! 1905: /* Always available. */
! 1906: return 1;
! 1907: }
! 1908:
! 1909: #endif
! 1910:
! 1911: #define EMIT_FPU_DATA_TRANSFER(add, load, base, freg, offs) \
! 1912: (VSTR | ((add) << 23) | ((load) << 20) | (reg_map[base] << 16) | (freg << 12) | (offs))
! 1913: #define EMIT_FPU_OPERATION(opcode, dst, src1, src2) \
! 1914: ((opcode) | ((dst) << 12) | (src1) | ((src2) << 16))
! 1915:
! 1916: static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
! 1917: {
! 1918: SLJIT_ASSERT(arg & SLJIT_MEM);
! 1919:
! 1920: /* Fast loads and stores. */
! 1921: if ((arg & 0xf) && !(arg & 0xf0) && (argw & 0x3) == 0) {
! 1922: if (argw >= 0 && argw <= 0x3ff) {
! 1923: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, arg & 0xf, fpu_reg, argw >> 2));
! 1924: return SLJIT_SUCCESS;
! 1925: }
! 1926: if (argw < 0 && argw >= -0x3ff) {
! 1927: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, arg & 0xf, fpu_reg, (-argw) >> 2));
! 1928: return SLJIT_SUCCESS;
! 1929: }
! 1930: if (argw >= 0 && argw <= 0x3ffff) {
! 1931: SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
! 1932: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
! 1933: argw &= 0x3ff;
! 1934: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, argw >> 2));
! 1935: return SLJIT_SUCCESS;
! 1936: }
! 1937: if (argw < 0 && argw >= -0x3ffff) {
! 1938: argw = -argw;
! 1939: SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
! 1940: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
! 1941: argw &= 0x3ff;
! 1942: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG1, fpu_reg, argw >> 2));
! 1943: return SLJIT_SUCCESS;
! 1944: }
! 1945: }
! 1946:
! 1947: if (arg & 0xf0) {
! 1948: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
! 1949: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, 0));
! 1950: return SLJIT_SUCCESS;
! 1951: }
! 1952:
! 1953: if (compiler->cache_arg == arg && ((argw - compiler->cache_argw) & 0x3) == 0) {
! 1954: if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= 0x3ff) {
! 1955: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, (argw - compiler->cache_argw) >> 2));
! 1956: return SLJIT_SUCCESS;
! 1957: }
! 1958: if (((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= 0x3ff) {
! 1959: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG3, fpu_reg, (compiler->cache_argw - argw) >> 2));
! 1960: return SLJIT_SUCCESS;
! 1961: }
! 1962: }
! 1963:
! 1964: compiler->cache_arg = arg;
! 1965: compiler->cache_argw = argw;
! 1966: if (arg & 0xf) {
! 1967: FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
! 1968: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & 0xf, reg_map[TMP_REG1]));
! 1969: }
! 1970: else
! 1971: FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
! 1972:
! 1973: EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, 0));
! 1974: return SLJIT_SUCCESS;
! 1975: }
! 1976:
! 1977: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
! 1978: int dst, sljit_w dstw,
! 1979: int src, sljit_w srcw)
! 1980: {
! 1981: int dst_freg;
! 1982:
! 1983: CHECK_ERROR();
! 1984: check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
! 1985:
! 1986: compiler->cache_arg = 0;
! 1987: compiler->cache_argw = 0;
! 1988:
! 1989: if (GET_OPCODE(op) == SLJIT_FCMP) {
! 1990: if (dst > SLJIT_FLOAT_REG4) {
! 1991: FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
! 1992: dst = TMP_FREG1;
! 1993: }
! 1994: if (src > SLJIT_FLOAT_REG4) {
! 1995: FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
! 1996: src = TMP_FREG2;
! 1997: }
! 1998: EMIT_INSTRUCTION(VCMP_F64 | (dst << 12) | src);
! 1999: EMIT_INSTRUCTION(VMRS);
! 2000: return SLJIT_SUCCESS;
! 2001: }
! 2002:
! 2003: dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
! 2004:
! 2005: if (src > SLJIT_FLOAT_REG4) {
! 2006: FAIL_IF(emit_fpu_data_transfer(compiler, dst_freg, 1, src, srcw));
! 2007: src = dst_freg;
! 2008: }
! 2009:
! 2010: switch (op) {
! 2011: case SLJIT_FMOV:
! 2012: if (src != dst_freg && dst_freg != TMP_FREG1)
! 2013: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F64, dst_freg, src, 0));
! 2014: break;
! 2015: case SLJIT_FNEG:
! 2016: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F64, dst_freg, src, 0));
! 2017: break;
! 2018: case SLJIT_FABS:
! 2019: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F64, dst_freg, src, 0));
! 2020: break;
! 2021: }
! 2022:
! 2023: if (dst_freg == TMP_FREG1)
! 2024: FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
! 2025:
! 2026: return SLJIT_SUCCESS;
! 2027: }
! 2028:
! 2029: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
! 2030: int dst, sljit_w dstw,
! 2031: int src1, sljit_w src1w,
! 2032: int src2, sljit_w src2w)
! 2033: {
! 2034: int dst_freg;
! 2035:
! 2036: CHECK_ERROR();
! 2037: check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
! 2038:
! 2039: compiler->cache_arg = 0;
! 2040: compiler->cache_argw = 0;
! 2041:
! 2042: dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
! 2043:
! 2044: if (src2 > SLJIT_FLOAT_REG4) {
! 2045: FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
! 2046: src2 = TMP_FREG2;
! 2047: }
! 2048:
! 2049: if (src1 > SLJIT_FLOAT_REG4) {
! 2050: FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
! 2051: src1 = TMP_FREG1;
! 2052: }
! 2053:
! 2054: switch (op) {
! 2055: case SLJIT_FADD:
! 2056: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F64, dst_freg, src2, src1));
! 2057: break;
! 2058:
! 2059: case SLJIT_FSUB:
! 2060: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F64, dst_freg, src2, src1));
! 2061: break;
! 2062:
! 2063: case SLJIT_FMUL:
! 2064: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F64, dst_freg, src2, src1));
! 2065: break;
! 2066:
! 2067: case SLJIT_FDIV:
! 2068: EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F64, dst_freg, src2, src1));
! 2069: break;
! 2070: }
! 2071:
! 2072: if (dst_freg == TMP_FREG1)
! 2073: FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
! 2074:
! 2075: return SLJIT_SUCCESS;
! 2076: }
! 2077:
! 2078: /* --------------------------------------------------------------------- */
! 2079: /* Other instructions */
! 2080: /* --------------------------------------------------------------------- */
! 2081:
! 2082: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
! 2083: {
! 2084: int size;
! 2085:
! 2086: CHECK_ERROR();
! 2087: check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
! 2088:
! 2089: compiler->temporaries = temporaries;
! 2090: compiler->generals = generals;
! 2091:
! 2092: size = (1 + generals) * sizeof(sljit_uw);
! 2093: if (temporaries >= 4)
! 2094: size += (temporaries - 3) * sizeof(sljit_uw);
! 2095: local_size += size;
! 2096: local_size = (local_size + 7) & ~7;
! 2097: local_size -= size;
! 2098: compiler->local_size = local_size;
! 2099:
! 2100: if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
! 2101: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
! 2102: else if (dst & SLJIT_MEM) {
! 2103: if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
! 2104: return compiler->error;
! 2105: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)));
! 2106: compiler->cache_arg = 0;
! 2107: compiler->cache_argw = 0;
! 2108: return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
! 2109: }
! 2110:
! 2111: return SLJIT_SUCCESS;
! 2112: }
! 2113:
! 2114: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
! 2115: {
! 2116: CHECK_ERROR();
! 2117: check_sljit_emit_fast_return(compiler, src, srcw);
! 2118:
! 2119: if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
! 2120: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
! 2121: else if (src & SLJIT_MEM) {
! 2122: if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
! 2123: FAIL_IF(compiler->error);
! 2124: else {
! 2125: compiler->cache_arg = 0;
! 2126: compiler->cache_argw = 0;
! 2127: FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0));
! 2128: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2)));
! 2129: }
! 2130: }
! 2131: else if (src & SLJIT_IMM)
! 2132: FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
! 2133: return push_inst(compiler, BLX | RM(TMP_REG3));
! 2134: }
! 2135:
! 2136: /* --------------------------------------------------------------------- */
! 2137: /* Conditional instructions */
! 2138: /* --------------------------------------------------------------------- */
! 2139:
! 2140: static sljit_uw get_cc(int type)
! 2141: {
! 2142: switch (type) {
! 2143: case SLJIT_C_EQUAL:
! 2144: case SLJIT_C_MUL_NOT_OVERFLOW:
! 2145: case SLJIT_C_FLOAT_EQUAL:
! 2146: return 0x00000000;
! 2147:
! 2148: case SLJIT_C_NOT_EQUAL:
! 2149: case SLJIT_C_MUL_OVERFLOW:
! 2150: case SLJIT_C_FLOAT_NOT_EQUAL:
! 2151: return 0x10000000;
! 2152:
! 2153: case SLJIT_C_LESS:
! 2154: case SLJIT_C_FLOAT_LESS:
! 2155: return 0x30000000;
! 2156:
! 2157: case SLJIT_C_GREATER_EQUAL:
! 2158: case SLJIT_C_FLOAT_GREATER_EQUAL:
! 2159: return 0x20000000;
! 2160:
! 2161: case SLJIT_C_GREATER:
! 2162: case SLJIT_C_FLOAT_GREATER:
! 2163: return 0x80000000;
! 2164:
! 2165: case SLJIT_C_LESS_EQUAL:
! 2166: case SLJIT_C_FLOAT_LESS_EQUAL:
! 2167: return 0x90000000;
! 2168:
! 2169: case SLJIT_C_SIG_LESS:
! 2170: return 0xb0000000;
! 2171:
! 2172: case SLJIT_C_SIG_GREATER_EQUAL:
! 2173: return 0xa0000000;
! 2174:
! 2175: case SLJIT_C_SIG_GREATER:
! 2176: return 0xc0000000;
! 2177:
! 2178: case SLJIT_C_SIG_LESS_EQUAL:
! 2179: return 0xd0000000;
! 2180:
! 2181: case SLJIT_C_OVERFLOW:
! 2182: case SLJIT_C_FLOAT_NAN:
! 2183: return 0x60000000;
! 2184:
! 2185: case SLJIT_C_NOT_OVERFLOW:
! 2186: case SLJIT_C_FLOAT_NOT_NAN:
! 2187: return 0x70000000;
! 2188:
! 2189: default: /* SLJIT_JUMP */
! 2190: return 0xe0000000;
! 2191: }
! 2192: }
! 2193:
! 2194: SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
! 2195: {
! 2196: struct sljit_label *label;
! 2197:
! 2198: CHECK_ERROR_PTR();
! 2199: check_sljit_emit_label(compiler);
! 2200:
! 2201: if (compiler->last_label && compiler->last_label->size == compiler->size)
! 2202: return compiler->last_label;
! 2203:
! 2204: label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
! 2205: PTR_FAIL_IF(!label);
! 2206: set_label(label, compiler);
! 2207: return label;
! 2208: }
! 2209:
! 2210: SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
! 2211: {
! 2212: struct sljit_jump *jump;
! 2213:
! 2214: CHECK_ERROR_PTR();
! 2215: check_sljit_emit_jump(compiler, type);
! 2216:
! 2217: jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
! 2218: PTR_FAIL_IF(!jump);
! 2219: set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
! 2220: type &= 0xff;
! 2221:
! 2222: /* In ARM, we don't need to touch the arguments. */
! 2223: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 2224: if (type >= SLJIT_FAST_CALL)
! 2225: PTR_FAIL_IF(prepare_blx(compiler));
! 2226: PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0,
! 2227: type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
! 2228:
! 2229: if (jump->flags & SLJIT_REWRITABLE_JUMP) {
! 2230: jump->addr = compiler->size;
! 2231: compiler->patches++;
! 2232: }
! 2233:
! 2234: if (type >= SLJIT_FAST_CALL) {
! 2235: jump->flags |= IS_BL;
! 2236: PTR_FAIL_IF(emit_blx(compiler));
! 2237: }
! 2238:
! 2239: if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
! 2240: jump->addr = compiler->size;
! 2241: #else
! 2242: if (type >= SLJIT_FAST_CALL)
! 2243: jump->flags |= IS_BL;
! 2244: PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
! 2245: PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));
! 2246: jump->addr = compiler->size;
! 2247: #endif
! 2248: return jump;
! 2249: }
! 2250:
! 2251: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
! 2252: {
! 2253: struct sljit_jump *jump;
! 2254:
! 2255: CHECK_ERROR();
! 2256: check_sljit_emit_ijump(compiler, type, src, srcw);
! 2257:
! 2258: /* In ARM, we don't need to touch the arguments. */
! 2259: if (src & SLJIT_IMM) {
! 2260: jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
! 2261: FAIL_IF(!jump);
! 2262: set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
! 2263: jump->u.target = srcw;
! 2264:
! 2265: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 2266: if (type >= SLJIT_FAST_CALL)
! 2267: FAIL_IF(prepare_blx(compiler));
! 2268: FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
! 2269: if (type >= SLJIT_FAST_CALL)
! 2270: FAIL_IF(emit_blx(compiler));
! 2271: #else
! 2272: FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
! 2273: FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
! 2274: #endif
! 2275: jump->addr = compiler->size;
! 2276: }
! 2277: else {
! 2278: if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
! 2279: return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
! 2280:
! 2281: SLJIT_ASSERT(src & SLJIT_MEM);
! 2282: FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
! 2283: return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
! 2284: }
! 2285:
! 2286: return SLJIT_SUCCESS;
! 2287: }
! 2288:
! 2289: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
! 2290: {
! 2291: int reg;
! 2292: sljit_uw cc;
! 2293:
! 2294: CHECK_ERROR();
! 2295: check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
! 2296:
! 2297: if (dst == SLJIT_UNUSED)
! 2298: return SLJIT_SUCCESS;
! 2299:
! 2300: cc = get_cc(type);
! 2301: if (GET_OPCODE(op) == SLJIT_OR) {
! 2302: if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
! 2303: EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
! 2304: if (op & SLJIT_SET_E)
! 2305: return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst)));
! 2306: return SLJIT_SUCCESS;
! 2307: }
! 2308:
! 2309: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0));
! 2310: EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
! 2311: #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
! 2312: compiler->skip_checks = 1;
! 2313: #endif
! 2314: return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw);
! 2315: }
! 2316:
! 2317: reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
! 2318:
! 2319: EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0));
! 2320: EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
! 2321:
! 2322: if (reg == TMP_REG2)
! 2323: return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
! 2324: return SLJIT_SUCCESS;
! 2325: }
! 2326:
! 2327: SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
! 2328: {
! 2329: struct sljit_const *const_;
! 2330: int reg;
! 2331:
! 2332: CHECK_ERROR_PTR();
! 2333: check_sljit_emit_const(compiler, dst, dstw, init_value);
! 2334:
! 2335: const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
! 2336: PTR_FAIL_IF(!const_);
! 2337:
! 2338: reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
! 2339:
! 2340: #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
! 2341: PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
! 2342: compiler->patches++;
! 2343: #else
! 2344: PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
! 2345: #endif
! 2346: set_const(const_, compiler);
! 2347:
! 2348: if (reg == TMP_REG2 && dst != SLJIT_UNUSED)
! 2349: if (emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0))
! 2350: return NULL;
! 2351: return const_;
! 2352: }
! 2353:
! 2354: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
! 2355: {
! 2356: inline_set_jump_addr(addr, new_addr, 1);
! 2357: }
! 2358:
! 2359: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
! 2360: {
! 2361: inline_set_const(addr, new_constant, 1);
! 2362: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>