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