| version 1.1.1.1, 2012/02/21 23:05:52 | version 1.1.1.3, 2012/10/09 09:19:18 | 
| Line 1 | Line 1 | 
 | /* | /* | 
 | *    Stack-less Just-In-Time compiler | *    Stack-less Just-In-Time compiler | 
 | * | * | 
| *    Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. | *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. | 
 | * | * | 
 | * Redistribution and use in source and binary forms, with or without modification, are | * Redistribution and use in source and binary forms, with or without modification, are | 
 | * permitted provided that the following conditions are met: | * permitted provided that the following conditions are met: | 
| Line 26 | Line 26 | 
 |  |  | 
 | SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() | SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() | 
 | { | { | 
| return "arm-thumb2"; | return "ARM-Thumb2" SLJIT_CPUINFO; | 
 | } | } | 
 |  |  | 
 | /* Last register + 1. */ | /* Last register + 1. */ | 
| Line 38  SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p | Line 38  SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p | 
 | #define TMP_FREG1       (SLJIT_FLOAT_REG4 + 1) | #define TMP_FREG1       (SLJIT_FLOAT_REG4 + 1) | 
 | #define TMP_FREG2       (SLJIT_FLOAT_REG4 + 2) | #define TMP_FREG2       (SLJIT_FLOAT_REG4 + 2) | 
 |  |  | 
| /* See sljit_emit_enter if you want to change them. */ | /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ | 
 | static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { | static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { | 
 | 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 | 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 | 
 | }; | }; | 
| Line 122  typedef sljit_ui sljit_ins; | Line 122  typedef sljit_ui sljit_ins; | 
 | #define LSR_W           0xfa20f000 | #define LSR_W           0xfa20f000 | 
 | #define LSR_WI          0xea4f0010 | #define LSR_WI          0xea4f0010 | 
 | #define MOV             0x4600 | #define MOV             0x4600 | 
 |  | #define MOVS            0x0000 | 
 | #define MOVSI           0x2000 | #define MOVSI           0x2000 | 
 | #define MOVT            0xf2c00000 | #define MOVT            0xf2c00000 | 
 | #define MOVW            0xf2400000 | #define MOVW            0xf2400000 | 
 |  | #define MOV_W           0xea4f0000 | 
 | #define MOV_WI          0xf04f0000 | #define MOV_WI          0xf04f0000 | 
 | #define MUL             0xfb00f000 | #define MUL             0xfb00f000 | 
 | #define MVNS            0x43c0 | #define MVNS            0x43c0 | 
| Line 158  typedef sljit_ui sljit_ins; | Line 160  typedef sljit_ui sljit_ins; | 
 | #define SXTH            0xb200 | #define SXTH            0xb200 | 
 | #define SXTH_W          0xfa0ff080 | #define SXTH_W          0xfa0ff080 | 
 | #define TST             0x4200 | #define TST             0x4200 | 
 |  | #define UMULL           0xfba00000 | 
 | #define UXTB            0xb2c0 | #define UXTB            0xb2c0 | 
 | #define UXTB_W          0xfa5ff080 | #define UXTB_W          0xfa5ff080 | 
 | #define UXTH            0xb280 | #define UXTH            0xb280 | 
| Line 512  static int emit_op_imm(struct sljit_compiler *compiler | Line 515  static int emit_op_imm(struct sljit_compiler *compiler | 
 | arg1 must be register, TMP_REG1, imm | arg1 must be register, TMP_REG1, imm | 
 | arg2 must be register, TMP_REG2, imm */ | arg2 must be register, TMP_REG2, imm */ | 
 | int reg; | int reg; | 
| sljit_uw imm; | sljit_uw imm, negated_imm; | 
 |  |  | 
 | if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { | if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { | 
 | /* Both are immediates. */ | /* Both are immediates. */ | 
| Line 539  static int emit_op_imm(struct sljit_compiler *compiler | Line 542  static int emit_op_imm(struct sljit_compiler *compiler | 
 | /* No form with immediate operand. */ | /* No form with immediate operand. */ | 
 | break; | break; | 
 | case SLJIT_ADD: | case SLJIT_ADD: | 
 |  | negated_imm = (sljit_uw)-(sljit_w)imm; | 
 | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { | 
 | if (imm <= 0x7) | if (imm <= 0x7) | 
 | return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); | return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); | 
| if (reg == dst && imm <= 0xff) | if (negated_imm <= 0x7) | 
| return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); | return push_inst16(compiler, SUBSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg)); | 
|  | if (reg == dst) { | 
|  | if (imm <= 0xff) | 
|  | return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); | 
|  | if (negated_imm <= 0xff) | 
|  | return push_inst16(compiler, SUBSI8 | IMM8(negated_imm) | RDN3(dst)); | 
|  | } | 
 | } | } | 
