2 * Stack-less Just-In-Time compiler
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
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.
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.
27 /* mips 64-bit arch dependent functions. */
29 static sljit_s32
load_immediate(struct sljit_compiler
*compiler
, sljit_s32 dst_ar
, sljit_sw imm
)
38 return push_inst(compiler
, ORI
| SA(0) | TA(dst_ar
) | IMM(imm
), dst_ar
);
40 if (imm
< 0 && imm
>= SIMM_MIN
)
41 return push_inst(compiler
, ADDIU
| SA(0) | TA(dst_ar
) | IMM(imm
), dst_ar
);
43 if (imm
<= 0x7fffffffl
&& imm
>= -0x80000000l
) {
44 FAIL_IF(push_inst(compiler
, LUI
| TA(dst_ar
) | IMM(imm
>> 16), dst_ar
));
45 return (imm
& 0xffff) ? push_inst(compiler
, ORI
| SA(dst_ar
) | TA(dst_ar
) | IMM(imm
), dst_ar
) : SLJIT_SUCCESS
;
48 /* Zero extended number. */
51 uimm
= ~(sljit_uw
)imm
;
55 while (!(uimm
& 0xff00000000000000l
)) {
60 if (!(uimm
& 0xf000000000000000l
)) {
65 if (!(uimm
& 0xc000000000000000l
)) {
70 if ((sljit_sw
)uimm
< 0) {
74 SLJIT_ASSERT(((uimm
& 0xc000000000000000l
) == 0x4000000000000000l
) && (shift
> 0) && (shift
<= 32));
79 FAIL_IF(push_inst(compiler
, LUI
| TA(dst_ar
) | IMM(uimm
>> 48), dst_ar
));
80 if (uimm
& 0x0000ffff00000000l
)
81 FAIL_IF(push_inst(compiler
, ORI
| SA(dst_ar
) | TA(dst_ar
) | IMM(uimm
>> 32), dst_ar
));
83 imm
&= (1l << shift
) - 1;
84 if (!(imm
& ~0xffff)) {
85 ins
= (shift
== 32) ? DSLL32
: DSLL
;
88 FAIL_IF(push_inst(compiler
, ins
| TA(dst_ar
) | DA(dst_ar
), dst_ar
));
89 return !(imm
& 0xffff) ? SLJIT_SUCCESS
: push_inst(compiler
, ORI
| SA(dst_ar
) | TA(dst_ar
) | IMM(imm
), dst_ar
);
92 /* Double shifts needs to be performed. */
96 while (!(uimm
& 0xf000000000000000l
)) {
101 if (!(uimm
& 0xc000000000000000l
)) {
106 if (!(uimm
& 0x8000000000000000l
)) {
111 SLJIT_ASSERT((uimm
& 0x8000000000000000l
) && (shift2
> 0) && (shift2
<= 16));
113 FAIL_IF(push_inst(compiler
, DSLL
| TA(dst_ar
) | DA(dst_ar
) | SH_IMM(shift
- shift2
), dst_ar
));
114 FAIL_IF(push_inst(compiler
, ORI
| SA(dst_ar
) | TA(dst_ar
) | IMM(uimm
>> 48), dst_ar
));
115 FAIL_IF(push_inst(compiler
, DSLL
| TA(dst_ar
) | DA(dst_ar
) | SH_IMM(shift2
), dst_ar
));
117 imm
&= (1l << shift2
) - 1;
118 return !(imm
& 0xffff) ? SLJIT_SUCCESS
: push_inst(compiler
, ORI
| SA(dst_ar
) | TA(dst_ar
) | IMM(imm
), dst_ar
);
121 static SLJIT_INLINE sljit_s32
emit_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw init_value
)
123 FAIL_IF(push_inst(compiler
, LUI
| T(dst
) | IMM(init_value
>> 48), DR(dst
)));
124 FAIL_IF(push_inst(compiler
, ORI
| S(dst
) | T(dst
) | IMM(init_value
>> 32), DR(dst
)));
125 FAIL_IF(push_inst(compiler
, DSLL
| T(dst
) | D(dst
) | SH_IMM(16), DR(dst
)));
126 FAIL_IF(push_inst(compiler
, ORI
| S(dst
) | T(dst
) | IMM(init_value
>> 16), DR(dst
)));
127 FAIL_IF(push_inst(compiler
, DSLL
| T(dst
) | D(dst
) | SH_IMM(16), DR(dst
)));
128 return push_inst(compiler
, ORI
| S(dst
) | T(dst
) | IMM(init_value
), DR(dst
));
131 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_target
, sljit_sw executable_offset
)
133 sljit_ins
*inst
= (sljit_ins
*)addr
;
134 SLJIT_UNUSED_ARG(executable_offset
);
136 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 6, 0);
137 inst
[0] = (inst
[0] & 0xffff0000) | ((sljit_ins
)(new_target
>> 48) & 0xffff);
138 inst
[1] = (inst
[1] & 0xffff0000) | ((sljit_ins
)(new_target
>> 32) & 0xffff);
139 inst
[3] = (inst
[3] & 0xffff0000) | ((sljit_ins
)(new_target
>> 16) & 0xffff);
140 inst
[5] = (inst
[5] & 0xffff0000) | ((sljit_ins
)new_target
& 0xffff);
141 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 6, 1);
142 inst
= (sljit_ins
*)SLJIT_ADD_EXEC_OFFSET(inst
, executable_offset
);
143 SLJIT_CACHE_FLUSH(inst
, inst
+ 6);
146 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
, sljit_sw executable_offset
)
148 sljit_set_jump_addr(addr
, (sljit_uw
)new_constant
, executable_offset
);
151 static sljit_s32
call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
, sljit_ins
*ins_ptr
)
153 sljit_s32 arg_count
= 0;
154 sljit_s32 word_arg_count
= 0;
155 sljit_s32 float_arg_count
= 0;
157 sljit_ins prev_ins
= *ins_ptr
;
160 SLJIT_ASSERT(reg_map
[TMP_REG1
] == 4 && freg_map
[TMP_FREG1
] == 12);
162 arg_types
>>= SLJIT_ARG_SHIFT
;
165 types
= (types
<< SLJIT_ARG_SHIFT
) | (arg_types
& SLJIT_ARG_MASK
);
167 switch (arg_types
& SLJIT_ARG_MASK
) {
168 case SLJIT_ARG_TYPE_F64
:
169 case SLJIT_ARG_TYPE_F32
:
179 arg_types
>>= SLJIT_ARG_SHIFT
;
183 switch (types
& SLJIT_ARG_MASK
) {
184 case SLJIT_ARG_TYPE_F64
:
185 if (arg_count
!= float_arg_count
)
186 ins
= MOV_S
| FMT_D
| FS(float_arg_count
) | FD(arg_count
);
187 else if (arg_count
== 1)
188 ins
= MOV_S
| FMT_D
| FS(SLJIT_FR0
) | FD(TMP_FREG1
);
192 case SLJIT_ARG_TYPE_F32
:
193 if (arg_count
!= float_arg_count
)
194 ins
= MOV_S
| FMT_S
| FS(float_arg_count
) | FD(arg_count
);
195 else if (arg_count
== 1)
196 ins
= MOV_S
| FMT_S
| FS(SLJIT_FR0
) | FD(TMP_FREG1
);
201 if (arg_count
!= word_arg_count
)
202 ins
= DADDU
| S(word_arg_count
) | TA(0) | D(arg_count
);
203 else if (arg_count
== 1)
204 ins
= DADDU
| S(SLJIT_R0
) | TA(0) | DA(4);
212 FAIL_IF(push_inst(compiler
, prev_ins
, MOVABLE_INS
));
217 types
>>= SLJIT_ARG_SHIFT
;
222 return SLJIT_SUCCESS
;
225 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_call(struct sljit_compiler
*compiler
, sljit_s32 type
,
228 struct sljit_jump
*jump
;
232 CHECK_PTR(check_sljit_emit_call(compiler
, type
, arg_types
));
234 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
236 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
238 if (type
& SLJIT_CALL_RETURN
)
239 PTR_FAIL_IF(emit_stack_frame_release(compiler
, 0, &ins
));
241 if ((type
& 0xff) != SLJIT_CALL_REG_ARG
)
242 PTR_FAIL_IF(call_with_args(compiler
, arg_types
, &ins
));
244 SLJIT_ASSERT(DR(PIC_ADDR_REG
) == 25 && PIC_ADDR_REG
== TMP_REG2
);
246 if (ins
== NOP
&& compiler
->delay_slot
!= UNMOVABLE_INS
)
247 jump
->flags
|= IS_MOVABLE
;
249 if (!(type
& SLJIT_CALL_RETURN
)) {
250 jump
->flags
|= IS_JAL
;
252 if ((type
& 0xff) != SLJIT_CALL_REG_ARG
)
253 jump
->flags
|= IS_CALL
;
255 PTR_FAIL_IF(push_inst(compiler
, JALR
| S(PIC_ADDR_REG
) | DA(RETURN_ADDR_REG
), UNMOVABLE_INS
));
257 PTR_FAIL_IF(push_inst(compiler
, JR
| S(PIC_ADDR_REG
), UNMOVABLE_INS
));
259 jump
->addr
= compiler
->size
;
260 PTR_FAIL_IF(push_inst(compiler
, ins
, UNMOVABLE_INS
));
262 /* Maximum number of instructions required for generating a constant. */
267 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_icall(struct sljit_compiler
*compiler
, sljit_s32 type
,
269 sljit_s32 src
, sljit_sw srcw
)
274 CHECK(check_sljit_emit_icall(compiler
, type
, arg_types
, src
, srcw
));
276 if (src
& SLJIT_MEM
) {
277 ADJUST_LOCAL_OFFSET(src
, srcw
);
278 FAIL_IF(emit_op_mem(compiler
, WORD_DATA
| LOAD_DATA
, DR(PIC_ADDR_REG
), src
, srcw
));
283 if ((type
& 0xff) == SLJIT_CALL_REG_ARG
) {
284 if (type
& SLJIT_CALL_RETURN
) {
285 if (src
>= SLJIT_FIRST_SAVED_REG
&& src
<= SLJIT_S0
) {
286 FAIL_IF(push_inst(compiler
, DADDU
| S(src
) | TA(0) | D(PIC_ADDR_REG
), DR(PIC_ADDR_REG
)));
291 FAIL_IF(emit_stack_frame_release(compiler
, 0, &ins
));
294 FAIL_IF(push_inst(compiler
, ins
, MOVABLE_INS
));
297 SLJIT_SKIP_CHECKS(compiler
);
298 return sljit_emit_ijump(compiler
, type
, src
, srcw
);
301 SLJIT_ASSERT(DR(PIC_ADDR_REG
) == 25 && PIC_ADDR_REG
== TMP_REG2
);
304 FAIL_IF(load_immediate(compiler
, DR(PIC_ADDR_REG
), srcw
));
305 else if (src
!= PIC_ADDR_REG
)
306 FAIL_IF(push_inst(compiler
, DADDU
| S(src
) | TA(0) | D(PIC_ADDR_REG
), DR(PIC_ADDR_REG
)));
308 if (type
& SLJIT_CALL_RETURN
)
309 FAIL_IF(emit_stack_frame_release(compiler
, 0, &ins
));
311 FAIL_IF(call_with_args(compiler
, arg_types
, &ins
));
313 /* Register input. */
314 if (!(type
& SLJIT_CALL_RETURN
))
315 FAIL_IF(push_inst(compiler
, JALR
| S(PIC_ADDR_REG
) | DA(RETURN_ADDR_REG
), UNMOVABLE_INS
));
317 FAIL_IF(push_inst(compiler
, JR
| S(PIC_ADDR_REG
), UNMOVABLE_INS
));
318 return push_inst(compiler
, ins
, UNMOVABLE_INS
);