Annotation of embedaddon/pcre/sljit/sljitNativeSPARC_common.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Stack-less Just-In-Time compiler
3: *
4: * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without modification, are
7: * permitted provided that the following conditions are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright notice, this list of
10: * conditions and the following disclaimer.
11: *
12: * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13: * of conditions and the following disclaimer in the documentation and/or other materials
14: * provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19: * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
28: {
29: return "SPARC" SLJIT_CPUINFO;
30: }
31:
32: /* Length of an instruction word
33: Both for sparc-32 and sparc-64 */
34: typedef sljit_ui sljit_ins;
35:
36: static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
37: {
38: #if defined(__SUNPRO_C) && __SUNPRO_C < 0x590
39: __asm (
40: /* if (from == to) return */
41: "cmp %i0, %i1\n"
42: "be .leave\n"
43: "nop\n"
44:
45: /* loop until from >= to */
46: ".mainloop:\n"
47: "flush %i0\n"
48: "add %i0, 8, %i0\n"
49: "cmp %i0, %i1\n"
50: "bcs .mainloop\n"
51: "nop\n"
52:
53: /* The comparison was done above. */
54: "bne .leave\n"
55: /* nop is not necessary here, since the
56: sub operation has no side effect. */
57: "sub %i0, 4, %i0\n"
58: "flush %i0\n"
59: ".leave:"
60: );
61: #else
62: if (SLJIT_UNLIKELY(from == to))
63: return;
64:
65: do {
66: __asm__ volatile (
67: "flush %0\n"
68: : : "r"(from)
69: );
70: /* Operates at least on doubleword. */
71: from += 2;
72: } while (from < to);
73:
74: if (from == to) {
75: /* Flush the last word. */
76: from --;
77: __asm__ volatile (
78: "flush %0\n"
79: : : "r"(from)
80: );
81: }
82: #endif
83: }
84:
85: /* TMP_REG2 is not used by getput_arg */
86: #define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
87: #define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
88: #define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
89: #define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
90: #define LINK_REG (SLJIT_NO_REGISTERS + 5)
91:
92: #define TMP_FREG1 (0)
93: #define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
94:
95: static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 7] = {
96: 0, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 14, 1, 24, 25, 26, 15
97: };
98:
99: /* --------------------------------------------------------------------- */
100: /* Instrucion forms */
101: /* --------------------------------------------------------------------- */
102:
103: #define D(d) (reg_map[d] << 25)
104: #define DA(d) ((d) << 25)
105: #define S1(s1) (reg_map[s1] << 14)
106: #define S2(s2) (reg_map[s2])
107: #define S1A(s1) ((s1) << 14)
108: #define S2A(s2) (s2)
109: #define IMM_ARG 0x2000
110: #define DOP(op) ((op) << 5)
111: #define IMM(imm) (((imm) & 0x1fff) | IMM_ARG)
112:
113: #define DR(dr) (reg_map[dr])
114: #define OPC1(opcode) ((opcode) << 30)
115: #define OPC2(opcode) ((opcode) << 22)
116: #define OPC3(opcode) ((opcode) << 19)
117: #define SET_FLAGS OPC3(0x10)
118:
119: #define ADD (OPC1(0x2) | OPC3(0x00))
120: #define ADDC (OPC1(0x2) | OPC3(0x08))
121: #define AND (OPC1(0x2) | OPC3(0x01))
122: #define ANDN (OPC1(0x2) | OPC3(0x05))
123: #define CALL (OPC1(0x1))
124: #define FABSS (OPC1(0x2) | OPC3(0x34) | DOP(0x09))
125: #define FADDD (OPC1(0x2) | OPC3(0x34) | DOP(0x42))
126: #define FADDS (OPC1(0x2) | OPC3(0x34) | DOP(0x41))
127: #define FCMPD (OPC1(0x2) | OPC3(0x35) | DOP(0x52))
128: #define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51))
129: #define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e))
130: #define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d))
131: #define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01))
132: #define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a))
133: #define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49))
134: #define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05))
135: #define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))
136: #define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))
137: #define JMPL (OPC1(0x2) | OPC3(0x38))
138: #define NOP (OPC1(0x0) | OPC2(0x04))
139: #define OR (OPC1(0x2) | OPC3(0x02))
140: #define ORN (OPC1(0x2) | OPC3(0x06))
141: #define RDY (OPC1(0x2) | OPC3(0x28) | S1A(0))
142: #define RESTORE (OPC1(0x2) | OPC3(0x3d))
143: #define SAVE (OPC1(0x2) | OPC3(0x3c))
144: #define SETHI (OPC1(0x0) | OPC2(0x04))
145: #define SLL (OPC1(0x2) | OPC3(0x25))
146: #define SLLX (OPC1(0x2) | OPC3(0x25) | (1 << 12))
147: #define SRA (OPC1(0x2) | OPC3(0x27))
148: #define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))
149: #define SRL (OPC1(0x2) | OPC3(0x26))
150: #define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))
151: #define SUB (OPC1(0x2) | OPC3(0x04))
152: #define SUBC (OPC1(0x2) | OPC3(0x0c))
153: #define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25))
154: #define WRY (OPC1(0x2) | OPC3(0x30) | DA(0))
155: #define XOR (OPC1(0x2) | OPC3(0x03))
156: #define XNOR (OPC1(0x2) | OPC3(0x07))
157:
158: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
159: #define MAX_DISP (0x1fffff)
160: #define MIN_DISP (-0x200000)
161: #define DISP_MASK (0x3fffff)
162:
163: #define BICC (OPC1(0x0) | OPC2(0x2))
164: #define FBFCC (OPC1(0x0) | OPC2(0x6))
165: #define SLL_W SLL
166: #define SDIV (OPC1(0x2) | OPC3(0x0f))
167: #define SMUL (OPC1(0x2) | OPC3(0x0b))
168: #define UDIV (OPC1(0x2) | OPC3(0x0e))
169: #define UMUL (OPC1(0x2) | OPC3(0x0a))
170: #else
171: #define SLL_W SLLX
172: #endif
173:
174: #define SIMM_MAX (0x0fff)
175: #define SIMM_MIN (-0x1000)
176:
177: /* dest_reg is the absolute name of the register
178: Useful for reordering instructions in the delay slot. */
179: static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_si delay_slot)
180: {
181: sljit_ins *ptr;
182: SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS
183: || (delay_slot & DST_INS_MASK) == MOVABLE_INS
184: || (delay_slot & DST_INS_MASK) == ((ins >> 25) & 0x1f));
185: ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
186: FAIL_IF(!ptr);
187: *ptr = ins;
188: compiler->size++;
189: compiler->delay_slot = delay_slot;
190: return SLJIT_SUCCESS;
191: }
192:
193: static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
194: {
195: sljit_sw diff;
196: sljit_uw target_addr;
197: sljit_ins *inst;
198: sljit_ins saved_inst;
199:
200: if (jump->flags & SLJIT_REWRITABLE_JUMP)
201: return code_ptr;
202:
203: if (jump->flags & JUMP_ADDR)
204: target_addr = jump->u.target;
205: else {
206: SLJIT_ASSERT(jump->flags & JUMP_LABEL);
207: target_addr = (sljit_uw)(code + jump->u.label->size);
208: }
209: inst = (sljit_ins*)jump->addr;
210:
211: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
212: if (jump->flags & IS_CALL) {
213: /* Call is always patchable on sparc 32. */
214: jump->flags |= PATCH_CALL;
215: if (jump->flags & IS_MOVABLE) {
216: inst[0] = inst[-1];
217: inst[-1] = CALL;
218: jump->addr -= sizeof(sljit_ins);
219: return inst;
220: }
221: inst[0] = CALL;
222: inst[1] = NOP;
223: return inst + 1;
224: }
225: #else
226: /* Both calls and BPr instructions shall not pass this point. */
227: #error "Implementation required"
228: #endif
229:
230: if (jump->flags & IS_COND)
231: inst--;
232:
233: if (jump->flags & IS_MOVABLE) {
234: diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1)) >> 2;
235: if (diff <= MAX_DISP && diff >= MIN_DISP) {
236: jump->flags |= PATCH_B;
237: inst--;
238: if (jump->flags & IS_COND) {
239: saved_inst = inst[0];
240: inst[0] = inst[1] ^ (1 << 28);
241: inst[1] = saved_inst;
242: } else {
243: inst[1] = inst[0];
244: inst[0] = BICC | DA(0x8);
245: }
246: jump->addr = (sljit_uw)inst;
247: return inst + 1;
248: }
249: }
250:
251: diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
252: if (diff <= MAX_DISP && diff >= MIN_DISP) {
253: jump->flags |= PATCH_B;
254: if (jump->flags & IS_COND)
255: inst[0] ^= (1 << 28);
256: else
257: inst[0] = BICC | DA(0x8);
258: inst[1] = NOP;
259: jump->addr = (sljit_uw)inst;
260: return inst + 1;
261: }
262:
263: return code_ptr;
264: }
265:
266: SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
267: {
268: struct sljit_memory_fragment *buf;
269: sljit_ins *code;
270: sljit_ins *code_ptr;
271: sljit_ins *buf_ptr;
272: sljit_ins *buf_end;
273: sljit_uw word_count;
274: sljit_uw addr;
275:
276: struct sljit_label *label;
277: struct sljit_jump *jump;
278: struct sljit_const *const_;
279:
280: CHECK_ERROR_PTR();
281: check_sljit_generate_code(compiler);
282: reverse_buf(compiler);
283:
284: code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
285: PTR_FAIL_WITH_EXEC_IF(code);
286: buf = compiler->buf;
287:
288: code_ptr = code;
289: word_count = 0;
290: label = compiler->labels;
291: jump = compiler->jumps;
292: const_ = compiler->consts;
293: do {
294: buf_ptr = (sljit_ins*)buf->memory;
295: buf_end = buf_ptr + (buf->used_size >> 2);
296: do {
297: *code_ptr = *buf_ptr++;
298: SLJIT_ASSERT(!label || label->size >= word_count);
299: SLJIT_ASSERT(!jump || jump->addr >= word_count);
300: SLJIT_ASSERT(!const_ || const_->addr >= word_count);
301: /* These structures are ordered by their address. */
302: if (label && label->size == word_count) {
303: /* Just recording the address. */
304: label->addr = (sljit_uw)code_ptr;
305: label->size = code_ptr - code;
306: label = label->next;
307: }
308: if (jump && jump->addr == word_count) {
309: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
310: jump->addr = (sljit_uw)(code_ptr - 3);
311: #else
312: jump->addr = (sljit_uw)(code_ptr - 6);
313: #endif
314: code_ptr = optimize_jump(jump, code_ptr, code);
315: jump = jump->next;
316: }
317: if (const_ && const_->addr == word_count) {
318: /* Just recording the address. */
319: const_->addr = (sljit_uw)code_ptr;
320: const_ = const_->next;
321: }
322: code_ptr ++;
323: word_count ++;
324: } while (buf_ptr < buf_end);
325:
326: buf = buf->next;
327: } while (buf);
328:
329: if (label && label->size == word_count) {
330: label->addr = (sljit_uw)code_ptr;
331: label->size = code_ptr - code;
332: label = label->next;
333: }
334:
335: SLJIT_ASSERT(!label);
336: SLJIT_ASSERT(!jump);
337: SLJIT_ASSERT(!const_);
338: SLJIT_ASSERT(code_ptr - code <= (sljit_si)compiler->size);
339:
340: jump = compiler->jumps;
341: while (jump) {
342: do {
343: addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
344: buf_ptr = (sljit_ins*)jump->addr;
345:
346: if (jump->flags & PATCH_CALL) {
347: addr = (sljit_sw)(addr - jump->addr) >> 2;
348: SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
349: buf_ptr[0] = CALL | (addr & 0x3fffffff);
350: break;
351: }
352: if (jump->flags & PATCH_B) {
353: addr = (sljit_sw)(addr - jump->addr) >> 2;
354: SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
355: buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
356: break;
357: }
358:
359: /* Set the fields of immediate loads. */
360: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
361: buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
362: buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
363: #else
364: #error "Implementation required"
365: #endif
366: } while (0);
367: jump = jump->next;
368: }
369:
370:
371: compiler->error = SLJIT_ERR_COMPILED;
372: compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
373: SLJIT_CACHE_FLUSH(code, code_ptr);
374: return code;
375: }
376:
377: /* --------------------------------------------------------------------- */
378: /* Entry, exit */
379: /* --------------------------------------------------------------------- */
380:
381: /* Creates an index in data_transfer_insts array. */
382: #define LOAD_DATA 0x01
383: #define WORD_DATA 0x00
384: #define BYTE_DATA 0x02
385: #define HALF_DATA 0x04
386: #define INT_DATA 0x06
387: #define SIGNED_DATA 0x08
388: /* Separates integer and floating point registers */
389: #define GPR_REG 0x0f
390: #define DOUBLE_DATA 0x10
391:
392: #define MEM_MASK 0x1f
393:
394: #define WRITE_BACK 0x00020
395: #define ARG_TEST 0x00040
396: #define ALT_KEEP_CACHE 0x00080
397: #define CUMULATIVE_OP 0x00100
398: #define IMM_OP 0x00200
399: #define SRC2_IMM 0x00400
400:
401: #define REG_DEST 0x00800
402: #define REG2_SOURCE 0x01000
403: #define SLOW_SRC1 0x02000
404: #define SLOW_SRC2 0x04000
405: #define SLOW_DEST 0x08000
406:
407: /* SET_FLAGS (0x10 << 19) also belong here! */
408:
409: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
410: #include "sljitNativeSPARC_32.c"
411: #else
412: #include "sljitNativeSPARC_64.c"
413: #endif
414:
415: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
416: {
417: CHECK_ERROR();
418: check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
419:
420: compiler->scratches = scratches;
421: compiler->saveds = saveds;
422: #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
423: compiler->logical_local_size = local_size;
424: #endif
425:
426: local_size += 23 * sizeof(sljit_sw);
427: local_size = (local_size + 7) & ~0x7;
428: compiler->local_size = local_size;
429:
430: if (local_size <= SIMM_MAX) {
431: FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | IMM(-local_size), UNMOVABLE_INS));
432: }
433: else {
434: FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size));
435: FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_LOCALS_REG) | S1(SLJIT_LOCALS_REG) | S2(TMP_REG1), UNMOVABLE_INS));
436: }
437:
438: if (args >= 1)
439: FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG1) | S1(0) | S2A(24), DR(SLJIT_SAVED_REG1)));
440: if (args >= 2)
441: FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG2) | S1(0) | S2A(25), DR(SLJIT_SAVED_REG2)));
442: if (args >= 3)
443: FAIL_IF(push_inst(compiler, OR | D(SLJIT_SAVED_REG3) | S1(0) | S2A(26), DR(SLJIT_SAVED_REG3)));
444:
445: return SLJIT_SUCCESS;
446: }
447:
448: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
449: {
450: CHECK_ERROR_VOID();
451: check_sljit_set_context(compiler, args, scratches, saveds, local_size);
452:
453: compiler->scratches = scratches;
454: compiler->saveds = saveds;
455: #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
456: compiler->logical_local_size = local_size;
457: #endif
458:
459: local_size += 23 * sizeof(sljit_sw);
460: compiler->local_size = (local_size + 7) & ~0x7;
461: }
462:
463: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
464: {
465: CHECK_ERROR();
466: check_sljit_emit_return(compiler, op, src, srcw);
467:
468: if (op != SLJIT_MOV || !(src <= TMP_REG3)) {
469: FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
470: src = SLJIT_SCRATCH_REG1;
471: }
472:
473: FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));
474: return push_inst(compiler, RESTORE | D(SLJIT_SCRATCH_REG1) | S1(src) | S2(0), UNMOVABLE_INS);
475: }
476:
477: /* --------------------------------------------------------------------- */
478: /* Operators */
479: /* --------------------------------------------------------------------- */
480:
481: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
482: #define ARCH_32_64(a, b) a
483: #else
484: #define ARCH_32_64(a, b) b
485: #endif
486:
487: static SLJIT_CONST sljit_ins data_transfer_insts[16 + 4] = {
488: /* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
489: /* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
490: /* u b s */ OPC1(3) | OPC3(0x05) /* stb */,
491: /* u b l */ OPC1(3) | OPC3(0x01) /* ldub */,
492: /* u h s */ OPC1(3) | OPC3(0x06) /* sth */,
493: /* u h l */ OPC1(3) | OPC3(0x02) /* lduh */,
494: /* u i s */ OPC1(3) | OPC3(0x04) /* stw */,
495: /* u i l */ OPC1(3) | OPC3(0x00) /* lduw */,
496:
497: /* s w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */),
498: /* s w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */),
499: /* s b s */ OPC1(3) | OPC3(0x05) /* stb */,
500: /* s b l */ OPC1(3) | OPC3(0x09) /* ldsb */,
501: /* s h s */ OPC1(3) | OPC3(0x06) /* sth */,
502: /* s h l */ OPC1(3) | OPC3(0x0a) /* ldsh */,
503: /* s i s */ OPC1(3) | OPC3(0x04) /* stw */,
504: /* s i l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x08) /* ldsw */),
505:
506: /* d s */ OPC1(3) | OPC3(0x27),
507: /* d l */ OPC1(3) | OPC3(0x23),
508: /* s s */ OPC1(3) | OPC3(0x24),
509: /* s l */ OPC1(3) | OPC3(0x20),
510: };
511:
512: #undef ARCH_32_64
513:
514: /* Can perform an operation using at most 1 instruction. */
515: static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
516: {
517: SLJIT_ASSERT(arg & SLJIT_MEM);
518:
519: if (!(flags & WRITE_BACK) || !(arg & 0xf)) {
520: if ((!(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN)
521: || ((arg & 0xf0) && (argw & 0x3) == 0)) {
522: /* Works for both absoulte and relative addresses (immediate case). */
523: if (SLJIT_UNLIKELY(flags & ARG_TEST))
524: return 1;
525: FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
526: | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg))
527: | S1(arg & 0xf) | ((arg & 0xf0) ? S2((arg >> 4) & 0xf) : IMM(argw)),
528: ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
529: return -1;
530: }
531: }
532: return 0;
533: }
534:
535: /* See getput_arg below.
536: Note: can_cache is called only for binary operators. Those
537: operators always uses word arguments without write back. */
538: static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
539: {
540: SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
541:
542: /* Simple operation except for updates. */
543: if (arg & 0xf0) {
544: argw &= 0x3;
545: SLJIT_ASSERT(argw);
546: next_argw &= 0x3;
547: if ((arg & 0xf0) == (next_arg & 0xf0) && argw == next_argw)
548: return 1;
549: return 0;
550: }
551:
552: if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
553: return 1;
554: return 0;
555: }
556:
557: /* Emit the necessary instructions. See can_cache above. */
558: static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
559: {
560: sljit_si base, arg2, delay_slot;
561: sljit_ins dest;
562:
563: SLJIT_ASSERT(arg & SLJIT_MEM);
564: if (!(next_arg & SLJIT_MEM)) {
565: next_arg = 0;
566: next_argw = 0;
567: }
568:
569: base = arg & 0xf;
570: if (SLJIT_UNLIKELY(arg & 0xf0)) {
571: argw &= 0x3;
572: SLJIT_ASSERT(argw != 0);
573:
574: /* Using the cache. */
575: if (((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) && (argw == compiler->cache_argw))
576: arg2 = TMP_REG3;
577: else {
578: if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
579: compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
580: compiler->cache_argw = argw;
581: arg2 = TMP_REG3;
582: }
583: else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && (reg << 4) != (arg & 0xf0))
584: arg2 = reg;
585: else /* It must be a mov operation, so tmp1 must be free to use. */
586: arg2 = TMP_REG1;
587: FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1((arg >> 4) & 0xf) | IMM_ARG | argw, DR(arg2)));
588: }
589: }
590: else {
591: /* Using the cache. */
592: if ((compiler->cache_arg == SLJIT_MEM) && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
593: if (argw != compiler->cache_argw) {
594: FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | S1(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
595: compiler->cache_argw = argw;
596: }
597: arg2 = TMP_REG3;
598: } else {
599: if ((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) {
600: compiler->cache_arg = SLJIT_MEM;
601: compiler->cache_argw = argw;
602: arg2 = TMP_REG3;
603: }
604: else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base)
605: arg2 = reg;
606: else /* It must be a mov operation, so tmp1 must be free to use. */
607: arg2 = TMP_REG1;
608: FAIL_IF(load_immediate(compiler, arg2, argw));
609: }
610: }
611:
612: dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg));
613: delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;
614: if (!base)
615: return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);
616: if (!(flags & WRITE_BACK))
617: return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
618: FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot));
619: return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
620: }
621:
622: static SLJIT_INLINE sljit_si emit_op_mem(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
623: {
624: if (getput_arg_fast(compiler, flags, reg, arg, argw))
625: return compiler->error;
626: compiler->cache_arg = 0;
627: compiler->cache_argw = 0;
628: return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
629: }
630:
631: static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg1, sljit_sw arg1w, sljit_si arg2, sljit_sw arg2w)
632: {
633: if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
634: return compiler->error;
635: return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
636: }
637:
638: static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
639: sljit_si dst, sljit_sw dstw,
640: sljit_si src1, sljit_sw src1w,
641: sljit_si src2, sljit_sw src2w)
642: {
643: /* arg1 goes to TMP_REG1 or src reg
644: arg2 goes to TMP_REG2, imm or src reg
645: TMP_REG3 can be used for caching
646: result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
647: sljit_si dst_r = TMP_REG2;
648: sljit_si src1_r;
649: sljit_sw src2_r = 0;
650: sljit_si sugg_src2_r = TMP_REG2;
651:
652: if (!(flags & ALT_KEEP_CACHE)) {
653: compiler->cache_arg = 0;
654: compiler->cache_argw = 0;
655: }
656:
657: if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
658: if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
659: return SLJIT_SUCCESS;
660: }
661: else if (dst <= TMP_REG3) {
662: dst_r = dst;
663: flags |= REG_DEST;
664: if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
665: sugg_src2_r = dst_r;
666: }
667: else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
668: flags |= SLOW_DEST;
669:
670: if (flags & IMM_OP) {
671: if ((src2 & SLJIT_IMM) && src2w) {
672: if (src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
673: flags |= SRC2_IMM;
674: src2_r = src2w;
675: }
676: }
677: if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
678: if (src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
679: flags |= SRC2_IMM;
680: src2_r = src1w;
681:
682: /* And swap arguments. */
683: src1 = src2;
684: src1w = src2w;
685: src2 = SLJIT_IMM;
686: /* src2w = src2_r unneeded. */
687: }
688: }
689: }
690:
691: /* Source 1. */
692: if (src1 <= TMP_REG3)
693: src1_r = src1;
694: else if (src1 & SLJIT_IMM) {
695: if (src1w) {
696: FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
697: src1_r = TMP_REG1;
698: }
699: else
700: src1_r = 0;
701: }
702: else {
703: if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
704: FAIL_IF(compiler->error);
705: else
706: flags |= SLOW_SRC1;
707: src1_r = TMP_REG1;
708: }
709:
710: /* Source 2. */
711: if (src2 <= TMP_REG3) {
712: src2_r = src2;
713: flags |= REG2_SOURCE;
714: if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
715: dst_r = src2_r;
716: }
717: else if (src2 & SLJIT_IMM) {
718: if (!(flags & SRC2_IMM)) {
719: if (src2w) {
720: FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
721: src2_r = sugg_src2_r;
722: }
723: else {
724: src2_r = 0;
725: if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) && (dst & SLJIT_MEM))
726: dst_r = 0;
727: }
728: }
729: }
730: else {
731: if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w))
732: FAIL_IF(compiler->error);
733: else
734: flags |= SLOW_SRC2;
735: src2_r = sugg_src2_r;
736: }
737:
738: if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
739: SLJIT_ASSERT(src2_r == TMP_REG2);
740: if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
741: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
742: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
743: }
744: else {
745: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
746: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
747: }
748: }
749: else if (flags & SLOW_SRC1)
750: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
751: else if (flags & SLOW_SRC2)
752: FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
753:
754: FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
755:
756: if (dst & SLJIT_MEM) {
757: if (!(flags & SLOW_DEST)) {
758: getput_arg_fast(compiler, flags, dst_r, dst, dstw);
759: return compiler->error;
760: }
761: return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
762: }
763:
764: return SLJIT_SUCCESS;
765: }
766:
767: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
768: {
769: CHECK_ERROR();
770: check_sljit_emit_op0(compiler, op);
771:
772: op = GET_OPCODE(op);
773: switch (op) {
774: case SLJIT_BREAKPOINT:
775: return push_inst(compiler, TA, UNMOVABLE_INS);
776: case SLJIT_NOP:
777: return push_inst(compiler, NOP, UNMOVABLE_INS);
778: case SLJIT_UMUL:
779: case SLJIT_SMUL:
780: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
781: FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? UMUL : SMUL) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
782: return push_inst(compiler, RDY | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
783: #else
784: #error "Implementation required"
785: #endif
786: case SLJIT_UDIV:
787: case SLJIT_SDIV:
788: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
789: if (op == SLJIT_UDIV)
790: FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
791: else {
792: FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_SCRATCH_REG1) | IMM(31), DR(TMP_REG1)));
793: FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
794: }
795: FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_SCRATCH_REG1), DR(TMP_REG2)));
796: FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? UDIV : SDIV) | D(SLJIT_SCRATCH_REG1) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG1)));
797: FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_SCRATCH_REG2) | S1(SLJIT_SCRATCH_REG1) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
798: FAIL_IF(push_inst(compiler, SUB | D(SLJIT_SCRATCH_REG2) | S1(TMP_REG2) | S2(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2)));
799: return SLJIT_SUCCESS;
800: #else
801: #error "Implementation required"
802: #endif
803: }
804:
805: return SLJIT_SUCCESS;
806: }
807:
808: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
809: sljit_si dst, sljit_sw dstw,
810: sljit_si src, sljit_sw srcw)
811: {
812: sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
813:
814: CHECK_ERROR();
815: check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
816: ADJUST_LOCAL_OFFSET(dst, dstw);
817: ADJUST_LOCAL_OFFSET(src, srcw);
818:
819: op = GET_OPCODE(op);
820: switch (op) {
821: case SLJIT_MOV:
822: case SLJIT_MOV_P:
823: return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
824:
825: case SLJIT_MOV_UI:
826: return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
827:
828: case SLJIT_MOV_SI:
829: return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
830:
831: case SLJIT_MOV_UB:
832: return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
833:
834: case SLJIT_MOV_SB:
835: return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
836:
837: case SLJIT_MOV_UH:
838: return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
839:
840: case SLJIT_MOV_SH:
841: return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
842:
843: case SLJIT_MOVU:
844: case SLJIT_MOVU_P:
845: return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
846:
847: case SLJIT_MOVU_UI:
848: return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
849:
850: case SLJIT_MOVU_SI:
851: return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
852:
853: case SLJIT_MOVU_UB:
854: return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
855:
856: case SLJIT_MOVU_SB:
857: return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
858:
859: case SLJIT_MOVU_UH:
860: return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
861:
862: case SLJIT_MOVU_SH:
863: return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
864:
865: case SLJIT_NOT:
866: case SLJIT_CLZ:
867: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
868:
869: case SLJIT_NEG:
870: return emit_op(compiler, SLJIT_SUB, flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
871: }
872:
873: return SLJIT_SUCCESS;
874: }
875:
876: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
877: sljit_si dst, sljit_sw dstw,
878: sljit_si src1, sljit_sw src1w,
879: sljit_si src2, sljit_sw src2w)
880: {
881: sljit_si flags = GET_FLAGS(op) ? SET_FLAGS : 0;
882:
883: CHECK_ERROR();
884: check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
885: ADJUST_LOCAL_OFFSET(dst, dstw);
886: ADJUST_LOCAL_OFFSET(src1, src1w);
887: ADJUST_LOCAL_OFFSET(src2, src2w);
888:
889: op = GET_OPCODE(op);
890: switch (op) {
891: case SLJIT_ADD:
892: case SLJIT_ADDC:
893: case SLJIT_MUL:
894: case SLJIT_AND:
895: case SLJIT_OR:
896: case SLJIT_XOR:
897: return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
898:
899: case SLJIT_SUB:
900: case SLJIT_SUBC:
901: return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
902:
903: case SLJIT_SHL:
904: case SLJIT_LSHR:
905: case SLJIT_ASHR:
906: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
907: if (src2 & SLJIT_IMM)
908: src2w &= 0x1f;
909: #else
910: SLJIT_ASSERT_STOP();
911: #endif
912: return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
913: }
914:
915: return SLJIT_SUCCESS;
916: }
917:
918: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
919: {
920: check_sljit_get_register_index(reg);
921: return reg_map[reg];
922: }
923:
924: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
925: {
926: check_sljit_get_float_register_index(reg);
927: return reg << 1;
928: }
929:
930: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
931: void *instruction, sljit_si size)
932: {
933: CHECK_ERROR();
934: check_sljit_emit_op_custom(compiler, instruction, size);
935: SLJIT_ASSERT(size == 4);
936:
937: return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
938: }
939:
940: /* --------------------------------------------------------------------- */
941: /* Floating point operators */
942: /* --------------------------------------------------------------------- */
943:
944: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
945: {
946: return 1;
947: }
948:
949: #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
950: #define SELECT_FOP(op, single, double) ((op & SLJIT_SINGLE_OP) ? single : double)
951:
952: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
953: sljit_si dst, sljit_sw dstw,
954: sljit_si src, sljit_sw srcw)
955: {
956: sljit_si dst_fr;
957:
958: CHECK_ERROR();
959: check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
960: SLJIT_COMPILE_ASSERT((SLJIT_SINGLE_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
961:
962: compiler->cache_arg = 0;
963: compiler->cache_argw = 0;
964:
965: if (GET_OPCODE(op) == SLJIT_CMPD) {
966: if (dst > SLJIT_FLOAT_REG6) {
967: FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
968: dst = TMP_FREG1;
969: }
970: else
971: dst <<= 1;
972:
973: if (src > SLJIT_FLOAT_REG6) {
974: FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
975: src = TMP_FREG2;
976: }
977: else
978: src <<= 1;
979:
980: return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(dst) | S2A(src), FCC_IS_SET | MOVABLE_INS);
981: }
982:
983: dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
984:
985: if (src > SLJIT_FLOAT_REG6) {
986: FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
987: src = dst_fr;
988: }
989: else
990: src <<= 1;
991:
992: switch (GET_OPCODE(op)) {
993: case SLJIT_MOVD:
994: if (src != dst_fr && dst_fr != TMP_FREG1) {
995: FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr) | S2A(src), MOVABLE_INS));
996: if (!(op & SLJIT_SINGLE_OP))
997: FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
998: }
999: break;
1000: case SLJIT_NEGD:
1001: FAIL_IF(push_inst(compiler, FNEGS | DA(dst_fr) | S2A(src), MOVABLE_INS));
1002: if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
1003: FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
1004: break;
1005: case SLJIT_ABSD:
1006: FAIL_IF(push_inst(compiler, FABSS | DA(dst_fr) | S2A(src), MOVABLE_INS));
1007: if (dst_fr != src && !(op & SLJIT_SINGLE_OP))
1008: FAIL_IF(push_inst(compiler, FMOVS | DA(dst_fr | 1) | S2A(src | 1), MOVABLE_INS));
1009: break;
1010: }
1011:
1012: if (dst_fr == TMP_FREG1) {
1013: if (GET_OPCODE(op) == SLJIT_MOVD)
1014: dst_fr = src;
1015: FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_fr, dst, dstw, 0, 0));
1016: }
1017:
1018: return SLJIT_SUCCESS;
1019: }
1020:
1021: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
1022: sljit_si dst, sljit_sw dstw,
1023: sljit_si src1, sljit_sw src1w,
1024: sljit_si src2, sljit_sw src2w)
1025: {
1026: sljit_si dst_fr, flags = 0;
1027:
1028: CHECK_ERROR();
1029: check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
1030:
1031: compiler->cache_arg = 0;
1032: compiler->cache_argw = 0;
1033:
1034: dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
1035:
1036: if (src1 > SLJIT_FLOAT_REG6) {
1037: if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
1038: FAIL_IF(compiler->error);
1039: src1 = TMP_FREG1;
1040: } else
1041: flags |= SLOW_SRC1;
1042: }
1043: else
1044: src1 <<= 1;
1045:
1046: if (src2 > SLJIT_FLOAT_REG6) {
1047: if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
1048: FAIL_IF(compiler->error);
1049: src2 = TMP_FREG2;
1050: } else
1051: flags |= SLOW_SRC2;
1052: }
1053: else
1054: src2 <<= 1;
1055:
1056: if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1057: if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1058: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
1059: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
1060: }
1061: else {
1062: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
1063: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
1064: }
1065: }
1066: else if (flags & SLOW_SRC1)
1067: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
1068: else if (flags & SLOW_SRC2)
1069: FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
1070:
1071: if (flags & SLOW_SRC1)
1072: src1 = TMP_FREG1;
1073: if (flags & SLOW_SRC2)
1074: src2 = TMP_FREG2;
1075:
1076: switch (GET_OPCODE(op)) {
1077: case SLJIT_ADDD:
1078: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
1079: break;
1080:
1081: case SLJIT_SUBD:
1082: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
1083: break;
1084:
1085: case SLJIT_MULD:
1086: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
1087: break;
1088:
1089: case SLJIT_DIVD:
1090: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_fr) | S1A(src1) | S2A(src2), MOVABLE_INS));
1091: break;
1092: }
1093:
1094: if (dst_fr == TMP_FREG2)
1095: FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
1096:
1097: return SLJIT_SUCCESS;
1098: }
1099:
1100: #undef FLOAT_DATA
1101: #undef SELECT_FOP
1102:
1103: /* --------------------------------------------------------------------- */
1104: /* Other instructions */
1105: /* --------------------------------------------------------------------- */
1106:
1107: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
1108: {
1109: CHECK_ERROR();
1110: check_sljit_emit_fast_enter(compiler, dst, dstw);
1111: ADJUST_LOCAL_OFFSET(dst, dstw);
1112:
1113: /* For UNUSED dst. Uncommon, but possible. */
1114: if (dst == SLJIT_UNUSED)
1115: return SLJIT_SUCCESS;
1116:
1117: if (dst <= TMP_REG3)
1118: return push_inst(compiler, OR | D(dst) | S1(0) | S2(LINK_REG), DR(dst));
1119:
1120: /* Memory. */
1121: return emit_op_mem(compiler, WORD_DATA, LINK_REG, dst, dstw);
1122: }
1123:
1124: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
1125: {
1126: CHECK_ERROR();
1127: check_sljit_emit_fast_return(compiler, src, srcw);
1128: ADJUST_LOCAL_OFFSET(src, srcw);
1129:
1130: if (src <= TMP_REG3)
1131: FAIL_IF(push_inst(compiler, OR | D(LINK_REG) | S1(0) | S2(src), DR(LINK_REG)));
1132: else if (src & SLJIT_MEM)
1133: FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, LINK_REG, src, srcw));
1134: else if (src & SLJIT_IMM)
1135: FAIL_IF(load_immediate(compiler, LINK_REG, srcw));
1136:
1137: FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(LINK_REG) | IMM(8), UNMOVABLE_INS));
1138: return push_inst(compiler, NOP, UNMOVABLE_INS);
1139: }
1140:
1141: /* --------------------------------------------------------------------- */
1142: /* Conditional instructions */
1143: /* --------------------------------------------------------------------- */
1144:
1145: SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1146: {
1147: struct sljit_label *label;
1148:
1149: CHECK_ERROR_PTR();
1150: check_sljit_emit_label(compiler);
1151:
1152: if (compiler->last_label && compiler->last_label->size == compiler->size)
1153: return compiler->last_label;
1154:
1155: label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1156: PTR_FAIL_IF(!label);
1157: set_label(label, compiler);
1158: compiler->delay_slot = UNMOVABLE_INS;
1159: return label;
1160: }
1161:
1162: static sljit_ins get_cc(sljit_si type)
1163: {
1164: switch (type) {
1165: case SLJIT_C_EQUAL:
1166: case SLJIT_C_MUL_NOT_OVERFLOW:
1167: return DA(0x1);
1168:
1169: case SLJIT_C_NOT_EQUAL:
1170: case SLJIT_C_MUL_OVERFLOW:
1171: return DA(0x9);
1172:
1173: case SLJIT_C_LESS:
1174: return DA(0x5);
1175:
1176: case SLJIT_C_GREATER_EQUAL:
1177: return DA(0xd);
1178:
1179: case SLJIT_C_GREATER:
1180: return DA(0xc);
1181:
1182: case SLJIT_C_LESS_EQUAL:
1183: return DA(0x4);
1184:
1185: case SLJIT_C_SIG_LESS:
1186: return DA(0x3);
1187:
1188: case SLJIT_C_SIG_GREATER_EQUAL:
1189: return DA(0xb);
1190:
1191: case SLJIT_C_SIG_GREATER:
1192: return DA(0xa);
1193:
1194: case SLJIT_C_SIG_LESS_EQUAL:
1195: return DA(0x2);
1196:
1197: case SLJIT_C_OVERFLOW:
1198: return DA(0x7);
1199:
1200: case SLJIT_C_NOT_OVERFLOW:
1201: return DA(0xf);
1202:
1203: case SLJIT_C_FLOAT_EQUAL:
1204: return DA(0x9);
1205:
1206: case SLJIT_C_FLOAT_NOT_EQUAL: /* Unordered. */
1207: return DA(0x1);
1208:
1209: case SLJIT_C_FLOAT_LESS:
1210: return DA(0x4);
1211:
1212: case SLJIT_C_FLOAT_GREATER_EQUAL: /* Unordered. */
1213: return DA(0xc);
1214:
1215: case SLJIT_C_FLOAT_LESS_EQUAL:
1216: return DA(0xd);
1217:
1218: case SLJIT_C_FLOAT_GREATER: /* Unordered. */
1219: return DA(0x5);
1220:
1221: case SLJIT_C_FLOAT_UNORDERED:
1222: return DA(0x7);
1223:
1224: case SLJIT_C_FLOAT_ORDERED:
1225: return DA(0xf);
1226:
1227: default:
1228: SLJIT_ASSERT_STOP();
1229: return DA(0x8);
1230: }
1231: }
1232:
1233: SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
1234: {
1235: struct sljit_jump *jump;
1236:
1237: CHECK_ERROR_PTR();
1238: check_sljit_emit_jump(compiler, type);
1239:
1240: jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1241: PTR_FAIL_IF(!jump);
1242: set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
1243: type &= 0xff;
1244:
1245: if (type < SLJIT_C_FLOAT_EQUAL) {
1246: jump->flags |= IS_COND;
1247: if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET))
1248: jump->flags |= IS_MOVABLE;
1249: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
1250: PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
1251: #else
1252: #error "Implementation required"
1253: #endif
1254: }
1255: else if (type < SLJIT_JUMP) {
1256: jump->flags |= IS_COND;
1257: if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET))
1258: jump->flags |= IS_MOVABLE;
1259: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
1260: PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(type ^ 1) | 5, UNMOVABLE_INS));
1261: #else
1262: #error "Implementation required"
1263: #endif
1264: } else {
1265: if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
1266: jump->flags |= IS_MOVABLE;
1267: if (type >= SLJIT_FAST_CALL)
1268: jump->flags |= IS_CALL;
1269: }
1270:
1271: PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
1272: PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
1273: jump->addr = compiler->size;
1274: PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1275:
1276: return jump;
1277: }
1278:
1279: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
1280: {
1281: struct sljit_jump *jump = NULL;
1282: sljit_si src_r;
1283:
1284: CHECK_ERROR();
1285: check_sljit_emit_ijump(compiler, type, src, srcw);
1286: ADJUST_LOCAL_OFFSET(src, srcw);
1287:
1288: if (src <= TMP_REG3)
1289: src_r = src;
1290: else if (src & SLJIT_IMM) {
1291: jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1292: FAIL_IF(!jump);
1293: set_jump(jump, compiler, JUMP_ADDR);
1294: jump->u.target = srcw;
1295: if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
1296: jump->flags |= IS_MOVABLE;
1297: if (type >= SLJIT_FAST_CALL)
1298: jump->flags |= IS_CALL;
1299:
1300: FAIL_IF(emit_const(compiler, TMP_REG2, 0));
1301: src_r = TMP_REG2;
1302: }
1303: else {
1304: FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
1305: src_r = TMP_REG2;
1306: }
1307:
1308: FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
1309: if (jump)
1310: jump->addr = compiler->size;
1311: return push_inst(compiler, NOP, UNMOVABLE_INS);
1312: }
1313:
1314: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
1315: sljit_si dst, sljit_sw dstw,
1316: sljit_si src, sljit_sw srcw,
1317: sljit_si type)
1318: {
1319: sljit_si reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0);
1320:
1321: CHECK_ERROR();
1322: check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
1323: ADJUST_LOCAL_OFFSET(dst, dstw);
1324:
1325: if (dst == SLJIT_UNUSED)
1326: return SLJIT_SUCCESS;
1327:
1328: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
1329: op = GET_OPCODE(op);
1330: reg = (op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2;
1331:
1332: compiler->cache_arg = 0;
1333: compiler->cache_argw = 0;
1334: if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
1335: ADJUST_LOCAL_OFFSET(src, srcw);
1336: FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
1337: src = TMP_REG1;
1338: srcw = 0;
1339: }
1340:
1341: if (type < SLJIT_C_FLOAT_EQUAL)
1342: FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS));
1343: else
1344: FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS));
1345:
1346: FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS));
1347: FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS));
1348:
1349: if (op >= SLJIT_ADD)
1350: return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
1351:
1352: return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
1353: #else
1354: #error "Implementation required"
1355: #endif
1356: }
1357:
1358: SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
1359: {
1360: sljit_si reg;
1361: struct sljit_const *const_;
1362:
1363: CHECK_ERROR_PTR();
1364: check_sljit_emit_const(compiler, dst, dstw, init_value);
1365: ADJUST_LOCAL_OFFSET(dst, dstw);
1366:
1367: const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
1368: PTR_FAIL_IF(!const_);
1369: set_const(const_, compiler);
1370:
1371: reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
1372:
1373: PTR_FAIL_IF(emit_const(compiler, reg, init_value));
1374:
1375: if (dst & SLJIT_MEM)
1376: PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
1377:
1378: return const_;
1379: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>