--- embedaddon/pcre/sljit/sljitNativeARM_Thumb2.c 2012/02/21 23:05:52 1.1.1.1 +++ embedaddon/pcre/sljit/sljitNativeARM_Thumb2.c 2012/02/21 23:50:25 1.1.1.2 @@ -1,7 +1,7 @@ /* * 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 * permitted provided that the following conditions are met: @@ -26,7 +26,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() { - return "arm-thumb2"; + return "ARM-Thumb2" SLJIT_CPUINFO; } /* Last register + 1. */ @@ -38,7 +38,7 @@ SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_p #define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) #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] = { 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 }; @@ -122,9 +122,11 @@ typedef sljit_ui sljit_ins; #define LSR_W 0xfa20f000 #define LSR_WI 0xea4f0010 #define MOV 0x4600 +#define MOVS 0x0000 #define MOVSI 0x2000 #define MOVT 0xf2c00000 #define MOVW 0xf2400000 +#define MOV_W 0xea4f0000 #define MOV_WI 0xf04f0000 #define MUL 0xfb00f000 #define MVNS 0x43c0 @@ -158,6 +160,7 @@ typedef sljit_ui sljit_ins; #define SXTH 0xb200 #define SXTH_W 0xfa0ff080 #define TST 0x4200 +#define UMULL 0xfba00000 #define UXTB 0xb2c0 #define UXTB_W 0xfa5ff080 #define UXTH 0xb280 @@ -616,6 +619,13 @@ static int emit_op_imm(struct sljit_compiler *compiler case SLJIT_SHL: if (flags & ARG2_IMM) { 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)) 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)); @@ -624,6 +634,13 @@ static int emit_op_imm(struct sljit_compiler *compiler case SLJIT_LSHR: if (flags & ARG2_IMM) { 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)) 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)); @@ -632,6 +649,13 @@ static int emit_op_imm(struct sljit_compiler *compiler case SLJIT_ASHR: if (flags & ARG2_IMM) { 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)) 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)); @@ -1077,36 +1101,36 @@ static SLJIT_INLINE int emit_op_mem(struct sljit_compi 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; sljit_ins push; 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->generals = generals; + compiler->saveds = saveds; push = (1 << 4); - if (generals >= 5) + if (saveds >= 5) push |= 1 << 11; - if (generals >= 4) + if (saveds >= 4) push |= 1 << 10; - if (generals >= 3) + if (saveds >= 3) push |= 1 << 8; - if (generals >= 2) + if (saveds >= 2) push |= 1 << 7; - if (generals >= 1) + if (saveds >= 1) push |= 1 << 6; if (temporaries >= 5) push |= 1 << 5; - FAIL_IF(generals >= 3 + FAIL_IF(saveds >= 3 ? push_inst32(compiler, PUSH_W | (1 << 14) | push) : push_inst16(compiler, PUSH | push)); /* Stack must be aligned to 8 bytes: */ - size = (3 + generals) * sizeof(sljit_uw); + size = (3 + saveds) * sizeof(sljit_uw); local_size += size; local_size = (local_size + 7) & ~7; local_size -= size; @@ -1119,45 +1143,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct s } 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) - 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) - 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; } -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; 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->generals = generals; + compiler->saveds = saveds; - size = (3 + generals) * sizeof(sljit_uw); + size = (3 + saveds) * sizeof(sljit_uw); local_size += size; local_size = (local_size + 7) & ~7; local_size -= 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; CHECK_ERROR(); - check_sljit_emit_return(compiler, src, srcw); + check_sljit_emit_return(compiler, op, src, srcw); - if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) { - 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)); - } + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); if (compiler->local_size > 0) { if (compiler->local_size <= (127 << 2)) @@ -1167,19 +1186,19 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct } pop = (1 << 4); - if (compiler->generals >= 5) + if (compiler->saveds >= 5) pop |= 1 << 11; - if (compiler->generals >= 4) + if (compiler->saveds >= 4) pop |= 1 << 10; - if (compiler->generals >= 3) + if (compiler->saveds >= 3) pop |= 1 << 8; - if (compiler->generals >= 2) + if (compiler->saveds >= 2) pop |= 1 << 7; - if (compiler->generals >= 1) + if (compiler->saveds >= 1) pop |= 1 << 6; if (compiler->temporaries >= 5) pop |= 1 << 5; - return compiler->generals >= 3 + return compiler->saveds >= 3 ? push_inst32(compiler, POP_W | (1 << 15) | pop) : push_inst16(compiler, POP | pop); } @@ -1188,6 +1207,21 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct /* 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) { CHECK_ERROR(); @@ -1201,6 +1235,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct slj case SLJIT_NOP: push_inst16(compiler, NOP); 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; @@ -1412,6 +1472,24 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj 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 */ /* --------------------------------------------------------------------- */ @@ -1567,17 +1645,17 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sl /* 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 args, int temporaries, int saveds, int local_size) { int size; CHECK_ERROR(); - check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); compiler->temporaries = temporaries; - compiler->generals = generals; + compiler->saveds = saveds; - size = (3 + generals) * sizeof(sljit_uw); + size = (3 + saveds) * sizeof(sljit_uw); local_size += size; local_size = (local_size + 7) & ~7; local_size -= size;