Alien-TinyCCx
view release on metacpan or search on metacpan
src/arm-gen.c view on Meta::CPAN
TREG_F4,
TREG_F5,
TREG_F6,
TREG_F7,
#endif
TREG_SP = 13,
TREG_LR,
};
#ifdef TCC_ARM_VFP
#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
#endif
/* return registers for function */
#define REG_IRET TREG_R0 /* single word int return register */
#define REG_LRET TREG_R1 /* second word return register (for long long) */
#define REG_FRET TREG_F0 /* float return register */
#ifdef TCC_ARM_EABI
#define TOK___divdi3 TOK___aeabi_ldivmod
#define TOK___moddi3 TOK___aeabi_ldivmod
#define TOK___udivdi3 TOK___aeabi_uldivmod
#define TOK___umoddi3 TOK___aeabi_uldivmod
#endif
/* defined if function parameters must be evaluated in reverse order */
#define INVERT_FUNC_PARAMS
/* defined if structures are passed as pointers. Otherwise structures
are directly pushed on stack. */
/* #define FUNC_STRUCT_PARAM_AS_PTR */
/* pointer size, in bytes */
#define PTR_SIZE 4
/* long double size and alignment, in bytes */
#ifdef TCC_ARM_VFP
#define LDOUBLE_SIZE 8
#endif
#ifndef LDOUBLE_SIZE
#define LDOUBLE_SIZE 8
#endif
#ifdef TCC_ARM_EABI
#define LDOUBLE_ALIGN 8
#else
#define LDOUBLE_ALIGN 4
#endif
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
#define CHAR_IS_UNSIGNED
/******************************************************/
/* ELF defines */
#define EM_TCC_TARGET EM_ARM
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_ARM_ABS32
#define R_DATA_PTR R_ARM_ABS32
#define R_JMP_SLOT R_ARM_JUMP_SLOT
#define R_COPY R_ARM_COPY
#define ELF_START_ADDR 0x00008000
#define ELF_PAGE_SIZE 0x1000
enum float_abi {
ARM_SOFTFP_FLOAT,
ARM_HARD_FLOAT,
};
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#include "tcc.h"
enum float_abi float_abi;
ST_DATA const int reg_classes[NB_REGS] = {
/* r0 */ RC_INT | RC_R0,
/* r1 */ RC_INT | RC_R1,
/* r2 */ RC_INT | RC_R2,
/* r3 */ RC_INT | RC_R3,
/* r12 */ RC_INT | RC_R12,
/* f0 */ RC_FLOAT | RC_F0,
/* f1 */ RC_FLOAT | RC_F1,
/* f2 */ RC_FLOAT | RC_F2,
/* f3 */ RC_FLOAT | RC_F3,
#ifdef TCC_ARM_VFP
/* d4/s8 */ RC_FLOAT | RC_F4,
/* d5/s10 */ RC_FLOAT | RC_F5,
/* d6/s12 */ RC_FLOAT | RC_F6,
/* d7/s14 */ RC_FLOAT | RC_F7,
#endif
};
static int func_sub_sp_offset, last_itod_magic;
static int leaffunc;
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
static CType float_type, double_type, func_float_type, func_double_type;
ST_FUNC void arm_init(struct TCCState *s)
{
float_type.t = VT_FLOAT;
double_type.t = VT_DOUBLE;
func_float_type.t = VT_FUNC;
func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
func_double_type.t = VT_FUNC;
func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
float_abi = s->float_abi;
#ifndef TCC_ARM_HARDFLOAT
tcc_warning("soft float ABI currently not supported: default to softfp");
#endif
}
#else
#define func_float_type func_old_type
#define func_double_type func_old_type
src/arm-gen.c view on Meta::CPAN
calcaddr(&base,&fc,&sign,1020,2);
#ifdef TCC_ARM_VFP
op=0xED000A00; /* fsts */
if(!sign)
op|=0x800000;
if ((ft & VT_BTYPE) != VT_FLOAT)
op|=0x100; /* fsts -> fstd */
o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
#else
op=0xED000100;
if(!sign)
op|=0x800000;
#if LDOUBLE_SIZE == 8
if ((ft & VT_BTYPE) != VT_FLOAT)
op|=0x8000;
#else
if ((ft & VT_BTYPE) == VT_DOUBLE)
op|=0x8000;
if ((ft & VT_BTYPE) == VT_LDOUBLE)
op|=0x400000;
#endif
o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
#endif
return;
} else if((ft & VT_BTYPE) == VT_SHORT) {
calcaddr(&base,&fc,&sign,255,0);
op=0xE14000B0;
if(!sign)
op|=0x800000;
o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));
} else {
calcaddr(&base,&fc,&sign,4095,0);
op=0xE5000000;
if(!sign)
op|=0x800000;
if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
op|=0x400000;
o(op|(intr(r)<<12)|fc|(base<<16));
}
return;
}
}
tcc_error("store unimplemented");
}
static void gadd_sp(int val)
{
stuff_const_harder(0xE28DD000,val);
}
/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
uint32_t x;
/* constant case */
x=encbranch(ind,ind+vtop->c.i,0);
if(x) {
if (vtop->r & VT_SYM) {
/* relocation case */
greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
} else
put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
o(x|(is_jmp?0xE0000000:0xE1000000));
} else {
if(!is_jmp)
o(0xE28FE004); // add lr,pc,#4
o(0xE51FF004); // ldr pc,[pc,#-4]
if (vtop->r & VT_SYM)
greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
o(vtop->c.i);
}
} else {
/* otherwise, indirect call */
r = gv(RC_INT);
if(!is_jmp)
o(0xE1A0E00F); // mov lr,pc
o(0xE1A0F000|intr(r)); // mov pc,r
}
}
static int unalias_ldbl(int btype)
{
#if LDOUBLE_SIZE == 8
if (btype == VT_LDOUBLE)
btype = VT_DOUBLE;
#endif
return btype;
}
/* Return whether a structure is an homogeneous float aggregate or not.
The answer is true if all the elements of the structure are of the same
primitive float type and there is less than 4 elements.
type: the type corresponding to the structure to be tested */
static int is_hgen_float_aggr(CType *type)
{
if ((type->t & VT_BTYPE) == VT_STRUCT) {
struct Sym *ref;
int btype, nb_fields = 0;
ref = type->ref->next;
btype = unalias_ldbl(ref->type.t & VT_BTYPE);
if (btype == VT_FLOAT || btype == VT_DOUBLE) {
for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
return !ref && nb_fields <= 4;
}
}
return 0;
}
struct avail_regs {
signed char avail[3]; /* 3 holes max with only float and double alignments */
int first_hole; /* first available hole */
int last_hole; /* last available hole (none if equal to first_hole) */
int first_free_reg; /* next free register in the sequence, hole excluded */
};
#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
( run in 1.003 second using v1.01-cache-2.11-cpan-71847e10f99 )