88 int32_t savedregs_num = 0;
89 uint32_t savedregs_bitmask = 0;
93 savedregs_bitmask = (1<<
REG_LR);
101 #if !defined(NDEBUG) && !defined(__ARMHF__)
103 vm_abort(
"codegen_emit_prolog: Floating-point callee saved registers are not saved to stack");
109 if (savedregs_bitmask != 0)
114 int32_t additional_bytes = (cd->
stackframesize * 8 - savedregs_num * 4);
116 if (additional_bytes > 0)
119 #if defined(__ARMHF__)
129 for (i = 0, len = 0; i < md->
paramcount; i++) {
143 #if !defined(ENABLE_SOFTFLOAT)
172 #if !defined(ENABLE_SOFTFLOAT)
176 #if defined(__ARMHF__)
234 int32_t savedregs_num = 0;
235 uint32_t savedregs_bitmask = 0;
239 savedregs_bitmask = (1<<
REG_LR);
247 #if defined(__ARMHF__)
256 int32_t additional_bytes = (cd->
stackframesize * 8 - savedregs_num * 4);
258 if (additional_bytes > 0)
263 if (savedregs_bitmask) {
265 savedregs_bitmask &= ~(1<<
REG_LR);
266 savedregs_bitmask |= (1<<
REG_PC);
320 #if defined(ENABLE_SOFTFLOAT)
333 #if defined(ENABLE_SOFTFLOAT)
385 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
419 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP3);
420 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP1);
423 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP3);
424 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
450 s3 = iptr->
sx.
val.
l & 0xffffffff;
451 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
459 s3 = iptr->
sx.
val.
l >> 32;
460 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP2);
481 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP3);
482 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP1);
485 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP3);
486 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
508 s3 = iptr->
sx.
val.
l & 0xffffffff;
509 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
517 s3 = iptr->
sx.
val.
l >> 32;
518 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP2);
549 bte = iptr->
sx.
s23.s3.bte;
577 bte = iptr->
sx.
s23.s3.bte;
676 if ((iptr->
sx.
val.
i & 0x1f) == 0) {
690 if ((iptr->
sx.
val.
i & 0x1f) == 0)
708 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP3);
709 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP1);
712 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP3);
713 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
729 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP3);
730 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP1);
733 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP3);
734 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
750 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP3);
751 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP1);
754 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP3);
755 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
763 #if !defined(ENABLE_SOFTFLOAT)
884 #if defined(__VFP_FP__)
897 #if defined(__VFP_FP__)
910 #if defined(__VFP_FP__)
927 #if defined(__VFP_FP__)
963 #if defined(__VFP_FP__)
978 #if defined(__VFP_FP__)
993 #if defined(__VFP_FP__)
1008 #if defined(__VFP_FP__)
1088 #if !defined(ENABLE_SOFTFLOAT)
1105 #if !defined(ENABLE_SOFTFLOAT)
1189 #if !defined(ENABLE_SOFTFLOAT)
1205 #if !defined(ENABLE_SOFTFLOAT)
1252 uf = iptr->
sx.
s23.s3.uf;
1257 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1258 fieldtype = fi->
type;
1262 #if !defined(ENABLE_SOFTFLOAT)
1270 uf = iptr->
sx.
s23.s3.uf;
1275 switch (fieldtype) {
1277 #if defined(ENABLE_SOFTFLOAT)
1285 #if defined(ENABLE_SOFTFLOAT)
1291 #if !defined(ENABLE_SOFTFLOAT)
1314 uf = iptr->
sx.
s23.s3.uf;
1319 fi = iptr->
sx.
s23.s3.fmiref->p.field;
1320 fieldtype = fi->
type;
1324 #if !defined(ENABLE_SOFTFLOAT)
1330 switch (fieldtype) {
1332 #if defined(ENABLE_SOFTFLOAT)
1338 #if defined(ENABLE_SOFTFLOAT)
1344 #if !defined(ENABLE_SOFTFLOAT)
1357 uf = iptr->
sx.
s23.s3.uf;
1362 switch (fieldtype) {
1364 #if defined(ENABLE_SOFTFLOAT)
1368 M_IST(s2, s1, disp);
1371 #if defined(ENABLE_SOFTFLOAT)
1374 M_LST(s2, s1, disp);
1376 #if !defined(ENABLE_SOFTFLOAT)
1378 M_FST(s2, s1, disp);
1381 M_DST(s2, s1, disp);
1400 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1401 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1402 if (iptr->
sx.
val.
l == 0) {
1417 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1418 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1419 if (iptr->
sx.
val.
l == 0) {
1447 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1448 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1449 if (iptr->
sx.
val.
l == 0) {
1481 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1482 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1483 if (iptr->
sx.
val.
l == 0) {
1511 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1512 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1514 if (iptr->
sx.
val.
l == 0) {
1553 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1554 s2 = emit_load_s1_low(jd, iptr,
REG_ITMP2);
1555 if (iptr->
sx.
val.
l == 0) {
1571 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1572 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1575 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1576 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1585 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1586 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1589 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1590 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1600 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1601 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1608 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1609 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1622 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1623 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1630 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1631 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1644 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1645 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1652 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1653 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1666 s1 = emit_load_s1_high(jd, iptr,
REG_ITMP1);
1667 s2 = emit_load_s2_high(jd, iptr,
REG_ITMP2);
1674 s1 = emit_load_s1_low(jd, iptr,
REG_ITMP1);
1675 s2 = emit_load_s2_low(jd, iptr,
REG_ITMP2);
1691 l = iptr->
sx.
s23.s2.tablelow;
1692 i = iptr->
sx.
s23.s3.tablehigh;
1708 emit_bugt(cd, table[0].
block);
1727 bte = iptr->
sx.
s23.s3.bte;
1728 if (bte->
stub == NULL) {
1738 #if defined(ARM_NO_THUMB_IW)
1753 um = iptr->
sx.
s23.s3.um;
1760 lm = iptr->
sx.
s23.s3.fmiref->p.method;
1774 um = iptr->
sx.
s23.s3.um;
1794 lm = iptr->
sx.
s23.s3.fmiref->p.method;
1809 um = iptr->
sx.
s23.s3.um;
1814 assert(disp2 == disp - 4);
1837 lm = iptr->
sx.
s23.s3.fmiref->p.method;
1865 super = iptr->
sx.
s23.s3.c.cls;
1866 superindex = super->
index;
1873 if (super == NULL) {
1879 iptr->
sx.
s23.s3.c.ref, disp);
1891 if ((super == NULL) || !
IS_IMM(superindex)) {
1894 if (super == NULL) {
1896 iptr->
sx.
s23.s3.c.ref, disp);
1907 if ((super == NULL) || !
IS_IMM(superindex)) {
1912 assert(
IS_IMM(superindex));
1920 if ((super == NULL) || !
IS_IMM(superindex)) {
1953 if (super == NULL) {
1959 iptr->
sx.
s23.s3.c.ref,
1976 if (super == NULL || super->
vftbl->subtype_depth >= DISPLAY_SIZE) {
1991 if (super == NULL) {
2035 if (super == NULL) {
2052 iptr->
sx.
s23.s3.c.ref,
2086 super = iptr->
sx.
s23.s3.c.cls;
2087 superindex = super->
index;
2100 if (super == NULL) {
2108 iptr->
sx.
s23.s3.c.ref, disp);
2120 if ((super == NULL) || !
IS_IMM(superindex)) {
2123 if (super == NULL) {
2130 iptr->
sx.
s23.s3.c.ref, disp);
2144 if ((super == NULL) || !
IS_IMM(superindex)) {
2170 assert(
IS_IMM(superindex));
2193 if (super == NULL) {
2199 iptr->
sx.
s23.s3.c.ref, disp);
2216 if (super == NULL || super->
vftbl->subtype_depth >= DISPLAY_SIZE) {
2230 if (super == NULL) {
2282 if (super == NULL) {
2300 var =
VAR(iptr->
sx.
s23.s2.args[s1]);
2321 iptr->
sx.
s23.s3.c.ref, disp);
2355 vm_abort(
"Unknown ICMD %d during code generation", iptr->
opc);
2374 int s1,
s2, tmpfreg;
2397 #if defined(__ARMHF__)
2420 #if defined(ENABLE_GC_CACAO)
2436 #if defined(__ARMHF__)
2456 for (i = md->
paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2499 #if defined(__ARMHF__)
2500 for (i = md->
paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2577 for (i = md->
paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2585 #if !defined(__ARM_EABI__)
2594 #if !defined(__ARM_EABI__)
2645 #if defined(__ARMHF__)
2665 #if defined(ENABLE_GC_CACAO)
2700 printf(
"===> i am going to exit after this debugging message!\n");
2701 printf(
"got asm_debug(%p, %p, %p, %p)\n",(
void*)a1,(
void*)a2,(
void*)a3,(
void*)a4);
void codegen_emit_instruction(jitdata *jd, instruction *iptr)
Generates machine code for one ICMD.
#define BUILTIN_FAST_canstore
#define PATCHER_resolve_classref_to_flags
s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
#define REG_LSR_REG(reg, s)
#define M_SUBLO_IMM(d, a, i)
s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
#define M_ALD(a, b, disp)
#define M_SUBGT_IMM(d, a, i)
#define PATCHER_invokeinterface
#define M_LST_INTERN(a, b, disp)
#define M_LST(a, b, disp)
#define M_ILD(a, b, disp)
s4 dseg_add_unique_address(codegendata *cd, void *value)
#define PATCHER_resolve_classref_to_index
#define PATCHER_resolve_classref_to_vftbl
#define BUILTIN_multianewarray
#define IS_INT_LNG_TYPE(a)
#define M_RSBMI_IMM(d, a, i)
#define M_SBC_IMM(d, a, i)
#define M_IST(a, b, disp)
#define M_MOVGT_IMM(i, d)
#define PATCHER_get_putfield
#define M_FLD_INTERN(a, b, disp)
#define M_ADD_IMM(d, a, i)
#define M_CAST_L2D(a, Fb)
s4 dseg_add_address(codegendata *cd, void *value)
#define M_DSEG_BRANCH(offset)
#define REG_ITMP12_PACKED
#define M_ADDLT_IMM(d, a, i)
#define dseg_add_functionptr(cd, value)
#define M_IST_INTERN(a, b, disp)
#define M_SUBLT_IMM(d, a, i)
#define M_STMFD(regs, base)
void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
#define M_MOVNE_IMM(i, d)
#define M_DSEG_LOAD(reg, offset)
void emit_arraystore_check(codegendata *cd, instruction *iptr)
#define M_FST(a, b, disp)
patchref_t * patcher_add_patch_ref(jitdata *jd, functionptr patcher, void *ref, s4 disp)
#define M_FLD(a, b, disp)
void dseg_add_target(codegendata *cd, basicblock *target)
#define SPLIT_STORE_AND_CLOSE(type, reg, offset)
java_object_t * codegen_finish_native_call(u1 *sp, u1 *pv)
#define M_RSB_IMMS(d, a, i)
#define M_STRH(d, base, off)
const s4 abi_registers_integer_saved[]
void emit_recompute_pv(codegendata *cd)
Emit code to recompute the procedure vector.
void asm_debug(int a1, int a2, int a3, int a4)
static int code_is_leafmethod(codeinfo *code)
#define M_LDRSB(d, base, off)
#define BUILTIN_arraycheckcast
s4 dseg_add_s4(codegendata *cd, s4 value)
void vm_abort(const char *text,...)
void(* functionptr)(void)
#define M_STRB(d, base, off)
java_handle_t * codegen_start_native_call(u1 *sp, u1 *pv)
#define IS_2_WORD_TYPE(a)
void emit_exception_check(codegendata *cd, instruction *iptr)
#define M_LDR_INTERN(d, base, off)
s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
#define M_SUB_IMMS(d, a, i)
#define M_LDRH(d, base, off)
#define M_LDR(d, base, offset)
const s4 abi_registers_float_saved[]
constant_FMIref * fieldref
void emit_label_br(codegendata *cd, s4 label)
s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
#define REG_ITMP23_PACKED
#define REG_LSL(reg, shift)
#define IS_FLT_DBL_TYPE(a)
#define M_LDRSH(d, base, off)
#define M_MOVVS_IMM(i, d)
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
s4 dseg_add_unique_s4(codegendata *cd, s4 value)
#define REG_ASR_REG(reg, s)
union instruction::@12 sx
void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
#define M_LDR_REG(d, base, offreg)
#define M_SUB_IMM(d, a, i)
#define M_CAST_I2F(a, Fb)
#define M_ADC_IMM(d, a, i)
#define REG_ASR(reg, shift)
#define SPLIT_OPEN(type, reg, tmpreg)
void emit_icmp_imm(codegendata *cd, int reg, int32_t value)
Emits code comparing a single register.
#define M_STR_INTERN(d, base, off)
void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
#define PATCHER_invokestatic_special
#define M_ADDGT_IMM(d, a, i)
#define REG_LSR(reg, shift)
#define M_FST_INTERN(a, b, disp)
#define M_RSB_IMM(d, a, i)
#define M_ADD_IMM_EXT_MUL4(d, n, imm)
#define M_AND_IMM(a, b, c)
#define PATCHER_invokevirtual
void codegen_emit_epilog(jitdata *jd)
Generates machine code for the method epilog.
#define M_LLD_INTERN(a, b, disp)
void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
#define M_MOVLT_IMM(i, d)
void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
#define M_CMPEQ_IMM(a, b, c)
#define M_DLD_INTERN(a, b, disp)
#define M_DST(a, b, disp)
#define INSTRUCTION_IS_UNRESOLVED(iptr)
struct instruction::@12::@13 s23
void codegen_emit_prolog(jitdata *jd)
Generates machine code for the method prolog.
#define M_LDMFD(regs, base)
#define M_LLD(a, b, disp)
#define M_STR(d, base, offset)
const parseddesc_t parseddesc
static void emit_fmove(codegendata *cd, int s, int d)
Generates a float-move from register s to d.
#define PATCHER_resolve_classref_to_classinfo
void emit_label(codegendata *cd, s4 label)
#define M_MOVEQ_IMM(i, d)
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
static void emit_dmove(codegendata *cd, int s, int d)
Generates an double-move from register s to d.
#define M_DLD(a, b, disp)
#define INSTRUCTION_MUST_CHECK(iptr)
#define M_ADD_IMMS(d, a, i)
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
#define M_SUB_IMM_EXT_MUL4(d, n, imm)
static VM * get_current()
#define REG_RESULT_PACKED
#define M_DST_INTERN(a, b, disp)
#define M_ILD_INTERN(a, b, disp)
#define REG_LSL_REG(reg, s)
#define M_RSC_IMM(d, a, i)
#define M_ADDHI_IMM(d, a, i)