| if (imm <= 0xfff && !(flags & SET_FLAGS)) | if (!(flags & SET_FLAGS)) { | 
| return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); | if (imm <= 0xfff) | 
|  | return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); | 
|  | if (negated_imm <= 0xfff) | 
|  | return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(negated_imm)); | 
|  | } | 
 | imm = get_imm(imm); | imm = get_imm(imm); | 
 | if (imm != INVALID_IMM) | if (imm != INVALID_IMM) | 
 | return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); | return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); | 
| Line 558  static int emit_op_imm(struct sljit_compiler *compiler | Line 572  static int emit_op_imm(struct sljit_compiler *compiler | 
 | break; | break; | 
 | case SLJIT_SUB: | case SLJIT_SUB: | 
 | if (flags & ARG2_IMM) { | if (flags & ARG2_IMM) { | 
 |  | negated_imm = (sljit_uw)-(sljit_w)imm; | 
 | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { | 
 | if (imm <= 0x7) | if (imm <= 0x7) | 
 | return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); | return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); | 
| if (imm <= 0xff) { | if (negated_imm <= 0x7) | 
| if (reg == dst) | return push_inst16(compiler, ADDSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg)); | 
|  | if (reg == dst) { | 
|  | if (imm <= 0xff) | 
 | return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); | return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); | 
| if (flags & UNUSED_RETURN) | if (negated_imm <= 0xff) | 
| return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); | return push_inst16(compiler, ADDSI8 | IMM8(negated_imm) | RDN3(dst)); | 
 | } | } | 
 |  | if (imm <= 0xff && (flags & UNUSED_RETURN)) | 
 |  | return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); | 
 | } | } | 
| if (imm <= 0xfff && !(flags & SET_FLAGS)) | if (!(flags & SET_FLAGS)) { | 
| return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); | if (imm <= 0xfff) | 
|  | return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); | 
|  | if (negated_imm <= 0xfff) | 
|  | return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(negated_imm)); | 
|  | } | 
 | imm = get_imm(imm); | imm = get_imm(imm); | 
 | if (imm != INVALID_IMM) | if (imm != INVALID_IMM) | 
 | return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); | return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); | 
| Line 616  static int emit_op_imm(struct sljit_compiler *compiler | Line 639  static int emit_op_imm(struct sljit_compiler *compiler | 
 | case SLJIT_SHL: | case SLJIT_SHL: | 
 | if (flags & ARG2_IMM) { | if (flags & ARG2_IMM) { | 
 | imm &= 0x1f; | imm &= 0x1f; | 
 |  | if (imm == 0) { | 
 |  | if (!(flags & SET_FLAGS)) | 
 |  | return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); | 
 |  | if (IS_2_LO_REGS(dst, reg)) | 
 |  | return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); | 
 |  | return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); | 
 |  | } | 
 | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | 
 | return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); | return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); | 
 | return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | 
| Line 624  static int emit_op_imm(struct sljit_compiler *compiler | Line 654  static int emit_op_imm(struct sljit_compiler *compiler | 
 | case SLJIT_LSHR: | case SLJIT_LSHR: | 
 | if (flags & ARG2_IMM) { | if (flags & ARG2_IMM) { | 
 | imm &= 0x1f; | imm &= 0x1f; | 
 |  | if (imm == 0) { | 
 |  | if (!(flags & SET_FLAGS)) | 
 |  | return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); | 
 |  | if (IS_2_LO_REGS(dst, reg)) | 
 |  | return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); | 
 |  | return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); | 
 |  | } | 
 | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | 
 | return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); | return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); | 
 | return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | 
| Line 632  static int emit_op_imm(struct sljit_compiler *compiler | Line 669  static int emit_op_imm(struct sljit_compiler *compiler | 
 | case SLJIT_ASHR: | case SLJIT_ASHR: | 
 | if (flags & ARG2_IMM) { | if (flags & ARG2_IMM) { | 
 | imm &= 0x1f; | imm &= 0x1f; | 
 |  | if (imm == 0) { | 
 |  | if (!(flags & SET_FLAGS)) | 
 |  | return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); | 
 |  | if (IS_2_LO_REGS(dst, reg)) | 
 |  | return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); | 
 |  | return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); | 
 |  | } | 
 | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) | 
 | return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); | return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); | 
 | return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); | 
