Ignore:
Timestamp:
Jan 21, 2018, 12:10:09 AM (6 years ago)
Author:
coas-nagasima
Message:

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

Location:
EcnlProtoTool/trunk/tcc-0.9.27
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/tcc-0.9.27/arm-gen.c

    r321 r331  
    11/*
    22 *  ARMv4 code generator for TCC
    3  * 
     3 *
    44 *  Copyright (c) 2003 Daniel Glöckner
    55 *  Copyright (c) 2012 Thomas Preud'homme
     
    2424#ifdef TARGET_DEFS_ONLY
    2525
    26 #ifdef TCC_ARM_EABI
    27 #ifndef TCC_ARM_VFP // Avoid useless warning
    28 #define TCC_ARM_VFP
    29 #endif
     26#if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP)
     27#error "Currently TinyCC only supports float computation with VFP instructions"
    3028#endif
    3129
     
    3735#endif
    3836
    39 #ifndef TCC_ARM_VERSION
    40 # define TCC_ARM_VERSION 5
     37#ifndef TCC_CPU_VERSION
     38# define TCC_CPU_VERSION 5
    4139#endif
    4240
     
    4745#define RC_FLOAT   0x0002 /* generic float register */
    4846#define RC_R0      0x0004
    49 #define RC_R1      0x0008 
     47#define RC_R1      0x0008
    5048#define RC_R2      0x0010
    5149#define RC_R3      0x0020
     
    8280    TREG_F7,
    8381#endif
     82    TREG_SP = 13,
     83    TREG_LR,
    8484};
    8585
     
    105105/* defined if structures are passed as pointers. Otherwise structures
    106106   are directly pushed on stack. */
    107 //#define FUNC_STRUCT_PARAM_AS_PTR
     107/* #define FUNC_STRUCT_PARAM_AS_PTR */
    108108
    109109/* pointer size, in bytes */
     
    131131
    132132/******************************************************/
    133 /* ELF defines */
    134 
    135 #define EM_TCC_TARGET EM_ARM
    136 
    137 /* relocation type for 32 bit data relocation */
    138 #define R_DATA_32   R_ARM_ABS32
    139 #define R_DATA_PTR  R_ARM_ABS32
    140 #define R_JMP_SLOT  R_ARM_JUMP_SLOT
    141 #define R_COPY      R_ARM_COPY
    142 
    143 #define ELF_START_ADDR 0x00008000
    144 #define ELF_PAGE_SIZE  0x1000
    145 
    146 /******************************************************/
    147133#else /* ! TARGET_DEFS_ONLY */
    148134/******************************************************/
    149135#include "tcc.h"
     136
     137enum float_abi float_abi;
    150138
    151139ST_DATA const int reg_classes[NB_REGS] = {
     
    172160#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
    173161static CType float_type, double_type, func_float_type, func_double_type;
    174 ST_FUNC void arm_init_types(void)
     162ST_FUNC void arm_init(struct TCCState *s)
    175163{
    176164    float_type.t = VT_FLOAT;
     
    180168    func_double_type.t = VT_FUNC;
    181169    func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
     170
     171    float_abi = s->float_abi;
     172#ifndef TCC_ARM_HARDFLOAT
     173    tcc_warning("soft float ABI currently not supported: default to softfp");
     174#endif
    182175}
    183176#else
     
    185178#define func_double_type func_old_type
    186179#define func_ldouble_type func_old_type
    187 ST_FUNC void arm_init_types(void) {}
     180ST_FUNC void arm_init(struct TCCState *s)
     181{
     182#if 0
     183#if !defined (TCC_ARM_VFP)
     184    tcc_warning("Support for FPA is deprecated and will be removed in next"
     185                " release");
     186#endif
     187#if !defined (TCC_ARM_EABI)
     188    tcc_warning("Support for OABI is deprecated and will be removed in next"
     189                " release");
     190#endif
     191#endif
     192}
    188193#endif
    189194
     
    198203/******************************************************/
    199204
    200 void o(unsigned int i)
     205#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
     206const char *default_elfinterp(struct TCCState *s)
     207{
     208    if (s->float_abi == ARM_HARD_FLOAT)
     209        return "/lib/ld-linux-armhf.so.3";
     210    else
     211        return "/lib/ld-linux.so.3";
     212}
     213#endif
     214
     215void o(uint32_t i)
    201216{
    202217  /* this is a good place to start adding big-endian support*/
    203218  int ind1;
    204 
     219  if (nocode_wanted)
     220    return;
    205221  ind1 = ind + 4;
    206222  if (!cur_text_section)
     
    212228  i>>=8;
    213229  cur_text_section->data[ind++] = i&255;
    214   i>>=8; 
     230  i>>=8;
    215231  cur_text_section->data[ind++] = i&255;
    216232  i>>=8;
     
    328344}
    329345
    330 ST_FUNC uint32_t encbranch(int pos, int addr, int fail)
     346uint32_t encbranch(int pos, int addr, int fail)
    331347{
    332348  addr-=pos+8;
     
    377393  if(r<TREG_F0 || r>TREG_F7)
    378394    tcc_error("compiler error! register %i is no vfp register",r);
    379   return r-5;
     395  return r - TREG_F0;
    380396}
    381397#else
     
    384400  if(r<TREG_F0 || r>TREG_F3)
    385401    tcc_error("compiler error! register %i is no fpa register",r);
    386   return r-5;
     402  return r - TREG_F0;
    387403}
    388404#endif
     
    390406static uint32_t intr(int r)
    391407{
    392   if(r==4)
     408  if(r == TREG_R12)
    393409    return 12;
    394   if((r<0 || r>4) && r!=14)
    395     tcc_error("compiler error! register %i is no int register",r);
    396   return r;
     410  if(r >= TREG_R0 && r <= TREG_R3)
     411    return r - TREG_R0;
     412  if (r >= TREG_SP && r <= TREG_LR)
     413    return r + (13 - TREG_SP);
     414  tcc_error("compiler error! register %i is no int register",r);
    397415}
    398416
     
    499517  fr = sv->r;
    500518  ft = sv->type.t;
    501   fc = sv->c.ul;
     519  fc = sv->c.i;
    502520
    503521  if(fc>=0)
     
    507525    fc=-fc;
    508526  }
    509  
     527
    510528  v = fr & VT_VALMASK;
    511529  if (fr & VT_LVAL) {
     
    514532      v1.type.t = VT_PTR;
    515533      v1.r = VT_LOCAL | VT_LVAL;
    516       v1.c.ul = sv->c.ul;
    517       load(base=14 /* lr */, &v1);
     534      v1.c.i = sv->c.i;
     535      load(TREG_LR, &v1);
     536      base = 14; /* lr */
    518537      fc=sign=0;
    519538      v=VT_LOCAL;
     
    521540      v1.type.t = VT_PTR;
    522541      v1.r = fr&~VT_LVAL;
    523       v1.c.ul = sv->c.ul;
     542      v1.c.i = sv->c.i;
    524543      v1.sym=sv->sym;
    525       load(base=14, &v1);
     544      load(TREG_LR, &v1);
     545      base = 14; /* lr */
    526546      fc=sign=0;
    527547      v=VT_LOCAL;
     
    572592        if(!sign)
    573593          op|=0x800000;
    574         if ((ft & VT_BTYPE) == VT_BYTE)
     594        if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
    575595          op|=0x400000;
    576596        o(op|(intr(r)<<12)|fc|(base<<16));
     
    580600  } else {
    581601    if (v == VT_CONST) {
    582       op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
     602      op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i);
    583603      if (fr & VT_SYM || !op) {
    584604        o(0xE59F0000|(intr(r)<<12));
     
    586606        if(fr & VT_SYM)
    587607          greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
    588         o(sv->c.ul);
     608        o(sv->c.i);
    589609      } else
    590610        o(op);
    591611      return;
    592612    } else if (v == VT_LOCAL) {
    593       op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
     613      op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i);
    594614      if (fr & VT_SYM || !op) {
    595615        o(0xE59F0000|(intr(r)<<12));
     
    597617        if(fr & VT_SYM) // needed ?
    598618          greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
    599         o(sv->c.ul);
     619        o(sv->c.i);
    600620        o(0xE08B0000|(intr(r)<<12)|intr(r));
    601621      } else
     
    603623      return;
    604624    } else if(v == VT_CMP) {
    605       o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
    606       o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
     625      o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12));
     626      o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12));
    607627      return;
    608628    } else if (v == VT_JMP || v == VT_JMPI) {
     
    611631      o(0xE3A00000|(intr(r)<<12)|t);
    612632      o(0xEA000000);
    613       gsym(sv->c.ul);
     633      gsym(sv->c.i);
    614634      o(0xE3A00000|(intr(r)<<12)|(t^1));
    615635      return;
     
    638658  fr = sv->r;
    639659  ft = sv->type.t;
    640   fc = sv->c.ul;
     660  fc = sv->c.i;
    641661
    642662  if(fc>=0)
     
    646666    fc=-fc;
    647667  }
    648  
    649   v = fr & VT_VALMASK; 
     668
     669  v = fr & VT_VALMASK;
    650670  if (fr & VT_LVAL || fr == VT_LOCAL) {
    651     uint32_t base = 0xb;
     671    uint32_t base = 0xb; /* fp */
    652672    if(v < VT_CONST) {
    653673      base=intr(v);
     
    657677      v1.type.t = ft;
    658678      v1.r = fr&~VT_LVAL;
    659       v1.c.ul = sv->c.ul;
     679      v1.c.i = sv->c.i;
    660680      v1.sym=sv->sym;
    661       load(base=14, &v1);
     681      load(TREG_LR, &v1);
     682      base = 14; /* lr */
    662683      fc=sign=0;
    663       v=VT_LOCAL;   
     684      v=VT_LOCAL;
    664685    }
    665686    if(v == VT_LOCAL) {
     
    668689#ifdef TCC_ARM_VFP
    669690        op=0xED000A00; /* fsts */
    670         if(!sign) 
    671           op|=0x800000; 
    672         if ((ft & VT_BTYPE) != VT_FLOAT) 
     691        if(!sign)
     692          op|=0x800000;
     693        if ((ft & VT_BTYPE) != VT_FLOAT)
    673694          op|=0x100;   /* fsts -> fstd */
    674695        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
     
    700721        if(!sign)
    701722          op|=0x800000;
    702         if ((ft & VT_BTYPE) == VT_BYTE)
     723        if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
    703724          op|=0x400000;
    704725        o(op|(intr(r)<<12)|fc|(base<<16));
     
    722743    uint32_t x;
    723744    /* constant case */
    724     x=encbranch(ind,ind+vtop->c.ul,0);
     745    x=encbranch(ind,ind+vtop->c.i,0);
    725746    if(x) {
    726747      if (vtop->r & VT_SYM) {
     
    736757      if (vtop->r & VT_SYM)
    737758        greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
    738       o(vtop->c.ul);
     759      o(vtop->c.i);
    739760    }
    740761  } else {
     
    747768}
    748769
    749 #ifdef TCC_ARM_HARDFLOAT
    750 static int is_float_hgen_aggr(CType *type)
     770static int unalias_ldbl(int btype)
     771{
     772#if LDOUBLE_SIZE == 8
     773    if (btype == VT_LDOUBLE)
     774      btype = VT_DOUBLE;
     775#endif
     776    return btype;
     777}
     778
     779/* Return whether a structure is an homogeneous float aggregate or not.
     780   The answer is true if all the elements of the structure are of the same
     781   primitive float type and there is less than 4 elements.
     782
     783   type: the type corresponding to the structure to be tested */
     784static int is_hgen_float_aggr(CType *type)
    751785{
    752786  if ((type->t & VT_BTYPE) == VT_STRUCT) {
     
    754788    int btype, nb_fields = 0;
    755789
    756     ref = type->ref;
    757     btype = ref->type.t & VT_BTYPE;
     790    ref = type->ref->next;
     791    btype = unalias_ldbl(ref->type.t & VT_BTYPE);
    758792    if (btype == VT_FLOAT || btype == VT_DOUBLE) {
    759       for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
     793      for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
    760794      return !ref && nb_fields <= 4;
    761795    }
     
    765799
    766800struct avail_regs {
    767   /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */
    768   signed char avail[3];
    769   int first_hole;
    770   int last_hole;
    771   int first_free_reg;
     801  signed char avail[3]; /* 3 holes max with only float and double alignments */
     802  int first_hole; /* first available hole */
     803  int last_hole; /* last available hole (none if equal to first_hole) */
     804  int first_free_reg; /* next free register in the sequence, hole excluded */
    772805};
    773806
    774807#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
    775808
    776 /* Assign a register for a CPRC param with correct size and alignment
    777  * size and align are in bytes, as returned by type_size */
    778 int assign_fpreg(struct avail_regs *avregs, int align, int size)
     809/* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC
     810   param) according to the rules described in the procedure call standard for
     811   the ARM architecture (AAPCS). If found, the registers are assigned to this
     812   VFP CPRC parameter. Registers are allocated in sequence unless a hole exists
     813   and the parameter is a single float.
     814
     815   avregs: opaque structure to keep track of available VFP co-processor regs
     816   align: alignment constraints for the param, as returned by type_size()
     817   size: size of the parameter, as returned by type_size() */
     818int assign_vfpreg(struct avail_regs *avregs, int align, int size)
    779819{
    780820  int first_reg = 0;
     
    782822  if (avregs->first_free_reg == -1)
    783823    return -1;
    784   if (align >> 3) { // alignment needed (base type: double)
     824  if (align >> 3) { /* double alignment */
    785825    first_reg = avregs->first_free_reg;
     826    /* alignment constraint not respected so use next reg and record hole */
    786827    if (first_reg & 1)
    787828      avregs->avail[avregs->last_hole++] = first_reg++;
    788   } else {
     829  } else { /* no special alignment (float or array of float) */
     830    /* if single float and a hole is available, assign the param to it */
    789831    if (size == 4 && avregs->first_hole != avregs->last_hole)
    790832      return avregs->avail[avregs->first_hole++];
     
    799841  return -1;
    800842}
    801 #endif
    802 
    803 /* Generate function call. The function address is pushed first, then
    804    all the parameters in call order. This functions pops all the
    805    parameters and the function address. */
    806 void gfunc_call(int nb_args)
    807 {
    808   int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno;
    809   signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
    810   SValue *before_stack = NULL; /* SValue before first on stack argument */
    811   SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */
    812 #ifdef TCC_ARM_HARDFLOAT
     843
     844/* Returns whether all params need to be passed in core registers or not.
     845   This is the case for function part of the runtime ABI. */
     846int floats_in_core_regs(SValue *sval)
     847{
     848  if (!sval->sym)
     849    return 0;
     850
     851  switch (sval->sym->v) {
     852    case TOK___floatundisf:
     853    case TOK___floatundidf:
     854    case TOK___fixunssfdi:
     855    case TOK___fixunsdfdi:
     856#ifndef TCC_ARM_VFP
     857    case TOK___fixunsxfdi:
     858#endif
     859    case TOK___floatdisf:
     860    case TOK___floatdidf:
     861    case TOK___fixsfdi:
     862    case TOK___fixdfdi:
     863      return 1;
     864
     865    default:
     866      return 0;
     867  }
     868}
     869
     870/* Return the number of registers needed to return the struct, or 0 if
     871   returning via struct pointer. */
     872ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
     873#ifdef TCC_ARM_EABI
     874    int size, align;
     875    size = type_size(vt, &align);
     876    if (float_abi == ARM_HARD_FLOAT && !variadic &&
     877        (is_float(vt->t) || is_hgen_float_aggr(vt))) {
     878        *ret_align = 8;
     879        *regsize = 8;
     880        ret->ref = NULL;
     881        ret->t = VT_DOUBLE;
     882        return (size + 7) >> 3;
     883    } else if (size <= 4) {
     884        *ret_align = 4;
     885        *regsize = 4;
     886        ret->ref = NULL;
     887        ret->t = VT_INT;
     888        return 1;
     889    } else
     890        return 0;
     891#else
     892    return 0;
     893#endif
     894}
     895
     896/* Parameters are classified according to how they are copied to their final
     897   destination for the function call. Because the copying is performed class
     898   after class according to the order in the union below, it is important that
     899   some constraints about the order of the members of this union are respected:
     900   - CORE_STRUCT_CLASS must come after STACK_CLASS;
     901   - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and
     902     VFP_STRUCT_CLASS;
     903   - VFP_STRUCT_CLASS must come after VFP_CLASS.
     904   See the comment for the main loop in copy_params() for the reason. */
     905enum reg_class {
     906        STACK_CLASS = 0,
     907        CORE_STRUCT_CLASS,
     908        VFP_CLASS,
     909        VFP_STRUCT_CLASS,
     910        CORE_CLASS,
     911        NB_CLASSES
     912};
     913
     914struct param_plan {
     915    int start; /* first reg or addr used depending on the class */
     916    int end; /* last reg used or next free addr depending on the class */
     917    SValue *sval; /* pointer to SValue on the value stack */
     918    struct param_plan *prev; /*  previous element in this class */
     919};
     920
     921struct plan {
     922    struct param_plan *pplans; /* array of all the param plans */
     923    struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */
     924};
     925
     926#define add_param_plan(plan,pplan,class)                        \
     927    do {                                                        \
     928        pplan.prev = plan->clsplans[class];                     \
     929        plan->pplans[plan ## _nb] = pplan;                      \
     930        plan->clsplans[class] = &plan->pplans[plan ## _nb++];   \
     931    } while(0)
     932
     933/* Assign parameters to registers and stack with alignment according to the
     934   rules in the procedure call standard for the ARM architecture (AAPCS).
     935   The overall assignment is recorded in an array of per parameter structures
     936   called parameter plans. The parameter plans are also further organized in a
     937   number of linked lists, one per class of parameter (see the comment for the
     938   definition of union reg_class).
     939
     940   nb_args: number of parameters of the function for which a call is generated
     941   float_abi: float ABI in use for this function call
     942   plan: the structure where the overall assignment is recorded
     943   todo: a bitmap that record which core registers hold a parameter
     944
     945   Returns the amount of stack space needed for parameter passing
     946
     947   Note: this function allocated an array in plan->pplans with tcc_malloc. It
     948   is the responsibility of the caller to free this array once used (ie not
     949   before copy_params). */
     950static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
     951{
     952  int i, size, align;
     953  int ncrn /* next core register number */, nsaa /* next stacked argument address*/;
     954  int plan_nb = 0;
     955  struct param_plan pplan;
    813956  struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
    814   signed char vfp_plan[16];
    815   int plan2[4+16];
    816   int variadic;
    817 #else
    818   int plan2[4]={0,0,0,0};
    819 #endif
    820   int vfp_todo=0;
    821   int todo=0, keep;
    822 
    823 #ifdef TCC_ARM_HARDFLOAT
    824   memset(vfp_plan, -1, sizeof(vfp_plan));
    825   memset(plan2, 0, sizeof(plan2));
    826   variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
    827 #endif
    828   r = vtop->r & VT_VALMASK;
    829   if (r == VT_CMP || (r & ~1) == VT_JMP)
    830     gv(RC_INT);
    831 #ifdef TCC_ARM_EABI
    832   if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT
    833      && type_size(&vtop[-nb_args].type.ref->type, &align) <= 4) {
    834     SValue tmp;
    835     tmp=vtop[-nb_args];
    836     vtop[-nb_args]=vtop[-nb_args+1];
    837     vtop[-nb_args+1]=tmp;
    838     --nb_args;
    839   }
    840  
    841   vpushi(0), nb_args++;
    842   vtop->type.t = VT_LLONG;
    843 #endif
    844   ncrn = ncprn = argno = vfp_argno = args_size = 0;
    845   /* Assign argument to registers and stack with alignment.
    846      If, considering alignment constraints, enough registers of the correct type
    847      (core or VFP) are free for the current argument, assign them to it, else
    848      allocate on stack with correct alignment. Whenever a structure is allocated
    849      in registers or on stack, it is always put on the stack at this stage. The
    850      stack is divided in 3 zones. The zone are, from low addresses to high
    851      addresses: structures to be loaded in core registers, structures to be
    852      loaded in VFP registers, argument allocated to stack. SValue's representing
    853      structures in the first zone are moved just after the SValue pointed by
    854      before_vfpreg_hfa. SValue's representing structures in the second zone are
    855      moved just after the SValue pointer by before_stack. */
     957
     958  ncrn = nsaa = 0;
     959  *todo = 0;
     960  plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
     961  memset(plan->clsplans, 0, sizeof(plan->clsplans));
    856962  for(i = nb_args; i-- ;) {
    857     int j, assigned_vfpreg = 0;
    858     size = type_size(&vtop[-i].type, &align);
     963    int j, start_vfpreg = 0;
     964    CType type = vtop[-i].type;
     965    type.t &= ~VT_ARRAY;
     966    size = type_size(&type, &align);
     967    size = (size + 3) & ~3;
     968    align = (align + 3) & ~3;
    859969    switch(vtop[-i].type.t & VT_BTYPE) {
    860970      case VT_STRUCT:
     
    862972      case VT_DOUBLE:
    863973      case VT_LDOUBLE:
    864 #ifdef TCC_ARM_HARDFLOAT
    865       if (!variadic) {
    866         int hfa = 0; /* Homogeneous float aggregate */
     974      if (float_abi == ARM_HARD_FLOAT) {
     975        int is_hfa = 0; /* Homogeneous float aggregate */
    867976
    868977        if (is_float(vtop[-i].type.t)
    869             || (hfa = is_float_hgen_aggr(&vtop[-i].type))) {
    870           int end_reg;
    871 
    872           assigned_vfpreg = assign_fpreg(&avregs, align, size);
    873           end_reg = assigned_vfpreg + (size - 1) / 4;
    874           if (assigned_vfpreg >= 0) {
    875             vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2;
    876             if (hfa) {
    877               /* before_stack can only have been set because all core registers
    878                  are assigned, so no need to care about before_vfpreg_hfa if
    879                  before_stack is set */
    880               if (before_stack) {
    881                 vrote(&vtop[-i], &vtop[-i] - before_stack);
    882                 before_stack++;
    883               } else if (!before_vfpreg_hfa)
    884                 before_vfpreg_hfa = &vtop[-i-1];
    885               for (j = assigned_vfpreg; j <= end_reg; j++)
    886                 vfp_todo|=(1<<j);
    887             }
     978            || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {
     979          int end_vfpreg;
     980
     981          start_vfpreg = assign_vfpreg(&avregs, align, size);
     982          end_vfpreg = start_vfpreg + ((size - 1) >> 2);
     983          if (start_vfpreg >= 0) {
     984            pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};
     985            if (is_hfa)
     986              add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
     987            else
     988              add_param_plan(plan, pplan, VFP_CLASS);
    888989            continue;
    889           } else {
    890             if (!hfa)
    891               vfp_argno++;
    892             /* No need to update before_stack as no more hfa can be allocated in
    893                VFP regs */
    894             if (!before_vfpreg_hfa)
    895               before_vfpreg_hfa = &vtop[-i-1];
     990          } else
    896991            break;
    897           }
    898992        }
    899993      }
    900 #endif
    901       ncrn = (ncrn + (align-1)/4) & -(align/4);
    902       size = (size + 3) & -4;
    903       if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) {
    904         /* Either there is HFA in VFP registers, or there is arguments on stack,
    905            it cannot be both. Hence either before_stack already points after
    906            the slot where the vtop[-i] SValue is moved, or before_stack will not
    907            be used */
    908         if (before_vfpreg_hfa) {
    909           vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa);
    910           before_vfpreg_hfa++;
    911         }
     994      ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1);
     995      if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) {
     996        /* The parameter is allocated both in core register and on stack. As
     997         * such, it can be of either class: it would either be the last of
     998         * CORE_STRUCT_CLASS or the first of STACK_CLASS. */
    912999        for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
    913           todo|=(1<<j);
    914         ncrn+=size/4;
    915         if (ncrn > 4) {
    916           args_size = (ncrn - 4) * 4;
    917           if (!before_stack)
    918             before_stack = &vtop[-i-1];
    919         }
    920       }
    921       else {
     1000          *todo|=(1<<j);
     1001        pplan = (struct param_plan) {ncrn, j, &vtop[-i]};
     1002        add_param_plan(plan, pplan, CORE_STRUCT_CLASS);
     1003        ncrn += size/4;
     1004        if (ncrn > 4)
     1005          nsaa = (ncrn - 4) * 4;
     1006      } else {
    9221007        ncrn = 4;
    923         /* No need to set before_vfpreg_hfa if not set since there will no
    924            longer be any structure assigned to core registers */
    925         if (!before_stack)
    926           before_stack = &vtop[-i-1];
    9271008        break;
    9281009      }
    9291010      continue;
    9301011      default:
    931 #ifdef TCC_ARM_EABI
    932       if (!i) {
    933         break;
    934       }
    935 #endif
    9361012      if (ncrn < 4) {
    9371013        int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
     
    9391015        if (is_long) {
    9401016          ncrn = (ncrn + 1) & -2;
    941           if (ncrn == 4) {
    942             argno++;
     1017          if (ncrn == 4)
    9431018            break;
     1019        }
     1020        pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]};
     1021        ncrn++;
     1022        if (is_long)
     1023          pplan.end = ncrn++;
     1024        add_param_plan(plan, pplan, CORE_CLASS);
     1025        continue;
     1026      }
     1027    }
     1028    nsaa = (nsaa + (align - 1)) & ~(align - 1);
     1029    pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]};
     1030    add_param_plan(plan, pplan, STACK_CLASS);
     1031    nsaa += size; /* size already rounded up before */
     1032  }
     1033  return nsaa;
     1034}
     1035
     1036#undef add_param_plan
     1037
     1038/* Copy parameters to their final destination (core reg, VFP reg or stack) for
     1039   function call.
     1040
     1041   nb_args: number of parameters the function take
     1042   plan: the overall assignment plan for parameters
     1043   todo: a bitmap indicating what core reg will hold a parameter
     1044
     1045   Returns the number of SValue added by this function on the value stack */
     1046static int copy_params(int nb_args, struct plan *plan, int todo)
     1047{
     1048  int size, align, r, i, nb_extra_sval = 0;
     1049  struct param_plan *pplan;
     1050  int pass = 0;
     1051
     1052   /* Several constraints require parameters to be copied in a specific order:
     1053      - structures are copied to the stack before being loaded in a reg;
     1054      - floats loaded to an odd numbered VFP reg are first copied to the
     1055        preceding even numbered VFP reg and then moved to the next VFP reg.
     1056
     1057      It is thus important that:
     1058      - structures assigned to core regs must be copied after parameters
     1059        assigned to the stack but before structures assigned to VFP regs because
     1060        a structure can lie partly in core registers and partly on the stack;
     1061      - parameters assigned to the stack and all structures be copied before
     1062        parameters assigned to a core reg since copying a parameter to the stack
     1063        require using a core reg;
     1064      - parameters assigned to VFP regs be copied before structures assigned to
     1065        VFP regs as the copy might use an even numbered VFP reg that already
     1066        holds part of a structure. */
     1067again:
     1068  for(i = 0; i < NB_CLASSES; i++) {
     1069    for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
     1070
     1071      if (pass
     1072          && (i != CORE_CLASS || pplan->sval->r < VT_CONST))
     1073        continue;
     1074
     1075      vpushv(pplan->sval);
     1076      pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
     1077      switch(i) {
     1078        case STACK_CLASS:
     1079        case CORE_STRUCT_CLASS:
     1080        case VFP_STRUCT_CLASS:
     1081          if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
     1082            int padding = 0;
     1083            size = type_size(&pplan->sval->type, &align);
     1084            /* align to stack align size */
     1085            size = (size + 3) & ~3;
     1086            if (i == STACK_CLASS && pplan->prev)
     1087              padding = pplan->start - pplan->prev->end;
     1088            size += padding; /* Add padding if any */
     1089            /* allocate the necessary size on stack */
     1090            gadd_sp(-size);
     1091            /* generate structure store */
     1092            r = get_reg(RC_INT);
     1093            o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */
     1094            vset(&vtop->type, r | VT_LVAL, 0);
     1095            vswap();
     1096            vstore(); /* memcpy to current sp + potential padding */
     1097
     1098            /* Homogeneous float aggregate are loaded to VFP registers
     1099               immediately since there is no way of loading data in multiple
     1100               non consecutive VFP registers as what is done for other
     1101               structures (see the use of todo). */
     1102            if (i == VFP_STRUCT_CLASS) {
     1103              int first = pplan->start, nb = pplan->end - first + 1;
     1104              /* vpop.32 {pplan->start, ..., pplan->end} */
     1105              o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);
     1106              /* No need to write the register used to a SValue since VFP regs
     1107                 cannot be used for gcall_or_jmp */
     1108            }
     1109          } else {
     1110            if (is_float(pplan->sval->type.t)) {
     1111#ifdef TCC_ARM_VFP
     1112              r = vfpr(gv(RC_FLOAT)) << 12;
     1113              if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
     1114                size = 4;
     1115              else {
     1116                size = 8;
     1117                r |= 0x101; /* vpush.32 -> vpush.64 */
     1118              }
     1119              o(0xED2D0A01 + r); /* vpush */
     1120#else
     1121              r = fpr(gv(RC_FLOAT)) << 12;
     1122              if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
     1123                size = 4;
     1124              else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
     1125                size = 8;
     1126              else
     1127                size = LDOUBLE_SIZE;
     1128
     1129              if (size == 12)
     1130                r |= 0x400000;
     1131              else if(size == 8)
     1132                r|=0x8000;
     1133
     1134              o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */
     1135#endif
     1136            } else {
     1137              /* simple type (currently always same size) */
     1138              /* XXX: implicit cast ? */
     1139              size=4;
     1140              if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
     1141                lexpand_nr();
     1142                size = 8;
     1143                r = gv(RC_INT);
     1144                o(0xE52D0004|(intr(r)<<12)); /* push r */
     1145                vtop--;
     1146              }
     1147              r = gv(RC_INT);
     1148              o(0xE52D0004|(intr(r)<<12)); /* push r */
     1149            }
     1150            if (i == STACK_CLASS && pplan->prev)
     1151              gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
    9441152          }
     1153          break;
     1154
     1155        case VFP_CLASS:
     1156          gv(regmask(TREG_F0 + (pplan->start >> 1)));
     1157          if (pplan->start & 1) { /* Must be in upper part of double register */
     1158            o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
     1159            vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
     1160          }
     1161          break;
     1162
     1163        case CORE_CLASS:
     1164          if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
     1165            lexpand_nr();
     1166            gv(regmask(pplan->end));
     1167            pplan->sval->r2 = vtop->r;
     1168            vtop--;
     1169          }
     1170          gv(regmask(pplan->start));
     1171          /* Mark register as used so that gcall_or_jmp use another one
     1172             (regs >=4 are free as never used to pass parameters) */
     1173          pplan->sval->r = vtop->r;
     1174          break;
     1175      }
     1176      vtop--;
     1177    }
     1178  }
     1179
     1180  /* second pass to restore registers that were saved on stack by accident.
     1181     Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */
     1182  if (++pass < 2)
     1183    goto again;
     1184
     1185  /* Manually free remaining registers since next parameters are loaded
     1186   * manually, without the help of gv(int). */
     1187  save_regs(nb_args);
     1188
     1189  if(todo) {
     1190    o(0xE8BD0000|todo); /* pop {todo} */
     1191    for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {
     1192      int r;
     1193      pplan->sval->r = pplan->start;
     1194      /* An SValue can only pin 2 registers at best (r and r2) but a structure
     1195         can occupy more than 2 registers. Thus, we need to push on the value
     1196         stack some fake parameter to have on SValue for each registers used
     1197         by a structure (r2 is not used). */
     1198      for (r = pplan->start + 1; r <= pplan->end; r++) {
     1199        if (todo & (1 << r)) {
     1200          nb_extra_sval++;
     1201          vpushi(0);
     1202          vtop->r = r;
    9451203        }
    946         plan[argno++][0]=ncrn++;
    947         if (is_long) {
    948           plan[argno-1][1]=ncrn++;
    949         }
    950         continue;
    951       }
    952       argno++;
    953     }
     1204      }
     1205    }
     1206  }
     1207  return nb_extra_sval;
     1208}
     1209
     1210/* Generate function call. The function address is pushed first, then
     1211   all the parameters in call order. This functions pops all the
     1212   parameters and the function address. */
     1213void gfunc_call(int nb_args)
     1214{
     1215  int r, args_size;
     1216  int def_float_abi = float_abi;
     1217  int todo;
     1218  struct plan plan;
     1219
    9541220#ifdef TCC_ARM_EABI
    955     if(args_size & (align-1)) {
    956       vpushi(0);
    957       vtop->type.t = VT_VOID; /* padding */
    958       vrott(i+2);
    959       args_size += 4;
    960       nb_args++;
    961       argno++;
    962     }
    963 #endif
    964     args_size += (size + 3) & -4;
    965   }
     1221  int variadic;
     1222
     1223  if (float_abi == ARM_HARD_FLOAT) {
     1224    variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
     1225    if (variadic || floats_in_core_regs(&vtop[-nb_args]))
     1226      float_abi = ARM_SOFTFP_FLOAT;
     1227  }
     1228#endif
     1229  /* cannot let cpu flags if other instruction are generated. Also avoid leaving
     1230     VT_JMP anywhere except on the top of the stack because it would complicate
     1231     the code generator. */
     1232  r = vtop->r & VT_VALMASK;
     1233  if (r == VT_CMP || (r & ~1) == VT_JMP)
     1234    gv(RC_INT);
     1235
     1236  args_size = assign_regs(nb_args, float_abi, &plan, &todo);
     1237
    9661238#ifdef TCC_ARM_EABI
    967   vtop--, nb_args--;
    968 #endif
    969   args_size = keep = 0;
    970   for(i = 0;i < nb_args; i++) {
    971     vrotb(keep+1);
    972     if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
    973       size = type_size(&vtop->type, &align);
    974       /* align to stack align size */
    975       size = (size + 3) & -4;
    976       /* allocate the necessary size on stack */
    977       gadd_sp(-size);
    978       /* generate structure store */
    979       r = get_reg(RC_INT);
    980       o(0xE1A0000D|(intr(r)<<12));
    981       vset(&vtop->type, r | VT_LVAL, 0);
    982       vswap();
    983       vstore();
    984       vtop--;
    985       args_size += size;
    986     } else if (is_float(vtop->type.t)) {
    987 #ifdef TCC_ARM_HARDFLOAT
    988       if (!variadic && --vfp_argno<16 && vfp_plan[vfp_argno]!=-1) {
    989         plan2[keep++]=vfp_plan[vfp_argno];
    990         continue;
    991       }
    992 #endif
    993 #ifdef TCC_ARM_VFP
    994       r=vfpr(gv(RC_FLOAT))<<12;
    995       size=4;
    996       if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
    997       {
    998         size=8;
    999         r|=0x101; /* fstms -> fstmd */
    1000       }
    1001       o(0xED2D0A01+r);
    1002 #else
    1003       r=fpr(gv(RC_FLOAT))<<12;
    1004       if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
    1005         size = 4;
    1006       else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
    1007         size = 8;
    1008       else
    1009         size = LDOUBLE_SIZE;
    1010      
    1011       if (size == 12)
    1012         r|=0x400000;
    1013       else if(size == 8)
    1014         r|=0x8000;
    1015 
    1016       o(0xED2D0100|r|(size>>2));
    1017 #endif
    1018       vtop--;
    1019       args_size += size;
    1020     } else {
    1021       int s;
    1022       /* simple type (currently always same size) */
    1023       /* XXX: implicit cast ? */
    1024       size=4;
    1025       if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
    1026         lexpand_nr();
    1027         s=-1;
    1028         if(--argno<4 && plan[argno][1]!=-1)
    1029           s=plan[argno][1];
    1030         argno++;
    1031         size = 8;
    1032         if(s==-1) {
    1033           r = gv(RC_INT);
    1034           o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
    1035           vtop--;
    1036         } else {
    1037           size=0;
    1038           plan2[keep]=s;
    1039           keep++;
    1040           vswap();
    1041         }
    1042       }
    1043       s=-1;
    1044       if(--argno<4 && plan[argno][0]!=-1)
    1045         s=plan[argno][0];
    1046 #ifdef TCC_ARM_EABI
    1047       if(vtop->type.t == VT_VOID) {
    1048         if(s == -1)
    1049           o(0xE24DD004); /* sub sp,sp,#4 */
    1050         vtop--;
    1051       } else
    1052 #endif
    1053       if(s == -1) {
    1054         r = gv(RC_INT);
    1055         o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
    1056         vtop--;
    1057       } else {
    1058         size=0;
    1059         plan2[keep]=s;
    1060         keep++;
    1061       }
    1062       args_size += size;
    1063     }
    1064   }
    1065   for(i = 0; i < keep; i++) {
    1066     vrotb(keep);
    1067     gv(regmask(plan2[i]));
    1068 #ifdef TCC_ARM_HARDFLOAT
    1069     /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
    1070     if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) {
    1071       o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i]));
    1072     }
    1073 #endif
    1074   }
    1075 save_regs(keep); /* save used temporary registers */
    1076   keep++;
    1077   if(ncrn) {
    1078     int nb_regs=0;
    1079     if (ncrn>4)
    1080       ncrn=4;
    1081     todo&=((1<<ncrn)-1);
    1082     if(todo) {
    1083       int i;
    1084       o(0xE8BD0000|todo);
    1085       for(i=0;i<4;i++)
    1086         if(todo&(1<<i)) {
    1087           vpushi(0);
    1088           vtop->r=i;
    1089           keep++;
    1090           nb_regs++;
    1091         }
    1092     }
    1093     args_size-=nb_regs*4;
    1094   }
    1095   if(vfp_todo) {
    1096     int nb_fregs=0;
    1097 
    1098     for(i=0;i<16;i++)
    1099       if(vfp_todo&(1<<i)) {
    1100         o(0xED9D0A00|(i&1)<<22|(i>>1)<<12|nb_fregs);
    1101         vpushi(0);
    1102         /* There might be 2 floats in a double VFP reg but that doesn't seem
    1103            to matter */
    1104         if (!(i%2))
    1105           vtop->r=TREG_F0+i/2;
    1106         keep++;
    1107         nb_fregs++;
    1108       }
    1109     if (nb_fregs) {
    1110       gadd_sp(nb_fregs*4);
    1111       args_size-=nb_fregs*4;
    1112     }
    1113   }
    1114   vrotb(keep);
     1239  if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
     1240    args_size = (args_size + 7) & ~7;
     1241    o(0xE24DD004); /* sub sp, sp, #4 */
     1242  }
     1243#endif
     1244
     1245  nb_args += copy_params(nb_args, &plan, todo);
     1246  tcc_free(plan.pplans);
     1247
     1248  /* Move fct SValue on top as required by gcall_or_jmp */
     1249  vrotb(nb_args + 1);
    11151250  gcall_or_jmp(0);
    11161251  if (args_size)
    1117       gadd_sp(args_size);
    1118 #ifdef TCC_ARM_EABI
    1119   if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT
    1120      && type_size(&vtop->type.ref->type, &align) <= 4)
    1121   {
    1122     store(REG_IRET,vtop-keep);
    1123     ++keep;
    1124   }
    1125 #ifdef TCC_ARM_VFP
    1126 #ifdef TCC_ARM_HARDFLOAT
    1127   else if(variadic && is_float(vtop->type.ref->type.t)) {
    1128 #else
    1129   else if(is_float(vtop->type.ref->type.t)) {
    1130 #endif
     1252      gadd_sp(args_size); /* pop all parameters passed on the stack */
     1253#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
     1254  if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
    11311255    if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
    1132       o(0xEE000A10); /* fmsr s0,r0 */
     1256      o(0xEE000A10); /*vmov s0, r0 */
    11331257    } else {
    1134       o(0xEE000B10); /* fmdlr d0,r0 */
    1135       o(0xEE201B10); /* fmdhr d0,r1 */
    1136     }
    1137   }
    1138 #endif
    1139 #endif
    1140   vtop-=keep;
    1141   leaffunc = 0;
     1258      o(0xEE000B10); /* vmov.32 d0[0], r0 */
     1259      o(0xEE201B10); /* vmov.32 d0[1], r1 */
     1260    }
     1261  }
     1262#endif
     1263  vtop -= nb_args + 1; /* Pop all params and fct address from value stack */
     1264  leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */
     1265  float_abi = def_float_abi;
    11421266}
    11431267
     
    11461270{
    11471271  Sym *sym,*sym2;
    1148   int n,nf,size,align, variadic, struct_ret = 0;
    1149 #ifdef TCC_ARM_HARDFLOAT
     1272  int n, nf, size, align, rs, struct_ret = 0;
     1273  int addr, pn, sn; /* pn=core, sn=stack */
     1274  CType ret_type;
     1275
     1276#ifdef TCC_ARM_EABI
    11501277  struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
    11511278#endif
     
    11531280  sym = func_type->ref;
    11541281  func_vt = sym->type;
     1282  func_var = (func_type->ref->f.func_type == FUNC_ELLIPSIS);
    11551283
    11561284  n = nf = 0;
    1157   variadic = (func_type->ref->c == FUNC_ELLIPSIS);
    1158   if((func_vt.t & VT_BTYPE) == VT_STRUCT
    1159      && type_size(&func_vt,&align) > 4)
     1285  if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
     1286      !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs))
    11601287  {
    11611288    n++;
     
    11631290    func_vc = 12; /* Offset from fp of the place to store the result */
    11641291  }
    1165   for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {
     1292  for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {
    11661293    size = type_size(&sym2->type, &align);
    1167 #ifdef TCC_ARM_HARDFLOAT
    1168     if (!variadic && (is_float(sym2->type.t)
    1169         || is_float_hgen_aggr(&sym2->type))) {
    1170       int tmpnf = assign_fpreg(&avregs, align, size) + 1;
     1294#ifdef TCC_ARM_EABI
     1295    if (float_abi == ARM_HARD_FLOAT && !func_var &&
     1296        (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {
     1297      int tmpnf = assign_vfpreg(&avregs, align, size);
     1298      tmpnf += (size + 3) / 4;
    11711299      nf = (tmpnf > nf) ? tmpnf : nf;
    11721300    } else
     
    11761304  }
    11771305  o(0xE1A0C00D); /* mov ip,sp */
    1178   if(variadic)
     1306  if (func_var)
    11791307    n=4;
    1180   if(n) {
     1308  if (n) {
    11811309    if(n>4)
    11821310      n=4;
     
    11951323  o(0xE1A0B00D); /* mov fp, sp */
    11961324  func_sub_sp_offset = ind;
    1197   o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */
    1198   {
    1199     int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */
    1200 
    1201 #ifdef TCC_ARM_HARDFLOAT
     1325  o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */
     1326
     1327#ifdef TCC_ARM_EABI
     1328  if (float_abi == ARM_HARD_FLOAT) {
     1329    func_vc += nf * 4;
    12021330    avregs = AVAIL_REGS_INITIALIZER;
    1203 #endif
    1204     while ((sym = sym->next)) {
    1205       CType *type;
    1206       type = &sym->type;
    1207       size = type_size(type, &align);
    1208       size = (size + 3) >> 2;
    1209       align = (align + 3) & ~3;
    1210 #ifdef TCC_ARM_HARDFLOAT
    1211       if (!variadic && (is_float(sym->type.t)
    1212           || is_float_hgen_aggr(&sym->type))) {
    1213         int fpn = assign_fpreg(&avregs, align, size << 2);
    1214         if (fpn >= 0) {
    1215           addr = fpn * 4;
    1216         } else
    1217           goto from_stack;
    1218       } else
    1219 #endif
    1220       if (pn < 4) {
     1331  }
     1332#endif
     1333  pn = struct_ret, sn = 0;
     1334  while ((sym = sym->next)) {
     1335    CType *type;
     1336    type = &sym->type;
     1337    size = type_size(type, &align);
     1338    size = (size + 3) >> 2;
     1339    align = (align + 3) & ~3;
     1340#ifdef TCC_ARM_EABI
     1341    if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t)
     1342        || is_hgen_float_aggr(&sym->type))) {
     1343      int fpn = assign_vfpreg(&avregs, align, size << 2);
     1344      if (fpn >= 0)
     1345        addr = fpn * 4;
     1346      else
     1347        goto from_stack;
     1348    } else
     1349#endif
     1350    if (pn < 4) {
    12211351#ifdef TCC_ARM_EABI
    12221352        pn = (pn + (align-1)/4) & -(align/4);
    12231353#endif
    1224         addr = (nf + pn) * 4;
    1225         pn += size;
    1226         if (!sn && pn > 4)
    1227           sn = (pn - 4);
    1228       } else {
    1229 #ifdef TCC_ARM_HARDFLOAT
     1354      addr = (nf + pn) * 4;
     1355      pn += size;
     1356      if (!sn && pn > 4)
     1357        sn = (pn - 4);
     1358    } else {
     1359#ifdef TCC_ARM_EABI
    12301360from_stack:
    1231 #endif
    1232 #ifdef TCC_ARM_EABI
    12331361        sn = (sn + (align-1)/4) & -(align/4);
    12341362#endif
    1235         addr = (n + nf + sn) * 4;
    1236         sn += size;
    1237       }
    1238       sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12);
    1239     }
     1363      addr = (n + nf + sn) * 4;
     1364      sn += size;
     1365    }
     1366    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),
     1367             addr + 12);
    12401368  }
    12411369  last_itod_magic=0;
     
    12491377  uint32_t x;
    12501378  int diff;
    1251 #ifdef TCC_ARM_EABI
    1252   /* Useless but harmless copy of the float result into main register(s) in case
    1253      of variadic function in the hardfloat variant */
    1254   if(is_float(func_vt.t)) {
     1379  /* Copy float return value to core register if base standard is used and
     1380     float computation is made with VFP */
     1381#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
     1382  if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {
    12551383    if((func_vt.t & VT_BTYPE) == VT_FLOAT)
    12561384      o(0xEE100A10); /* fmrs r0, s0 */
     
    12871415{
    12881416  int r;
     1417  if (nocode_wanted)
     1418    return t;
    12891419  r=ind;
    12901420  o(0xE0000000|encbranch(r,t,1));
     
    13031433  int v, r;
    13041434  uint32_t op;
     1435
    13051436  v = vtop->r & VT_VALMASK;
    13061437  r=ind;
    1307   if (v == VT_CMP) {
     1438
     1439  if (nocode_wanted) {
     1440    ;
     1441  } else if (v == VT_CMP) {
    13081442    op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
    13091443    op|=encbranch(r,t,1);
     
    13321466      gsym(vtop->c.i);
    13331467    }
    1334   } else {
    1335     if (is_float(vtop->type.t)) {
    1336       r=gv(RC_FLOAT);
    1337 #ifdef TCC_ARM_VFP
    1338       o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */
    1339       o(0xEEF1FA10); /* fmstat */
    1340 #else
    1341       o(0xEE90F118|(fpr(r)<<16));
    1342 #endif
    1343       vtop->r = VT_CMP;
    1344       vtop->c.i = TOK_NE;
    1345       return gtst(inv, t);
    1346     } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
    1347       /* constant jmp optimization */
    1348       if ((vtop->c.i != 0) != inv)
    1349         t = gjmp(t);
    1350     } else {
    1351       v = gv(RC_INT);
    1352       o(0xE3300000|(intr(v)<<16));
    1353       vtop->r = VT_CMP;
    1354       vtop->c.i = TOK_NE;
    1355       return gtst(inv, t);
    1356     }   
    13571468  }
    13581469  vtop--;
     
    15431654
    15441655/* generate a floating point operation 'v = t1 op t2' instruction. The
    1545  *    two operands are guaranted to have the same floating point type */
     1656 *    two operands are guaranteed to have the same floating point type */
    15461657void gen_opf(int op)
    15471658{
     
    16121723        case TOK_UGT: op=TOK_GT; break;
    16131724      }
    1614      
     1725
    16151726      vtop->r = VT_CMP;
    16161727      vtop->c.i = op;
     
    16731784
    16741785/* generate a floating point operation 'v = t1 op t2' instruction. The
    1675    two operands are guaranted to have the same floating point type */
     1786   two operands are guaranteed to have the same floating point type */
    16761787void gen_opf(int op)
    16771788{
     
    17631874        vswap();
    17641875        r2=fpr(gv(RC_FLOAT));
    1765       }     
     1876      }
    17661877      break;
    17671878    default:
     
    17751886          case TOK_ULE:
    17761887          case TOK_UGT:
    1777             tcc_error("unsigned comparision on floats?");
     1888            tcc_error("unsigned comparison on floats?");
    17781889            break;
    17791890          case TOK_LT:
     
    20002111}
    20012112
     2113/* Save the stack pointer onto the stack and return the location of its address */
     2114ST_FUNC void gen_vla_sp_save(int addr) {
     2115    SValue v;
     2116    v.type.t = VT_PTR;
     2117    v.r = VT_LOCAL | VT_LVAL;
     2118    v.c.i = addr;
     2119    store(TREG_SP, &v);
     2120}
     2121
     2122/* Restore the SP from a location on the stack */
     2123ST_FUNC void gen_vla_sp_restore(int addr) {
     2124    SValue v;
     2125    v.type.t = VT_PTR;
     2126    v.r = VT_LOCAL | VT_LVAL;
     2127    v.c.i = addr;
     2128    load(TREG_SP, &v);
     2129}
     2130
     2131/* Subtract from the stack pointer, and push the resulting value onto the stack */
     2132ST_FUNC void gen_vla_alloc(CType *type, int align) {
     2133    int r = intr(gv(RC_INT));
     2134    o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */
     2135#ifdef TCC_ARM_EABI
     2136    if (align < 8)
     2137        align = 8;
     2138#else
     2139    if (align < 4)
     2140        align = 4;
     2141#endif
     2142    if (align & (align - 1))
     2143        tcc_error("alignment is not a power of 2: %i", align);
     2144    o(stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */
     2145    vpop();
     2146}
     2147
    20022148/* end of ARM code generator */
    20032149/*************************************************************/
Note: See TracChangeset for help on using the changeset viewer.