-/*
- * mini-arm64.c: ARM64 backend for the Mono code generator
+/**
+ * \file
+ * ARM64 backend for the Mono code generator
*
* Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
*
static gboolean ios_abi;
-static __attribute__((warn_unused_result)) guint8* emit_load_regset (guint8 *code, guint64 regs, int basereg, int offset);
+static __attribute__ ((__warn_unused_result__)) guint8* emit_load_regset (guint8 *code, guint64 regs, int basereg, int offset);
const char*
mono_arch_regname (int reg)
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_addw_imm (guint8 *code, int dreg, int sreg, int imm)
{
if (!arm_is_arith_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_addx_imm (guint8 *code, int dreg, int sreg, int imm)
{
if (!arm_is_arith_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_subw_imm (guint8 *code, int dreg, int sreg, int imm)
{
if (!arm_is_arith_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_subx_imm (guint8 *code, int dreg, int sreg, int imm)
{
if (!arm_is_arith_imm (imm)) {
}
/* Emit sp+=imm. Clobbers ip0/ip1 */
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_addx_sp_imm (guint8 *code, int imm)
{
code = emit_imm (code, ARMREG_IP0, imm);
}
/* Emit sp-=imm. Clobbers ip0/ip1 */
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_subx_sp_imm (guint8 *code, int imm)
{
code = emit_imm (code, ARMREG_IP0, imm);
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_andw_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_andx_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_orrw_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_orrx_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_eorw_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_eorx_imm (guint8 *code, int dreg, int sreg, int imm)
{
// FIXME:
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_cmpw_imm (guint8 *code, int sreg, int imm)
{
if (imm == 0) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_cmpx_imm (guint8 *code, int sreg, int imm)
{
if (imm == 0) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strb (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strb_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strh (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strh_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strw (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strw_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strfpw (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strw_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strfpx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strx_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_strx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_strx_imm (imm)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrb (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 1)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrsbx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 1)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrh (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 2)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrshx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 2)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrswx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 4)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrw (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 4)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 8)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrfpw (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 4)) {
return code;
}
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_ldrfpx (guint8 *code, int rt, int rn, int imm)
{
if (arm_is_pimm12_scaled (imm, 8)) {
* - ldrp [fp, lr], [sp], !stack_offfset
* Clobbers TEMP_REGS.
*/
-__attribute__((warn_unused_result)) guint8*
+__attribute__ ((__warn_unused_result__)) guint8*
mono_arm_emit_destroy_frame (guint8 *code, int stack_offset, guint64 temp_regs)
{
arm_movspx (code, ARMREG_SP, ARMREG_FP);
switch (ji->type) {
case MONO_PATCH_INFO_METHOD_JUMP:
/* ji->relocation is not set by the caller */
- arm_patch_rel (ip, (guint8*)target, MONO_R_ARM64_B);
+ arm_patch_full (cfg, domain, ip, (guint8*)target, MONO_R_ARM64_B);
break;
default:
arm_patch_full (cfg, domain, ip, (guint8*)target, ji->relocation);
case MONO_TYPE_I1:
add_general (cinfo, ainfo, 1, TRUE);
break;
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
add_general (cinfo, ainfo, 1, FALSE);
break;
add_general (cinfo, ainfo, 2, TRUE);
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
add_general (cinfo, ainfo, 2, FALSE);
break;
case MONO_TYPE_I4:
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_STRING:
case MONO_TYPE_U8:
case MONO_TYPE_I8:
add_general (cinfo, ainfo, 8, FALSE);
/* Pass the argument address in the next register */
if (cinfo->gr >= PARAM_REGS) {
ainfo->storage = ArgVtypeByRefOnStack;
+ cinfo->stack_usage = ALIGN_TO (cinfo->stack_usage, 8);
ainfo->offset = cinfo->stack_usage;
cinfo->stack_usage += 8;
} else {
/* Special case arguments smaller than 1 machine word */
switch (t->type) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
*(guint8*)stack_arg = *(guint8*)arg;
break;
*(gint8*)stack_arg = *(gint8*)arg;
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
*(guint16*)stack_arg = *(guint16*)arg;
break;
case MONO_TYPE_I2:
}
switch (t->type) {
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_U8:
p->regs [slot] = (mgreg_t)*arg;
break;
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
p->regs [slot] = *(guint8*)arg;
break;
p->regs [slot] = *(gint16*)arg;
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
p->regs [slot] = *(guint16*)arg;
break;
case MONO_TYPE_I4:
case MONO_TYPE_VOID:
*(gpointer*)ret = NULL;
break;
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_I:
case MONO_TYPE_U:
*(gint8*)ret = res;
break;
case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
*(guint8*)ret = res;
break;
case MONO_TYPE_I2:
*(gint16*)ret = res;
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
*(guint16*)ret = res;
break;
case MONO_TYPE_I4:
if (cfg->method->save_lmf) {
cfg->create_lmf_var = TRUE;
cfg->lmf_ir = TRUE;
-#ifndef TARGET_MACH
- cfg->lmf_ir_mono_lmf = TRUE;
-#endif
}
}
}
/* This clobbers LR */
-static inline __attribute__((warn_unused_result)) guint8*
+static inline __attribute__ ((__warn_unused_result__)) guint8*
emit_cond_exc (MonoCompile *cfg, guint8 *code, int opcode, const char *exc_name)
{
int cond;
} else {
mono_add_patch_info_rel (cfg, code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, call->method, MONO_R_ARM64_B);
arm_b (code, code);
+ cfg->thunk_area += THUNK_SIZE;
}
ins->flags |= MONO_INST_GC_CALLSITE;
ins->backend.pc_offset = code - cfg->native_code;
#endif
break;
}
-
+ case OP_FILL_PROF_CALL_CTX:
+ for (int i = 0; i < MONO_MAX_IREGS; i++)
+ if ((MONO_ARCH_CALLEE_SAVED_REGS & (1 << i)) || i == ARMREG_SP || i == ARMREG_FP)
+ arm_strx (code, i, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, regs) + i * sizeof (mgreg_t));
+ break;
default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
g_assert_not_reached ();
* Emit code to store the registers in REGS into the appropriate elements of
* the register array at BASEREG+OFFSET.
*/
-static __attribute__((warn_unused_result)) guint8*
+static __attribute__ ((__warn_unused_result__)) guint8*
emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset)
{
int i;
* Emit code to load the registers in REGS from the appropriate elements of
* the register array at BASEREG+OFFSET.
*/
-static __attribute__((warn_unused_result)) guint8*
+static __attribute__ ((__warn_unused_result__)) guint8*
emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset)
{
int i;
* Emit code to store the registers in REGS into consecutive memory locations starting
* at BASEREG+OFFSET.
*/
-static __attribute__((warn_unused_result)) guint8*
+static __attribute__ ((__warn_unused_result__)) guint8*
emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset)
{
int i, pos;
* Emit code to load the registers in REGS from consecutive memory locations starting
* at BASEREG+OFFSET.
*/
-static __attribute__((warn_unused_result)) guint8*
+static __attribute__ ((__warn_unused_result__)) guint8*
emit_load_regset (guint8 *code, guint64 regs, int basereg, int offset)
{
int i, pos;
return code;
}
-__attribute__((warn_unused_result)) guint8*
+__attribute__ ((__warn_unused_result__)) guint8*
mono_arm_emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset)
{
return emit_load_regarray (code, regs, basereg, offset);
}
-__attribute__((warn_unused_result)) guint8*
+__attribute__ ((__warn_unused_result__)) guint8*
mono_arm_emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset)
{
return emit_store_regarray (code, regs, basereg, offset);
}
-__attribute__((warn_unused_result)) guint8*
+__attribute__ ((__warn_unused_result__)) guint8*
mono_arm_emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset)
{
return emit_store_regset (code, regs, basereg, offset);
/* Same as emit_store_regset, but emit unwind info too */
/* CFA_OFFSET is the offset between the CFA and basereg */
-static __attribute__((warn_unused_result)) guint8*
+static __attribute__ ((__warn_unused_result__)) guint8*
emit_store_regset_cfa (MonoCompile *cfg, guint8 *code, guint64 regs, int basereg, int offset, int cfa_offset, guint64 no_cfa_regset)
{
int i, j, pos, nregs;
return NULL;
}
-gboolean
-mono_arch_print_tree (MonoInst *tree, int arity)
-{
- return FALSE;
-}
-
guint32
mono_arch_get_patch_offset (guint8 *code)
{
return get_call_info (mp, sig);
}
-gpointer
-mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value)
-{
- gpointer *lr_loc;
- char *old_value;
- char *bp;
-
- /*Load the spvar*/
- bp = MONO_CONTEXT_GET_BP (ctx);
- lr_loc = (gpointer*)(bp + clause->exvar_offset);
-
- old_value = *lr_loc;
- if ((char*)old_value < (char*)ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
- return old_value;
-
- *lr_loc = new_value;
-
- return old_value;
-}