/[pcre]/code/trunk/sljit/sljitNativeSPARC_common.c
ViewVC logotype

Contents of /code/trunk/sljit/sljitNativeSPARC_common.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5