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