| Line 1077  static SLJIT_INLINE int emit_op_mem(struct sljit_compi | Line 1121  static SLJIT_INLINE int emit_op_mem(struct sljit_compi | 
 | return getput_arg(compiler, flags, reg, arg, argw, 0, 0); | return getput_arg(compiler, flags, reg, arg, argw, 0, 0); | 
 | } | } | 
 |  |  | 
| SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) | 
 | { | { | 
 | int size; | int size; | 
 | sljit_ins push; | sljit_ins push; | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
| check_sljit_emit_enter(compiler, args, temporaries, generals, local_size); | check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); | 
 |  |  | 
 | compiler->temporaries = temporaries; | compiler->temporaries = temporaries; | 
| compiler->generals = generals; | compiler->saveds = saveds; | 
|  | #if (defined SLJIT_DEBUG && SLJIT_DEBUG) | 
|  | compiler->logical_local_size = local_size; | 
|  | #endif | 
 |  |  | 
 | push = (1 << 4); | push = (1 << 4); | 
| if (generals >= 5) | if (saveds >= 5) | 
 | push |= 1 << 11; | push |= 1 << 11; | 
| if (generals >= 4) | if (saveds >= 4) | 
 | push |= 1 << 10; | push |= 1 << 10; | 
| if (generals >= 3) | if (saveds >= 3) | 
 | push |= 1 << 8; | push |= 1 << 8; | 
| if (generals >= 2) | if (saveds >= 2) | 
 | push |= 1 << 7; | push |= 1 << 7; | 
| if (generals >= 1) | if (saveds >= 1) | 
 | push |= 1 << 6; | push |= 1 << 6; | 
 | if (temporaries >= 5) | if (temporaries >= 5) | 
 | push |= 1 << 5; | push |= 1 << 5; | 
| FAIL_IF(generals >= 3 | FAIL_IF(saveds >= 3 | 
 | ? push_inst32(compiler, PUSH_W | (1 << 14) | push) | ? push_inst32(compiler, PUSH_W | (1 << 14) | push) | 
 | : push_inst16(compiler, PUSH | push)); | : push_inst16(compiler, PUSH | push)); | 
 |  |  | 
 | /* Stack must be aligned to 8 bytes: */ | /* Stack must be aligned to 8 bytes: */ | 
| size = (3 + generals) * sizeof(sljit_uw); | size = (3 + saveds) * sizeof(sljit_uw); | 
 | local_size += size; | local_size += size; | 
 | local_size = (local_size + 7) & ~7; | local_size = (local_size + 7) & ~7; | 
 | local_size -= size; | local_size -= size; | 
| Line 1119  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s | Line 1166  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s | 
 | } | } | 
 |  |  | 
 | if (args >= 1) | if (args >= 1) | 
| FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG1, SLJIT_TEMPORARY_REG1))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1))); | 
 | if (args >= 2) | if (args >= 2) | 
| FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG2, SLJIT_TEMPORARY_REG2))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2))); | 
 | if (args >= 3) | if (args >= 3) | 
| FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_GENERAL_REG3, SLJIT_TEMPORARY_REG3))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3))); | 
 |  |  | 
 | return SLJIT_SUCCESS; | return SLJIT_SUCCESS; | 
 | } | } | 
 |  |  | 
| SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) | SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) | 
 | { | { | 
 | int size; | int size; | 
 |  |  | 
 | CHECK_ERROR_VOID(); | CHECK_ERROR_VOID(); | 
| check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); | check_sljit_set_context(compiler, args, temporaries, saveds, local_size); | 
 |  |  | 
 | compiler->temporaries = temporaries; | compiler->temporaries = temporaries; | 
| compiler->generals = generals; | compiler->saveds = saveds; | 
|  | #if (defined SLJIT_DEBUG && SLJIT_DEBUG) | 
|  | compiler->logical_local_size = local_size; | 
|  | #endif | 
 |  |  | 
| size = (3 + generals) * sizeof(sljit_uw); | size = (3 + saveds) * sizeof(sljit_uw); | 
 | local_size += size; | local_size += size; | 
 | local_size = (local_size + 7) & ~7; | local_size = (local_size + 7) & ~7; | 
 | local_size -= size; | local_size -= size; | 
 | compiler->local_size = local_size; | compiler->local_size = local_size; | 
 | } | } | 
 |  |  | 
| SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw) | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) | 
 | { | { | 
 | sljit_ins pop; | sljit_ins pop; | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
| check_sljit_emit_return(compiler, src, srcw); | check_sljit_emit_return(compiler, op, src, srcw); | 
|  | ADJUST_LOCAL_OFFSET(src, srcw); | 
 |  |  | 
| if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) { | FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); | 
| if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REG3) |  | 
| FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_RETURN_REG, src))); |  | 
| else |  | 
| FAIL_IF(emit_op_mem(compiler, WORD_SIZE, SLJIT_RETURN_REG, src, srcw)); |  | 
| } |  | 
 |  |  | 
 | if (compiler->local_size > 0) { | if (compiler->local_size > 0) { | 
 | if (compiler->local_size <= (127 << 2)) | if (compiler->local_size <= (127 << 2)) | 
| Line 1167  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct | Line 1213  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct | 
 | } | } | 
 |  |  | 
 | pop = (1 << 4); | pop = (1 << 4); | 
| if (compiler->generals >= 5) | if (compiler->saveds >= 5) | 
 | pop |= 1 << 11; | pop |= 1 << 11; | 
| if (compiler->generals >= 4) | if (compiler->saveds >= 4) | 
 | pop |= 1 << 10; | pop |= 1 << 10; | 
| if (compiler->generals >= 3) | if (compiler->saveds >= 3) | 
 | pop |= 1 << 8; | pop |= 1 << 8; | 
| if (compiler->generals >= 2) | if (compiler->saveds >= 2) | 
 | pop |= 1 << 7; | pop |= 1 << 7; | 
| if (compiler->generals >= 1) | if (compiler->saveds >= 1) | 
 | pop |= 1 << 6; | pop |= 1 << 6; | 
 | if (compiler->temporaries >= 5) | if (compiler->temporaries >= 5) | 
 | pop |= 1 << 5; | pop |= 1 << 5; | 
| return compiler->generals >= 3 | return compiler->saveds >= 3 | 
 | ? push_inst32(compiler, POP_W | (1 << 15) | pop) | ? push_inst32(compiler, POP_W | (1 << 15) | pop) | 
 | : push_inst16(compiler, POP | pop); | : push_inst16(compiler, POP | pop); | 
 | } | } | 
| Line 1188  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct | Line 1234  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct | 
 | /*  Operators                                                            */ | /*  Operators                                                            */ | 
 | /* --------------------------------------------------------------------- */ | /* --------------------------------------------------------------------- */ | 
 |  |  | 
 |  | #ifdef __cplusplus | 
 |  | extern "C" { | 
 |  | #endif | 
 |  |  | 
 |  | #if defined(__GNUC__) | 
 |  | extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator); | 
 |  | extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator); | 
 |  | #else | 
 |  | #error "Software divmod functions are needed" | 
 |  | #endif | 
 |  |  | 
 |  | #ifdef __cplusplus | 
 |  | } | 
 |  | #endif | 
 |  |  | 
 | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) | 
 | { | { | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
| Line 1201  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj | Line 1262  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj | 
 | case SLJIT_NOP: | case SLJIT_NOP: | 
 | push_inst16(compiler, NOP); | push_inst16(compiler, NOP); | 
 | break; | break; | 
 |  | case SLJIT_UMUL: | 
 |  | case SLJIT_SMUL: | 
 |  | return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) | 
 |  | | (reg_map[SLJIT_TEMPORARY_REG2] << 8) | 
 |  | | (reg_map[SLJIT_TEMPORARY_REG1] << 12) | 
 |  | | (reg_map[SLJIT_TEMPORARY_REG1] << 16) | 
 |  | | reg_map[SLJIT_TEMPORARY_REG2]); | 
 |  | case SLJIT_UDIV: | 
 |  | case SLJIT_SDIV: | 
 |  | if (compiler->temporaries >= 4) { | 
 |  | FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); | 
 |  | FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); | 
 |  | } else if (compiler->temporaries >= 3) | 
 |  | FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); | 
 |  | #if defined(__GNUC__) | 
 |  | FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, | 
 |  | (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); | 
 |  | #else | 
 |  | #error "Software divmod functions are needed" | 
 |  | #endif | 
 |  | if (compiler->temporaries >= 4) { | 
 |  | FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); | 
 |  | return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); | 
 |  | } else if (compiler->temporaries >= 3) | 
 |  | return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); | 
 |  | return SLJIT_SUCCESS; | 
 | } | } | 
 |  |  | 
 | return SLJIT_SUCCESS; | return SLJIT_SUCCESS; | 
| Line 1214  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj | Line 1301  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
 | check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); | check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); | 
 |  | ADJUST_LOCAL_OFFSET(dst, dstw); | 
 |  | ADJUST_LOCAL_OFFSET(src, srcw); | 
 |  |  | 
 | compiler->cache_arg = 0; | compiler->cache_arg = 0; | 
 | compiler->cache_argw = 0; | compiler->cache_argw = 0; | 
| Line 1342  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj | Line 1431  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
 | check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); | check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); | 
 |  | ADJUST_LOCAL_OFFSET(dst, dstw); | 
 |  | ADJUST_LOCAL_OFFSET(src1, src1w); | 
 |  | ADJUST_LOCAL_OFFSET(src2, src2w); | 
 |  |  | 
 | compiler->cache_arg = 0; | compiler->cache_arg = 0; | 
 | compiler->cache_argw = 0; | compiler->cache_argw = 0; | 
| Line 1412  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj | Line 1504  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj | 
 | return SLJIT_SUCCESS; | return SLJIT_SUCCESS; | 
 | } | } | 
 |  |  | 
 |  | SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) | 
 |  | { | 
 |  | check_sljit_get_register_index(reg); | 
 |  | return reg_map[reg]; | 
 |  | } | 
 |  |  | 
 |  | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, | 
 |  | void *instruction, int size) | 
 |  | { | 
 |  | CHECK_ERROR(); | 
 |  | check_sljit_emit_op_custom(compiler, instruction, size); | 
 |  | SLJIT_ASSERT(size == 2 || size == 4); | 
 |  |  | 
 |  | if (size == 2) | 
 |  | return push_inst16(compiler, *(sljit_uh*)instruction); | 
 |  | return push_inst32(compiler, *(sljit_ins*)instruction); | 
 |  | } | 
 |  |  | 
 | /* --------------------------------------------------------------------- */ | /* --------------------------------------------------------------------- */ | 
 | /*  Floating point operators                                             */ | /*  Floating point operators                                             */ | 
 | /* --------------------------------------------------------------------- */ | /* --------------------------------------------------------------------- */ | 
| Line 1567  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sl | Line 1677  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sl | 
 | /*  Other instructions                                                   */ | /*  Other instructions                                                   */ | 
 | /* --------------------------------------------------------------------- */ | /* --------------------------------------------------------------------- */ | 
 |  |  | 
| 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) | SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw) | 
 | { | { | 
 | int size; |  | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
| check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size); | check_sljit_emit_fast_enter(compiler, dst, dstw); | 
|  | ADJUST_LOCAL_OFFSET(dst, dstw); | 
 |  |  | 
 | compiler->temporaries = temporaries; |  | 
 | compiler->generals = generals; |  | 
 |  |  | 
 | size = (3 + generals) * sizeof(sljit_uw); |  | 
 | local_size += size; |  | 
 | local_size = (local_size + 7) & ~7; |  | 
 | local_size -= size; |  | 
 | compiler->local_size = local_size; |  | 
 |  |  | 
 | if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) | if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) | 
 | return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); | return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); | 
 | else if (dst & SLJIT_MEM) { | else if (dst & SLJIT_MEM) { | 
| Line 1601  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st | Line 1701  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(st | 
 | { | { | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
 | check_sljit_emit_fast_return(compiler, src, srcw); | check_sljit_emit_fast_return(compiler, src, srcw); | 
 |  | ADJUST_LOCAL_OFFSET(src, srcw); | 
 |  |  | 
 | if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) | if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) | 
 | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); | FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); | 
| Line 1732  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s | Line 1833  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
 | check_sljit_emit_ijump(compiler, type, src, srcw); | check_sljit_emit_ijump(compiler, type, src, srcw); | 
 |  | ADJUST_LOCAL_OFFSET(src, srcw); | 
 |  |  | 
 | /* In ARM, we don't need to touch the arguments. */ | /* In ARM, we don't need to touch the arguments. */ | 
 | if (src & SLJIT_IMM) { | if (src & SLJIT_IMM) { | 
| Line 1762  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str | Line 1864  SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str | 
 |  |  | 
 | CHECK_ERROR(); | CHECK_ERROR(); | 
 | check_sljit_emit_cond_value(compiler, op, dst, dstw, type); | check_sljit_emit_cond_value(compiler, op, dst, dstw, type); | 
 |  | ADJUST_LOCAL_OFFSET(dst, dstw); | 
 |  |  | 
 | if (dst == SLJIT_UNUSED) | if (dst == SLJIT_UNUSED) | 
 | return SLJIT_SUCCESS; | return SLJIT_SUCCESS; | 
| Line 1809  SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi | Line 1912  SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi | 
 |  |  | 
 | CHECK_ERROR_PTR(); | CHECK_ERROR_PTR(); | 
 | check_sljit_emit_const(compiler, dst, dstw, init_value); | check_sljit_emit_const(compiler, dst, dstw, init_value); | 
 |  | ADJUST_LOCAL_OFFSET(dst, dstw); | 
 |  |  | 
 | const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); | const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); | 
 | PTR_FAIL_IF(!const_); | PTR_FAIL_IF(!const_); |