Subversion Repositories Kolibri OS

Rev

Rev 647 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 647 Rev 6429
Line 1... Line 1...
1
/*
1
/*
2
 *  ARMv4 code generator for TCC
2
 *  ARMv4 code generator for TCC
3
 * 
3
 *
4
 *  Copyright (c) 2003 Daniel Glöckner
4
 *  Copyright (c) 2003 Daniel Glöckner
-
 
5
 *  Copyright (c) 2012 Thomas Preud'homme
5
 *
6
 *
6
 *  Based on i386-gen.c by Fabrice Bellard
7
 *  Based on i386-gen.c by Fabrice Bellard
7
 *
8
 *
8
 * This library is free software; you can redistribute it and/or
9
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * modify it under the terms of the GNU Lesser General Public
Line 18... Line 19...
18
 * You should have received a copy of the GNU Lesser General Public
19
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22
 */
Line -... Line 23...
-
 
23
 
-
 
24
#ifdef TARGET_DEFS_ONLY
-
 
25
 
-
 
26
#if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP)
-
 
27
#error "Currently TinyCC only supports float computation with VFP instructions"
-
 
28
#endif
22
 
29
 
-
 
30
/* number of available registers */
-
 
31
#ifdef TCC_ARM_VFP
-
 
32
#define NB_REGS            13
23
/* number of available registers */
33
#else
-
 
34
#define NB_REGS             9
-
 
35
#endif
-
 
36
 
-
 
37
#ifndef TCC_ARM_VERSION
-
 
38
# define TCC_ARM_VERSION 5
Line 24... Line 39...
24
#define NB_REGS             9
39
#endif
25
 
40
 
26
/* a register can belong to several classes. The classes must be
41
/* a register can belong to several classes. The classes must be
27
   sorted from more general to more precise (see gv2() code which does
42
   sorted from more general to more precise (see gv2() code which does
Line 35... Line 50...
35
#define RC_R12     0x0040
50
#define RC_R12     0x0040
36
#define RC_F0      0x0080
51
#define RC_F0      0x0080
37
#define RC_F1      0x0100
52
#define RC_F1      0x0100
38
#define RC_F2      0x0200
53
#define RC_F2      0x0200
39
#define RC_F3      0x0400
54
#define RC_F3      0x0400
-
 
55
#ifdef TCC_ARM_VFP
-
 
56
#define RC_F4      0x0800
-
 
57
#define RC_F5      0x1000
-
 
58
#define RC_F6      0x2000
-
 
59
#define RC_F7      0x4000
-
 
60
#endif
40
#define RC_IRET    RC_R0  /* function return: integer register */
61
#define RC_IRET    RC_R0  /* function return: integer register */
41
#define RC_LRET    RC_R1  /* function return: second integer register */
62
#define RC_LRET    RC_R1  /* function return: second integer register */
42
#define RC_FRET    RC_F0  /* function return: float register */
63
#define RC_FRET    RC_F0  /* function return: float register */
Line 43... Line 64...
43
 
64
 
Line 50... Line 71...
50
    TREG_R12,
71
    TREG_R12,
51
    TREG_F0,
72
    TREG_F0,
52
    TREG_F1,
73
    TREG_F1,
53
    TREG_F2,
74
    TREG_F2,
54
    TREG_F3,
75
    TREG_F3,
-
 
76
#ifdef TCC_ARM_VFP
-
 
77
    TREG_F4,
-
 
78
    TREG_F5,
-
 
79
    TREG_F6,
-
 
80
    TREG_F7,
-
 
81
#endif
55
};
82
};
Line 56... Line -...
56
 
-
 
57
int reg_classes[NB_REGS] = {
-
 
58
    /* r0 */ RC_INT | RC_R0,
-
 
59
    /* r1 */ RC_INT | RC_R1,
-
 
60
    /* r2 */ RC_INT | RC_R2,
-
 
61
    /* r3 */ RC_INT | RC_R3,
-
 
62
    /* r12 */ RC_INT | RC_R12,
83
 
63
    /* f0 */ RC_FLOAT | RC_F0,
-
 
64
    /* f1 */ RC_FLOAT | RC_F1,
-
 
65
    /* f2 */ RC_FLOAT | RC_F2,
84
#ifdef TCC_ARM_VFP
66
    /* f3 */ RC_FLOAT | RC_F3,
85
#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
67
};
-
 
68
 
-
 
69
static int two2mask(int a,int b) {
-
 
70
  return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
-
 
71
}
-
 
72
 
-
 
73
static int regmask(int r) {
-
 
74
  return reg_classes[r]&~(RC_INT|RC_FLOAT);
-
 
Line 75... Line 86...
75
}
86
#endif
76
 
87
 
77
/* return registers for function */
88
/* return registers for function */
78
#define REG_IRET TREG_R0 /* single word int return register */
89
#define REG_IRET TREG_R0 /* single word int return register */
Line -... Line 90...
-
 
90
#define REG_LRET TREG_R1 /* second word return register (for long long) */
-
 
91
#define REG_FRET TREG_F0 /* float return register */
-
 
92
 
-
 
93
#ifdef TCC_ARM_EABI
-
 
94
#define TOK___divdi3 TOK___aeabi_ldivmod
-
 
95
#define TOK___moddi3 TOK___aeabi_ldivmod
-
 
96
#define TOK___udivdi3 TOK___aeabi_uldivmod
79
#define REG_LRET TREG_R1 /* second word return register (for long long) */
97
#define TOK___umoddi3 TOK___aeabi_uldivmod
80
#define REG_FRET TREG_F0 /* float return register */
98
#endif
Line 81... Line 99...
81
 
99
 
82
/* defined if function parameters must be evaluated in reverse order */
100
/* defined if function parameters must be evaluated in reverse order */
83
#define INVERT_FUNC_PARAMS
101
#define INVERT_FUNC_PARAMS
Line 84... Line 102...
84
 
102
 
85
/* defined if structures are passed as pointers. Otherwise structures
103
/* defined if structures are passed as pointers. Otherwise structures
Line 86... Line 104...
86
   are directly pushed on stack. */
104
   are directly pushed on stack. */
-
 
105
/* #define FUNC_STRUCT_PARAM_AS_PTR */
-
 
106
 
-
 
107
/* pointer size, in bytes */
-
 
108
#define PTR_SIZE 4
-
 
109
 
87
//#define FUNC_STRUCT_PARAM_AS_PTR
110
/* long double size and alignment, in bytes */
-
 
111
#ifdef TCC_ARM_VFP
-
 
112
#define LDOUBLE_SIZE  8
-
 
113
#endif
-
 
114
 
-
 
115
#ifndef LDOUBLE_SIZE
88
 
116
#define LDOUBLE_SIZE  8
-
 
117
#endif
-
 
118
 
89
/* pointer size, in bytes */
119
#ifdef TCC_ARM_EABI
90
#define PTR_SIZE 4
120
#define LDOUBLE_ALIGN 8
Line 91... Line 121...
91
 
121
#else
Line 102... Line 132...
102
 
132
 
Line 103... Line 133...
103
#define EM_TCC_TARGET EM_ARM
133
#define EM_TCC_TARGET EM_ARM
104
 
134
 
-
 
135
/* relocation type for 32 bit data relocation */
105
/* relocation type for 32 bit data relocation */
136
#define R_DATA_32   R_ARM_ABS32
106
#define R_DATA_32   R_ARM_ABS32
137
#define R_DATA_PTR  R_ARM_ABS32
Line 107... Line 138...
107
#define R_JMP_SLOT  R_ARM_JUMP_SLOT
138
#define R_JMP_SLOT  R_ARM_JUMP_SLOT
108
#define R_COPY      R_ARM_COPY
139
#define R_COPY      R_ARM_COPY
Line -... Line 140...
-
 
140
 
-
 
141
#define ELF_START_ADDR 0x00008000
-
 
142
#define ELF_PAGE_SIZE  0x1000
-
 
143
 
-
 
144
enum float_abi {
-
 
145
    ARM_SOFTFP_FLOAT,
-
 
146
    ARM_HARD_FLOAT,
109
 
147
};
-
 
148
 
-
 
149
/******************************************************/
110
#define ELF_START_ADDR 0x00008000
150
#else /* ! TARGET_DEFS_ONLY */
Line -... Line 151...
-
 
151
/******************************************************/
-
 
152
#include "tcc.h"
-
 
153
 
-
 
154
enum float_abi float_abi;
-
 
155
 
-
 
156
ST_DATA const int reg_classes[NB_REGS] = {
-
 
157
    /* r0 */ RC_INT | RC_R0,
-
 
158
    /* r1 */ RC_INT | RC_R1,
-
 
159
    /* r2 */ RC_INT | RC_R2,
-
 
160
    /* r3 */ RC_INT | RC_R3,
-
 
161
    /* r12 */ RC_INT | RC_R12,
-
 
162
    /* f0 */ RC_FLOAT | RC_F0,
-
 
163
    /* f1 */ RC_FLOAT | RC_F1,
-
 
164
    /* f2 */ RC_FLOAT | RC_F2,
-
 
165
    /* f3 */ RC_FLOAT | RC_F3,
-
 
166
#ifdef TCC_ARM_VFP
-
 
167
 /* d4/s8 */ RC_FLOAT | RC_F4,
-
 
168
/* d5/s10 */ RC_FLOAT | RC_F5,
-
 
169
/* d6/s12 */ RC_FLOAT | RC_F6,
-
 
170
/* d7/s14 */ RC_FLOAT | RC_F7,
-
 
171
#endif
-
 
172
};
-
 
173
 
-
 
174
static int func_sub_sp_offset, last_itod_magic;
-
 
175
static int leaffunc;
-
 
176
 
-
 
177
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-
 
178
static CType float_type, double_type, func_float_type, func_double_type;
-
 
179
ST_FUNC void arm_init(struct TCCState *s)
-
 
180
{
-
 
181
    float_type.t = VT_FLOAT;
-
 
182
    double_type.t = VT_DOUBLE;
-
 
183
    func_float_type.t = VT_FUNC;
-
 
184
    func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
-
 
185
    func_double_type.t = VT_FUNC;
-
 
186
    func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
-
 
187
 
-
 
188
    float_abi = s->float_abi;
-
 
189
#ifndef TCC_ARM_HARDFLOAT
-
 
190
    tcc_warning("soft float ABI currently not supported: default to softfp");
-
 
191
#endif
-
 
192
}
-
 
193
#else
-
 
194
#define func_float_type func_old_type
-
 
195
#define func_double_type func_old_type
-
 
196
#define func_ldouble_type func_old_type
-
 
197
ST_FUNC void arm_init(struct TCCState *s)
-
 
198
{
-
 
199
#if !defined (TCC_ARM_VFP)
-
 
200
    tcc_warning("Support for FPA is deprecated and will be removed in next"
-
 
201
                " release");
-
 
202
#endif
-
 
203
#if !defined (TCC_ARM_EABI)
-
 
204
    tcc_warning("Support for OABI is deprecated and will be removed in next"
-
 
205
                " release");
-
 
206
#endif
-
 
207
}
-
 
208
#endif
-
 
209
 
-
 
210
static int two2mask(int a,int b) {
-
 
211
  return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
-
 
212
}
-
 
213
 
-
 
214
static int regmask(int r) {
-
 
215
  return reg_classes[r]&~(RC_INT|RC_FLOAT);
-
 
216
}
-
 
217
 
-
 
218
/******************************************************/
-
 
219
 
-
 
220
#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
-
 
221
char *default_elfinterp(struct TCCState *s)
-
 
222
{
-
 
223
    if (s->float_abi == ARM_HARD_FLOAT)
-
 
224
        return "/lib/ld-linux-armhf.so.3";
111
#define ELF_PAGE_SIZE  0x1000
225
    else
112
 
226
        return "/lib/ld-linux.so.3";
113
/******************************************************/
227
}
114
static unsigned long func_sub_sp_offset,last_itod_magic;
228
#endif
Line 115... Line 229...
115
 
229
 
116
void o(unsigned long i)
230
void o(uint32_t i)
117
{
231
{
118
  /* this is a good place to start adding big-endian support*/
232
  /* this is a good place to start adding big-endian support*/
119
  int ind1;
233
  int ind1;
120
 
234
 
121
  ind1 = ind + 4;
235
  ind1 = ind + 4;
122
  if (!cur_text_section)
236
  if (!cur_text_section)
Line 131... Line 245...
131
  cur_text_section->data[ind++] = i&255;
245
  cur_text_section->data[ind++] = i&255;
132
  i>>=8;
246
  i>>=8;
133
  cur_text_section->data[ind++] = i;
247
  cur_text_section->data[ind++] = i;
134
}
248
}
Line 135... Line 249...
135
 
249
 
136
static unsigned long stuff_const(unsigned long op,unsigned long c)
250
static uint32_t stuff_const(uint32_t op, uint32_t c)
137
{
251
{
138
  int try_neg=0;
252
  int try_neg=0;
Line 139... Line 253...
139
  unsigned long nc = 0,negop = 0;
253
  uint32_t nc = 0, negop = 0;
140
 
254
 
141
  switch(op&0x1F00000)
255
  switch(op&0x1F00000)
142
  {
256
  {
Line 168... Line 282...
168
      if(c==~0)
282
      if(c==~0)
169
	return (op&0xFFF0FFFF)|0x1E00000;
283
	return (op&0xFFF0FFFF)|0x1E00000;
170
      break;
284
      break;
171
  }
285
  }
172
  do {
286
  do {
173
    unsigned long m;
287
    uint32_t m;
174
    int i;
288
    int i;
175
    if(c<256) /* catch undefined <<32 */
289
    if(c<256) /* catch undefined <<32 */
176
      return op|c;
290
      return op|c;
177
    for(i=2;i<32;i+=2) {
291
    for(i=2;i<32;i+=2) {
178
      m=(0xff>>i)|(0xff<<(32-i));
292
      m=(0xff>>i)|(0xff<<(32-i));
Line 185... Line 299...
185
  return 0;
299
  return 0;
186
}
300
}
Line 187... Line 301...
187
 
301
 
188
 
302
 
189
//only add,sub
303
//only add,sub
190
void stuff_const_harder(unsigned long op,unsigned long v) {
304
void stuff_const_harder(uint32_t op, uint32_t v) {
191
  unsigned long x;
305
  uint32_t x;
192
  x=stuff_const(op,v);
306
  x=stuff_const(op,v);
193
  if(x)
307
  if(x)
194
    o(x);
308
    o(x);
195
  else {
309
  else {
196
    unsigned long a[16],nv,no,o2,n2;
310
    uint32_t a[16], nv, no, o2, n2;
197
    int i,j,k;
311
    int i,j,k;
198
    a[0]=0xff;
312
    a[0]=0xff;
199
    o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
313
    o2=(op&0xfff0ffff)|((op&0xf000)<<4);;
200
    for(i=1;i<16;i++)
314
    for(i=1;i<16;i++)
201
      a[i]=(a[i-1]>>2)|(a[i-1]<<30);
315
      a[i]=(a[i-1]>>2)|(a[i-1]<<30);
202
    for(i=0;i<12;i++)
316
    for(i=0;i<12;i++)
203
      for(j=i+4;i<13+i;i++)
317
      for(j=i<4?i+12:15;j>=i+4;j--)
204
	if((v&(a[i]|a[j]))==v) {
318
	if((v&(a[i]|a[j]))==v) {
205
	  o(stuff_const(op,v&a[i]));
319
	  o(stuff_const(op,v&a[i]));
206
	  o(stuff_const(o2,v&a[j]));
320
	  o(stuff_const(o2,v&a[j]));
207
	  return;
321
	  return;
208
	}
322
	}
209
    no=op^0xC00000;
323
    no=op^0xC00000;
210
    n2=o2^0xC00000;
324
    n2=o2^0xC00000;
211
    nv=-v;
325
    nv=-v;
212
    for(i=0;i<12;i++)
326
    for(i=0;i<12;i++)
213
      for(j=i+4;i<13+i;i++)
327
      for(j=i<4?i+12:15;j>=i+4;j--)
214
	if((nv&(a[i]|a[j]))==nv) {
328
	if((nv&(a[i]|a[j]))==nv) {
215
	  o(stuff_const(no,nv&a[i]));
329
	  o(stuff_const(no,nv&a[i]));
216
	  o(stuff_const(n2,nv&a[j]));
330
	  o(stuff_const(n2,nv&a[j]));
217
	  return;
331
	  return;
218
	}
332
	}
219
    for(i=0;i<8;i++)
333
    for(i=0;i<8;i++)
220
      for(j=i+4;i<12;i++)
334
      for(j=i+4;j<12;j++)
221
	for(k=j+4;k<13+i;i++)
335
	for(k=i<4?i+12:15;k>=j+4;k--)
222
	  if((v&(a[i]|a[j]|a[k]))==v) {
336
	  if((v&(a[i]|a[j]|a[k]))==v) {
223
	    o(stuff_const(op,v&a[i]));
337
	    o(stuff_const(op,v&a[i]));
224
	    o(stuff_const(o2,v&a[j]));
338
	    o(stuff_const(o2,v&a[j]));
225
	    o(stuff_const(o2,v&a[k]));
339
	    o(stuff_const(o2,v&a[k]));
226
	    return;
340
	    return;
227
	  }
341
	  }
228
    no=op^0xC00000;
342
    no=op^0xC00000;
229
    nv=-v;
343
    nv=-v;
230
    for(i=0;i<8;i++)
344
    for(i=0;i<8;i++)
231
      for(j=i+4;i<12;i++)
345
      for(j=i+4;j<12;j++)
232
	for(k=j+4;k<13+i;i++)
346
	for(k=i<4?i+12:15;k>=j+4;k--)
233
	  if((nv&(a[i]|a[j]|a[k]))==nv) {
347
	  if((nv&(a[i]|a[j]|a[k]))==nv) {
234
	    o(stuff_const(no,nv&a[i]));
348
	    o(stuff_const(no,nv&a[i]));
235
	    o(stuff_const(n2,nv&a[j]));
349
	    o(stuff_const(n2,nv&a[j]));
Line 241... Line 355...
241
    o(stuff_const(o2,v&a[8]));
355
    o(stuff_const(o2,v&a[8]));
242
    o(stuff_const(o2,v&a[12]));
356
    o(stuff_const(o2,v&a[12]));
243
  }
357
  }
244
}
358
}
Line 245... Line 359...
245
 
359
 
246
unsigned long encbranch(int pos,int addr,int fail)
360
ST_FUNC uint32_t encbranch(int pos, int addr, int fail)
247
{
361
{
248
  addr-=pos+8;
362
  addr-=pos+8;
249
  addr/=4;
363
  addr/=4;
250
  if(addr>=0x1000000 || addr<-0x1000000) {
364
  if(addr>=0x1000000 || addr<-0x1000000) {
251
    if(fail)
365
    if(fail)
252
      error("FIXME: function bigger than 32MB");
366
      tcc_error("FIXME: function bigger than 32MB");
253
    return 0;
367
    return 0;
254
  }
368
  }
255
  return 0x0A000000|(addr&0xffffff);
369
  return 0x0A000000|(addr&0xffffff);
Line 256... Line 370...
256
}
370
}
257
 
371
 
258
int decbranch(int pos)
372
int decbranch(int pos)
259
{
373
{
260
  int x;
374
  int x;
261
  x=*(int *)(cur_text_section->data + pos);
375
  x=*(uint32_t *)(cur_text_section->data + pos);
262
  x&=0x00ffffff;
376
  x&=0x00ffffff;
263
  if(x&0x800000)
377
  if(x&0x800000)
264
    x-=0x1000000;
378
    x-=0x1000000;
Line 265... Line 379...
265
  return x*4+pos+8;
379
  return x*4+pos+8;
266
}
380
}
267
 
381
 
268
/* output a symbol and patch all calls to it */
382
/* output a symbol and patch all calls to it */
269
void gsym_addr(int t, int a)
383
void gsym_addr(int t, int a)
270
{
384
{
271
  unsigned long *x;
385
  uint32_t *x;
272
  int lt;
386
  int lt;
273
  while(t) {
387
  while(t) {
274
    x=(unsigned long *)(cur_text_section->data + t);
388
    x=(uint32_t *)(cur_text_section->data + t);
275
    t=decbranch(lt=t);
389
    t=decbranch(lt=t);
276
    if(a==lt+4)
390
    if(a==lt+4)
Line 285... Line 399...
285
void gsym(int t)
399
void gsym(int t)
286
{
400
{
287
  gsym_addr(t, ind);
401
  gsym_addr(t, ind);
288
}
402
}
Line -... Line 403...
-
 
403
 
-
 
404
#ifdef TCC_ARM_VFP
-
 
405
static uint32_t vfpr(int r)
-
 
406
{
-
 
407
  if(rTREG_F7)
-
 
408
    tcc_error("compiler error! register %i is no vfp register",r);
-
 
409
  return r-5;
-
 
410
}
289
 
411
#else
290
static unsigned long fpr(int r)
412
static uint32_t fpr(int r)
291
{
413
{
292
  if(rTREG_F3)
414
  if(rTREG_F3)
293
    error("compiler error! register %i is no fp register\n",r);
415
    tcc_error("compiler error! register %i is no fpa register",r);
294
  return r-5;
416
  return r-5;
-
 
417
}
Line 295... Line 418...
295
}
418
#endif
296
 
419
 
297
static unsigned long intr(int r)
420
static uint32_t intr(int r)
298
{
421
{
299
  if(r==4)
422
  if(r==4)
300
    return 12;
423
    return 12;
301
  if((r<0 || r>4) && r!=14)
424
  if((r<0 || r>4) && r!=14)
302
    error("compiler error! register %i is no int register\n",r);
425
    tcc_error("compiler error! register %i is no int register",r);
Line 303... Line 426...
303
  return r;
426
  return r;
304
}
427
}
305
 
428
 
306
static void calcaddr(unsigned long *base,int *off,int *sgn,int maxoff,unsigned shift)
429
static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift)
307
{
430
{
308
  if(*off>maxoff || *off&((1<
431
  if(*off>maxoff || *off&((1<
309
    unsigned long x,y;
432
    uint32_t x, y;
310
    x=0xE280E000;
433
    x=0xE280E000;
311
    if(*sgn)
434
    if(*sgn)
Line 328... Line 451...
328
    stuff_const_harder(x,*off&~maxoff);
451
    stuff_const_harder(x,*off&~maxoff);
329
    *off&=maxoff;
452
    *off&=maxoff;
330
  }
453
  }
331
}
454
}
Line 332... Line 455...
332
 
455
 
333
static unsigned long mapcc(int cc)
456
static uint32_t mapcc(int cc)
334
{
457
{
335
  switch(cc)
458
  switch(cc)
336
  {
459
  {
337
    case TOK_ULT:
460
    case TOK_ULT:
338
      return 0x30000000;
461
      return 0x30000000; /* CC/LO */
339
    case TOK_UGE:
462
    case TOK_UGE:
340
      return 0x20000000;
463
      return 0x20000000; /* CS/HS */
341
    case TOK_EQ:
464
    case TOK_EQ:
342
      return 0x00000000;
465
      return 0x00000000; /* EQ */
343
    case TOK_NE:
466
    case TOK_NE:
344
      return 0x10000000;
467
      return 0x10000000; /* NE */
345
    case TOK_ULE:
468
    case TOK_ULE:
346
      return 0x90000000;
469
      return 0x90000000; /* LS */
347
    case TOK_UGT:
470
    case TOK_UGT:
-
 
471
      return 0x80000000; /* HI */
-
 
472
    case TOK_Nset:
-
 
473
      return 0x40000000; /* MI */
-
 
474
    case TOK_Nclear:
348
      return 0x80000000;
475
      return 0x50000000; /* PL */
349
    case TOK_LT:
476
    case TOK_LT:
350
      return 0xB0000000;
477
      return 0xB0000000; /* LT */
351
    case TOK_GE:
478
    case TOK_GE:
352
      return 0xA0000000;
479
      return 0xA0000000; /* GE */
353
    case TOK_LE:
480
    case TOK_LE:
354
      return 0xD0000000;
481
      return 0xD0000000; /* LE */
355
    case TOK_GT:
482
    case TOK_GT:
356
      return 0xC0000000;
483
      return 0xC0000000; /* GT */
357
  }
484
  }
358
  error("unexpected condition code");
485
  tcc_error("unexpected condition code");
359
  return 0xE0000000;
486
  return 0xE0000000; /* AL */
Line 360... Line 487...
360
}
487
}
361
 
488
 
362
static int negcc(int cc)
489
static int negcc(int cc)
Line 373... Line 500...
373
      return TOK_EQ;
500
      return TOK_EQ;
374
    case TOK_ULE:
501
    case TOK_ULE:
375
      return TOK_UGT;
502
      return TOK_UGT;
376
    case TOK_UGT:
503
    case TOK_UGT:
377
      return TOK_ULE;
504
      return TOK_ULE;
-
 
505
    case TOK_Nset:
-
 
506
      return TOK_Nclear;
-
 
507
    case TOK_Nclear:
-
 
508
      return TOK_Nset;
378
    case TOK_LT:
509
    case TOK_LT:
379
      return TOK_GE;
510
      return TOK_GE;
380
    case TOK_GE:
511
    case TOK_GE:
381
      return TOK_LT;
512
      return TOK_LT;
382
    case TOK_LE:
513
    case TOK_LE:
383
      return TOK_GT;
514
      return TOK_GT;
384
    case TOK_GT:
515
    case TOK_GT:
385
      return TOK_LE;
516
      return TOK_LE;
386
  }
517
  }
387
  error("unexpected condition code");
518
  tcc_error("unexpected condition code");
388
  return TOK_NE;
519
  return TOK_NE;
389
}
520
}
Line 390... Line 521...
390
 
521
 
391
/* load 'r' from value 'sv' */
522
/* load 'r' from value 'sv' */
392
void load(int r, SValue *sv)
523
void load(int r, SValue *sv)
393
{
524
{
394
  int v, ft, fc, fr, sign;
525
  int v, ft, fc, fr, sign;
395
  unsigned long op;
526
  uint32_t op;
Line 396... Line 527...
396
  SValue v1;
527
  SValue v1;
397
 
528
 
398
  fr = sv->r;
529
  fr = sv->r;
Line 399... Line 530...
399
  ft = sv->type.t;
530
  ft = sv->type.t;
400
  fc = sv->c.ul;
531
  fc = sv->c.i;
401
 
532
 
402
  if(fc>=0)
533
  if(fc>=0)
403
    sign=0;
534
    sign=0;
404
  else {
535
  else {
Line 405... Line 536...
405
    sign=1;
536
    sign=1;
406
    fc=-fc;
537
    fc=-fc;
407
  }
538
  }
408
  
539
 
409
  v = fr & VT_VALMASK;
540
  v = fr & VT_VALMASK;
410
  if (fr & VT_LVAL) {
541
  if (fr & VT_LVAL) {
411
    unsigned long base=0xB; // fp
542
    uint32_t base = 0xB; // fp
412
    if(v == VT_LLOCAL) {
543
    if(v == VT_LLOCAL) {
413
      v1.type.t = VT_PTR;
544
      v1.type.t = VT_PTR;
414
      v1.r = VT_LOCAL | VT_LVAL;
545
      v1.r = VT_LOCAL | VT_LVAL;
415
      v1.c.ul = sv->c.ul;
546
      v1.c.i = sv->c.i;
416
      load(base=14 /* lr */, &v1);
547
      load(base=14 /* lr */, &v1);
417
      fc=sign=0;
548
      fc=sign=0;
418
      v=VT_LOCAL;
549
      v=VT_LOCAL;
419
    } else if(v == VT_CONST) {
550
    } else if(v == VT_CONST) {
420
      v1.type.t = VT_PTR;
551
      v1.type.t = VT_PTR;
421
      v1.r = fr&~VT_LVAL;
552
      v1.r = fr&~VT_LVAL;
422
      v1.c.ul = sv->c.ul;
553
      v1.c.i = sv->c.i;
423
      v1.sym=sv->sym;
554
      v1.sym=sv->sym;
Line 430... Line 561...
430
      v=VT_LOCAL;
561
      v=VT_LOCAL;
431
    }
562
    }
432
    if(v == VT_LOCAL) {
563
    if(v == VT_LOCAL) {
433
      if(is_float(ft)) {
564
      if(is_float(ft)) {
434
	calcaddr(&base,&fc,&sign,1020,2);
565
	calcaddr(&base,&fc,&sign,1020,2);
-
 
566
#ifdef TCC_ARM_VFP
-
 
567
        op=0xED100A00; /* flds */
-
 
568
        if(!sign)
-
 
569
          op|=0x800000;
-
 
570
        if ((ft & VT_BTYPE) != VT_FLOAT)
-
 
571
          op|=0x100;   /* flds -> fldd */
-
 
572
        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
-
 
573
#else
435
	op=0xED100100;
574
	op=0xED100100;
436
	if(!sign)
575
	if(!sign)
437
	  op|=0x800000;
576
	  op|=0x800000;
438
#if LDOUBLE_SIZE == 8
577
#if LDOUBLE_SIZE == 8
439
	if ((ft & VT_BTYPE) != VT_FLOAT)
578
	if ((ft & VT_BTYPE) != VT_FLOAT)
Line 443... Line 582...
443
	  op|=0x8000;
582
	  op|=0x8000;
444
	else if ((ft & VT_BTYPE) == VT_LDOUBLE)
583
	else if ((ft & VT_BTYPE) == VT_LDOUBLE)
445
	  op|=0x400000;
584
	  op|=0x400000;
446
#endif
585
#endif
447
	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
586
	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
-
 
587
#endif
-
 
588
      } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
448
      } else if((ft & VT_TYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_SHORT) {
589
                || (ft & VT_BTYPE) == VT_SHORT) {
449
	calcaddr(&base,&fc,&sign,255,0);
590
	calcaddr(&base,&fc,&sign,255,0);
450
	op=0xE1500090;
591
	op=0xE1500090;
451
	if ((ft & VT_BTYPE) == VT_SHORT)
592
	if ((ft & VT_BTYPE) == VT_SHORT)
452
	  op|=0x20;
593
	  op|=0x20;
453
	if ((ft & VT_UNSIGNED) == 0)
594
	if ((ft & VT_UNSIGNED) == 0)
Line 458... Line 599...
458
      } else {
599
      } else {
459
	calcaddr(&base,&fc,&sign,4095,0);
600
	calcaddr(&base,&fc,&sign,4095,0);
460
	op=0xE5100000;
601
	op=0xE5100000;
461
	if(!sign)
602
	if(!sign)
462
	  op|=0x800000;
603
	  op|=0x800000;
463
        if ((ft & VT_BTYPE) == VT_BYTE)
604
        if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
464
          op|=0x400000;
605
          op|=0x400000;
465
        o(op|(intr(r)<<12)|fc|(base<<16));
606
        o(op|(intr(r)<<12)|fc|(base<<16));
466
      }
607
      }
467
      return;
608
      return;
468
    }
609
    }
469
  } else {
610
  } else {
470
    if (v == VT_CONST) {
611
    if (v == VT_CONST) {
471
      op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);
612
      op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i);
472
      if (fr & VT_SYM || !op) {
613
      if (fr & VT_SYM || !op) {
473
        o(0xE59F0000|(intr(r)<<12));
614
        o(0xE59F0000|(intr(r)<<12));
474
        o(0xEA000000);
615
        o(0xEA000000);
475
        if(fr & VT_SYM)
616
        if(fr & VT_SYM)
476
	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
617
	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
477
        o(sv->c.ul);
618
        o(sv->c.i);
478
      } else
619
      } else
479
        o(op);
620
        o(op);
480
      return;
621
      return;
481
    } else if (v == VT_LOCAL) {
622
    } else if (v == VT_LOCAL) {
482
      op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);
623
      op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i);
483
      if (fr & VT_SYM || !op) {
624
      if (fr & VT_SYM || !op) {
484
	o(0xE59F0000|(intr(r)<<12));
625
	o(0xE59F0000|(intr(r)<<12));
485
	o(0xEA000000);
626
	o(0xEA000000);
486
	if(fr & VT_SYM) // needed ?
627
	if(fr & VT_SYM) // needed ?
487
	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
628
	  greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
488
	o(sv->c.ul);
629
	o(sv->c.i);
489
	o(0xE08B0000|(intr(r)<<12)|intr(r));
630
	o(0xE08B0000|(intr(r)<<12)|intr(r));
490
      } else
631
      } else
491
	o(op);
632
	o(op);
492
      return;
633
      return;
493
    } else if(v == VT_CMP) {
634
    } else if(v == VT_CMP) {
494
      o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));
635
      o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12));
495
      o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));
636
      o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12));
496
      return;
637
      return;
497
    } else if (v == VT_JMP || v == VT_JMPI) {
638
    } else if (v == VT_JMP || v == VT_JMPI) {
498
      int t;
639
      int t;
499
      t = v & 1;
640
      t = v & 1;
500
      o(0xE3A00000|(intr(r)<<12)|t);
641
      o(0xE3A00000|(intr(r)<<12)|t);
501
      o(0xEA000000);
642
      o(0xEA000000);
502
      gsym(sv->c.ul);
643
      gsym(sv->c.i);
503
      o(0xE3A00000|(intr(r)<<12)|(t^1));
644
      o(0xE3A00000|(intr(r)<<12)|(t^1));
504
      return;
645
      return;
505
    } else if (v < VT_CONST) {
646
    } else if (v < VT_CONST) {
506
      if(is_float(ft))
647
      if(is_float(ft))
-
 
648
#ifdef TCC_ARM_VFP
-
 
649
        o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
-
 
650
#else
507
	o(0xEE008180|(fpr(r)<<12)|fpr(v));
651
	o(0xEE008180|(fpr(r)<<12)|fpr(v));
-
 
652
#endif
508
      else
653
      else
509
	o(0xE1A00000|(intr(r)<<12)|intr(v));
654
	o(0xE1A00000|(intr(r)<<12)|intr(v));
510
      return;
655
      return;
511
    }
656
    }
512
  }
657
  }
513
  error("load unimplemented!");
658
  tcc_error("load unimplemented!");
514
}
659
}
Line 515... Line 660...
515
 
660
 
516
/* store register 'r' in lvalue 'v' */
661
/* store register 'r' in lvalue 'v' */
517
void store(int r, SValue *sv)
662
void store(int r, SValue *sv)
518
{
663
{
519
  SValue v1;
664
  SValue v1;
520
  int v, ft, fc, fr, sign;
665
  int v, ft, fc, fr, sign;
Line 521... Line 666...
521
  unsigned long op;
666
  uint32_t op;
522
 
667
 
523
  fr = sv->r;
668
  fr = sv->r;
Line 524... Line 669...
524
  ft = sv->type.t;
669
  ft = sv->type.t;
525
  fc = sv->c.ul;
670
  fc = sv->c.i;
526
 
671
 
527
  if(fc>=0)
672
  if(fc>=0)
528
    sign=0;
673
    sign=0;
529
  else {
674
  else {
Line 530... Line 675...
530
    sign=1;
675
    sign=1;
531
    fc=-fc;
676
    fc=-fc;
532
  }
677
  }
533
  
678
 
534
  v = fr & VT_VALMASK; 
679
  v = fr & VT_VALMASK;
535
  if (fr & VT_LVAL || fr == VT_LOCAL) {
680
  if (fr & VT_LVAL || fr == VT_LOCAL) {
536
    unsigned long base=0xb;
681
    uint32_t base = 0xb;
537
    if(v < VT_CONST) {
682
    if(v < VT_CONST) {
538
      base=intr(v);
683
      base=intr(v);
539
      v=VT_LOCAL;
684
      v=VT_LOCAL;
540
      fc=sign=0;
685
      fc=sign=0;
541
    } else if(v == VT_CONST) {
686
    } else if(v == VT_CONST) {
542
      v1.type.t = ft;
687
      v1.type.t = ft;
543
      v1.r = fr&~VT_LVAL;
688
      v1.r = fr&~VT_LVAL;
544
      v1.c.ul = sv->c.ul;
689
      v1.c.i = sv->c.i;
545
      v1.sym=sv->sym;
690
      v1.sym=sv->sym;
546
      load(base=14, &v1);
691
      load(base=14, &v1);
547
      fc=sign=0;
692
      fc=sign=0;
548
      v=VT_LOCAL;   
693
      v=VT_LOCAL;
-
 
694
    }
-
 
695
    if(v == VT_LOCAL) {
-
 
696
       if(is_float(ft)) {
-
 
697
	calcaddr(&base,&fc,&sign,1020,2);
-
 
698
#ifdef TCC_ARM_VFP
-
 
699
        op=0xED000A00; /* fsts */
-
 
700
        if(!sign)
-
 
701
          op|=0x800000;
549
    }
702
        if ((ft & VT_BTYPE) != VT_FLOAT)
550
    if(v == VT_LOCAL) {
703
          op|=0x100;   /* fsts -> fstd */
551
       if(is_float(ft)) {
704
        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
552
	calcaddr(&base,&fc,&sign,1020,2);
705
#else
553
	op=0xED000100;
706
	op=0xED000100;
Line 561... Line 714...
561
	  op|=0x8000;
714
	  op|=0x8000;
562
	if ((ft & VT_BTYPE) == VT_LDOUBLE)
715
	if ((ft & VT_BTYPE) == VT_LDOUBLE)
563
	  op|=0x400000;
716
	  op|=0x400000;
564
#endif
717
#endif
565
	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
718
	o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
-
 
719
#endif
566
	return;
720
	return;
567
      } else if((ft & VT_BTYPE) == VT_SHORT) {
721
      } else if((ft & VT_BTYPE) == VT_SHORT) {
568
	calcaddr(&base,&fc,&sign,255,0);
722
	calcaddr(&base,&fc,&sign,255,0);
569
	op=0xE14000B0;
723
	op=0xE14000B0;
570
	if(!sign)
724
	if(!sign)
Line 573... Line 727...
573
      } else {
727
      } else {
574
	calcaddr(&base,&fc,&sign,4095,0);
728
	calcaddr(&base,&fc,&sign,4095,0);
575
	op=0xE5000000;
729
	op=0xE5000000;
576
	if(!sign)
730
	if(!sign)
577
	  op|=0x800000;
731
	  op|=0x800000;
578
        if ((ft & VT_BTYPE) == VT_BYTE)
732
        if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
579
          op|=0x400000;
733
          op|=0x400000;
580
        o(op|(intr(r)<<12)|fc|(base<<16));
734
        o(op|(intr(r)<<12)|fc|(base<<16));
581
      }
735
      }
582
      return;
736
      return;
583
    }
737
    }
584
  }
738
  }
585
  error("store unimplemented");
739
  tcc_error("store unimplemented");
586
}
740
}
Line 587... Line 741...
587
 
741
 
588
static void gadd_sp(int val)
742
static void gadd_sp(int val)
589
{
743
{
Line 593... Line 747...
593
/* 'is_jmp' is '1' if it is a jump */
747
/* 'is_jmp' is '1' if it is a jump */
594
static void gcall_or_jmp(int is_jmp)
748
static void gcall_or_jmp(int is_jmp)
595
{
749
{
596
  int r;
750
  int r;
597
  if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
751
  if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
598
    unsigned long x;
752
    uint32_t x;
599
    /* constant case */
753
    /* constant case */
600
    x=encbranch(ind,ind+vtop->c.ul,0);
754
    x=encbranch(ind,ind+vtop->c.i,0);
601
    if(x) {
755
    if(x) {
602
      if (vtop->r & VT_SYM) {
756
      if (vtop->r & VT_SYM) {
603
	/* relocation case */
757
	/* relocation case */
604
	greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
758
	greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
605
      } else
759
      } else
Line 609... Line 763...
609
      if(!is_jmp)
763
      if(!is_jmp)
610
	o(0xE28FE004); // add lr,pc,#4
764
	o(0xE28FE004); // add lr,pc,#4
611
      o(0xE51FF004);   // ldr pc,[pc,#-4]
765
      o(0xE51FF004);   // ldr pc,[pc,#-4]
612
      if (vtop->r & VT_SYM)
766
      if (vtop->r & VT_SYM)
613
	greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
767
	greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
614
      o(vtop->c.ul);
768
      o(vtop->c.i);
615
    }
769
    }
616
  } else {
770
  } else {
617
    /* otherwise, indirect call */
771
    /* otherwise, indirect call */
618
    r = gv(RC_INT);
772
    r = gv(RC_INT);
619
    if(!is_jmp)
773
    if(!is_jmp)
620
      o(0xE1A0E00F);       // mov lr,pc
774
      o(0xE1A0E00F);       // mov lr,pc
621
    o(0xE1A0F000|intr(r)); // mov pc,r
775
    o(0xE1A0F000|intr(r)); // mov pc,r
622
  }
776
  }
623
}
777
}
Line -... Line 778...
-
 
778
 
624
 
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 */
-
 
784
static int is_hgen_float_aggr(CType *type)
-
 
785
{
-
 
786
  if ((type->t & VT_BTYPE) == VT_STRUCT) {
-
 
787
    struct Sym *ref;
-
 
788
    int btype, nb_fields = 0;
-
 
789
 
-
 
790
    ref = type->ref->next;
-
 
791
    btype = ref->type.t & VT_BTYPE;
-
 
792
    if (btype == VT_FLOAT || btype == VT_DOUBLE) {
-
 
793
      for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
-
 
794
      return !ref && nb_fields <= 4;
-
 
795
    }
-
 
796
  }
-
 
797
  return 0;
-
 
798
}
-
 
799
 
-
 
800
struct avail_regs {
-
 
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 */
-
 
805
};
-
 
806
 
-
 
807
#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
-
 
808
 
-
 
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
625
/* Generate function call. The function address is pushed first, then
811
   the ARM architecture (AAPCS). If found, the registers are assigned to this
626
   all the parameters in call order. This functions pops all the
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 contraints for the param, as returned by type_size()
-
 
817
   size: size of the parameter, as returned by type_size() */
-
 
818
int assign_vfpreg(struct avail_regs *avregs, int align, int size)
-
 
819
{
-
 
820
  int first_reg = 0;
-
 
821
 
-
 
822
  if (avregs->first_free_reg == -1)
-
 
823
    return -1;
-
 
824
  if (align >> 3) { /* double alignment */
-
 
825
    first_reg = avregs->first_free_reg;
-
 
826
    /* alignment contraint not respected so use next reg and record hole */
-
 
827
    if (first_reg & 1)
-
 
828
      avregs->avail[avregs->last_hole++] = first_reg++;
-
 
829
  } else { /* no special alignment (float or array of float) */
-
 
830
    /* if single float and a hole is available, assign the param to it */
-
 
831
    if (size == 4 && avregs->first_hole != avregs->last_hole)
-
 
832
      return avregs->avail[avregs->first_hole++];
-
 
833
    else
-
 
834
      first_reg = avregs->first_free_reg;
627
   parameters and the function address. */
835
  }
-
 
836
  if (first_reg + size / 4 <= 16) {
-
 
837
    avregs->first_free_reg = first_reg + size / 4;
-
 
838
    return first_reg;
-
 
839
  }
-
 
840
  avregs->first_free_reg = -1;
-
 
841
  return -1;
-
 
842
}
-
 
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. */
628
void gfunc_call(int nb_args)
846
int floats_in_core_regs(SValue *sval)
629
{
847
{
630
  int size, align, r, args_size, i;
848
  if (!sval->sym)
631
  Sym *func_sym;
-
 
632
  signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
-
 
Line -... Line 849...
-
 
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. */
-
 
872
ST_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;
633
  int todo=0xf, keep, plan2[4]={0,0,0,0};
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;
634
 
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. */
-
 
905
enum 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
 
-
 
914
struct 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
 
-
 
921
struct 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];                     \
635
  r = vtop->r & VT_VALMASK;
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). */
-
 
950
static 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;
636
  if (r == VT_CMP || (r & ~1) == VT_JMP)
956
  struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
-
 
957
 
-
 
958
  ncrn = nsaa = 0;
-
 
959
  *todo = 0;
637
    gv(RC_INT);
960
  plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
-
 
961
  memset(plan->clsplans, 0, sizeof(plan->clsplans));
-
 
962
  for(i = nb_args; i-- ;) {
638
  args_size = 0;
963
    int j, start_vfpreg = 0;
639
  for(i = nb_args ; i-- && args_size < 16 ;) {
964
    CType type = vtop[-i].type;
640
    if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) {
965
    type.t &= ~VT_ARRAY;
641
      size = type_size(&vtop[-i].type, &align);
966
    size = type_size(&type, &align);
642
      size = (size + 3) & ~3;
967
    size = (size + 3) & ~3;
-
 
968
    align = (align + 3) & ~3;
643
      args_size += size;
969
    switch(vtop[-i].type.t & VT_BTYPE) {
644
    } else if ((vtop[-i].type.t & VT_BTYPE) == VT_FLOAT)
970
      case VT_STRUCT:
645
      args_size += 4;
971
      case VT_FLOAT:
646
    else if ((vtop[-i].type.t & VT_BTYPE) == VT_DOUBLE)
972
      case VT_DOUBLE:
-
 
973
      case VT_LDOUBLE:
-
 
974
      if (float_abi == ARM_HARD_FLOAT) {
647
      args_size += 8;
975
        int is_hfa = 0; /* Homogeneous float aggregate */
-
 
976
 
648
    else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE)
977
        if (is_float(vtop[-i].type.t)
-
 
978
            || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {
-
 
979
          int end_vfpreg;
649
      args_size += LDOUBLE_SIZE;
980
 
-
 
981
          start_vfpreg = assign_vfpreg(&avregs, align, size);
-
 
982
          end_vfpreg = start_vfpreg + ((size - 1) >> 2);
650
    else {
983
          if (start_vfpreg >= 0) {
651
      plan[nb_args-1-i][0]=args_size/4;
984
            pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};
-
 
985
            if (is_hfa)
652
      args_size += 4;
986
              add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
-
 
987
            else
-
 
988
              add_param_plan(plan, pplan, VFP_CLASS);
653
      if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) {
989
            continue;
654
	plan[nb_args-1-i][1]=args_size/4;
990
          } else
655
	args_size += 4;
991
            break;
-
 
992
        }
-
 
993
      }
-
 
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. */
-
 
999
        for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
-
 
1000
          *todo|=(1<
-
 
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 {
656
      }
1007
        ncrn = 4;
-
 
1008
        break;
-
 
1009
      }
-
 
1010
      continue;
-
 
1011
      default:
-
 
1012
      if (ncrn < 4) {
-
 
1013
        int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
-
 
1014
 
657
    }
1015
        if (is_long) {
-
 
1016
          ncrn = (ncrn + 1) & -2;
-
 
1017
          if (ncrn == 4)
-
 
1018
            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 */
-
 
1046
static 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
 
-
 
1051
   /* Several constraints require parameters to be copied in a specific order:
-
 
1052
      - structures are copied to the stack before being loaded in a reg;
-
 
1053
      - floats loaded to an odd numbered VFP reg are first copied to the
-
 
1054
        preceding even numbered VFP reg and then moved to the next VFP reg.
-
 
1055
 
-
 
1056
      It is thus important that:
-
 
1057
      - structures assigned to core regs must be copied after parameters
-
 
1058
        assigned to the stack but before structures assigned to VFP regs because
-
 
1059
        a structure can lie partly in core registers and partly on the stack;
-
 
1060
      - parameters assigned to the stack and all structures be copied before
-
 
1061
        parameters assigned to a core reg since copying a parameter to the stack
-
 
1062
        require using a core reg;
-
 
1063
      - parameters assigned to VFP regs be copied before structures assigned to
658
  }
1064
        VFP regs as the copy might use an even numbered VFP reg that already
-
 
1065
        holds part of a structure. */
-
 
1066
  for(i = 0; i < NB_CLASSES; i++) {
-
 
1067
    for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
659
  args_size = keep = 0;
1068
      vpushv(pplan->sval);
-
 
1069
      pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
-
 
1070
      switch(i) {
-
 
1071
        case STACK_CLASS:
660
  for(i = 0;i < nb_args; i++) {
1072
        case CORE_STRUCT_CLASS:
-
 
1073
        case VFP_STRUCT_CLASS:
661
    vnrott(keep+1);
1074
          if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
662
    if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1075
            int padding = 0;
663
      size = type_size(&vtop->type, &align);
1076
            size = type_size(&pplan->sval->type, &align);
-
 
1077
            /* align to stack align size */
-
 
1078
            size = (size + 3) & ~3;
-
 
1079
            if (i == STACK_CLASS && pplan->prev)
664
      /* align to stack align size */
1080
              padding = pplan->start - pplan->prev->end;
665
      size = (size + 3) & ~3;
1081
            size += padding; /* Add padding if any */
666
      /* allocate the necessary size on stack */
1082
            /* allocate the necessary size on stack */
667
      gadd_sp(-size);
1083
            gadd_sp(-size);
668
      /* generate structure store */
1084
            /* generate structure store */
669
      r = get_reg(RC_INT);
1085
            r = get_reg(RC_INT);
670
      o(0xE1A0000D|(intr(r)<<12));
1086
            o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */
-
 
1087
            vset(&vtop->type, r | VT_LVAL, 0);
-
 
1088
            vswap();
-
 
1089
            vstore(); /* memcpy to current sp + potential padding */
-
 
1090
 
-
 
1091
            /* Homogeneous float aggregate are loaded to VFP registers
-
 
1092
               immediately since there is no way of loading data in multiple
-
 
1093
               non consecutive VFP registers as what is done for other
-
 
1094
               structures (see the use of todo). */
-
 
1095
            if (i == VFP_STRUCT_CLASS) {
-
 
1096
              int first = pplan->start, nb = pplan->end - first + 1;
-
 
1097
              /* vpop.32 {pplan->start, ..., pplan->end} */
-
 
1098
              o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);
671
      vset(&vtop->type, r | VT_LVAL, 0);
1099
              /* No need to write the register used to a SValue since VFP regs
672
      vswap();
1100
                 cannot be used for gcall_or_jmp */
-
 
1101
            }
-
 
1102
          } else {
-
 
1103
            if (is_float(pplan->sval->type.t)) {
-
 
1104
#ifdef TCC_ARM_VFP
-
 
1105
              r = vfpr(gv(RC_FLOAT)) << 12;
-
 
1106
              if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
673
      vstore();
1107
                size = 4;
-
 
1108
              else {
-
 
1109
                size = 8;
674
      vtop--;
1110
                r |= 0x101; /* vpush.32 -> vpush.64 */
-
 
1111
              }
675
      args_size += size;
1112
              o(0xED2D0A01 + r); /* vpush */
676
    } else if (is_float(vtop->type.t)) {
1113
#else
677
      r=fpr(gv(RC_FLOAT))<<12;
1114
              r = fpr(gv(RC_FLOAT)) << 12;
678
      if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
1115
              if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
679
        size = 4;
1116
                size = 4;
680
      else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1117
              else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
681
        size = 8;
1118
                size = 8;
Line 682... Line 1119...
682
      else
1119
              else
683
        size = LDOUBLE_SIZE;
1120
                size = LDOUBLE_SIZE;
684
      
1121
 
685
      if (size == 12)
1122
              if (size == 12)
Line 686... Line 1123...
686
	r|=0x400000;
1123
                r |= 0x400000;
687
      else if(size == 8)
1124
              else if(size == 8)
688
	r|=0x8000;
-
 
689
 
1125
                r|=0x8000;
690
      o(0xED2D0100|r|(size>>2));
-
 
691
      vtop--;
1126
 
692
      args_size += size;
1127
              o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */
693
    } else {
1128
#endif
694
      int s;
1129
            } else {
695
      /* simple type (currently always same size) */
1130
              /* simple type (currently always same size) */
696
      /* XXX: implicit cast ? */
-
 
697
      size=4;
-
 
698
      if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1131
              /* XXX: implicit cast ? */
699
	lexpand_nr();
-
 
700
	s=RC_INT;
-
 
701
	if(nb_args-i<5 && plan[nb_args-i-1][1]!=-1) {
-
 
702
	  s=regmask(plan[nb_args-i-1][1]);
1132
              size=4;
703
	  todo&=~(1<
1133
              if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
704
	}
1134
                lexpand_nr();
705
	if(s==RC_INT) {
-
 
706
	  r = gv(s);
-
 
707
	  o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
-
 
708
	  vtop--;
-
 
709
	} else {
1135
                size = 8;
-
 
1136
                r = gv(RC_INT);
-
 
1137
                o(0xE52D0004|(intr(r)<<12)); /* push r */
710
	  plan2[keep]=s;
1138
                vtop--;
-
 
1139
              }
-
 
1140
              r = gv(RC_INT);
711
	  keep++;
1141
              o(0xE52D0004|(intr(r)<<12)); /* push r */
712
          vswap();
1142
            }
-
 
1143
            if (i == STACK_CLASS && pplan->prev)
713
	}
1144
              gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
714
	size = 8;
1145
          }
715
      }
1146
          break;
-
 
1147
 
-
 
1148
        case VFP_CLASS:
716
      s=RC_INT;
1149
          gv(regmask(TREG_F0 + (pplan->start >> 1)));
-
 
1150
          if (pplan->start & 1) { /* Must be in upper part of double register */
-
 
1151
            o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
717
      if(nb_args-i<5 && plan[nb_args-i-1][0]!=-1) {
1152
            vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
-
 
1153
          }
718
        s=regmask(plan[nb_args-i-1][0]);
1154
          break;
-
 
1155
 
719
	todo&=~(1<
1156
        case CORE_CLASS:
720
      }
1157
          if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
721
      if(s==RC_INT) {
-
 
722
	r = gv(s);
-
 
723
	o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
-
 
724
	vtop--;
1158
            lexpand_nr();
-
 
1159
            gv(regmask(pplan->end));
-
 
1160
            pplan->sval->r2 = vtop->r;
-
 
1161
            vtop--;
-
 
1162
          }
725
      } else {
1163
          gv(regmask(pplan->start));
726
	plan2[keep]=s;
1164
          /* Mark register as used so that gcall_or_jmp use another one
-
 
1165
             (regs >=4 are free as never used to pass parameters) */
727
	keep++;
1166
          pplan->sval->r = vtop->r;
728
      }
-
 
729
      args_size += size;
-
 
730
    }
-
 
731
  }
1167
          break;
-
 
1168
      }
732
  for(i=keep;i--;) {
1169
      vtop--;
733
    gv(plan2[i]);
-
 
734
    vrott(keep);
1170
    }
735
  }
-
 
736
  save_regs(keep); /* save used temporary registers */
1171
  }
737
  keep++;
-
 
738
  if(args_size) {
1172
 
739
    int n;
-
 
740
    n=args_size/4;
1173
  /* Manually free remaining registers since next parameters are loaded
-
 
1174
   * manually, without the help of gv(int). */
-
 
1175
  save_regs(nb_args);
741
    if(n>4)
1176
 
742
      n=4;
1177
  if(todo) {
-
 
1178
    o(0xE8BD0000|todo); /* pop {todo} */
-
 
1179
    for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {
-
 
1180
      int r;
-
 
1181
      pplan->sval->r = pplan->start;
743
    todo&=((1<
1182
      /* An SValue can only pin 2 registers at best (r and r2) but a structure
744
    if(todo) {
1183
         can occupy more than 2 registers. Thus, we need to push on the value
-
 
1184
         stack some fake parameter to have on SValue for each registers used
745
      int i;
1185
         by a structure (r2 is not used). */
746
      o(0xE8BD0000|todo);
1186
      for (r = pplan->start + 1; r <= pplan->end; r++) {
747
      for(i=0;i<4;i++)
1187
        if (todo & (1 << r)) {
-
 
1188
          nb_extra_sval++;
-
 
1189
          vpushi(0);
748
	if(todo&(1<
1190
          vtop->r = r;
-
 
1191
        }
-
 
1192
      }
-
 
1193
    }
-
 
1194
  }
-
 
1195
  return nb_extra_sval;
-
 
1196
}
-
 
1197
 
-
 
1198
/* Generate function call. The function address is pushed first, then
-
 
1199
   all the parameters in call order. This functions pops all the
-
 
1200
   parameters and the function address. */
-
 
1201
void gfunc_call(int nb_args)
-
 
1202
{
-
 
1203
  int r, args_size;
-
 
1204
  int def_float_abi = float_abi;
-
 
1205
  int todo;
-
 
1206
  struct plan plan;
-
 
1207
 
-
 
1208
#ifdef TCC_ARM_EABI
-
 
1209
  int variadic;
-
 
1210
 
749
	  vpushi(0);
1211
  if (float_abi == ARM_HARD_FLOAT) {
-
 
1212
    variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
-
 
1213
    if (variadic || floats_in_core_regs(&vtop[-nb_args]))
-
 
1214
      float_abi = ARM_SOFTFP_FLOAT;
-
 
1215
  }
-
 
1216
#endif
-
 
1217
  /* cannot let cpu flags if other instruction are generated. Also avoid leaving
750
	  vtop->r=i;
1218
     VT_JMP anywhere except on the top of the stack because it would complicate
-
 
1219
     the code generator. */
-
 
1220
  r = vtop->r & VT_VALMASK;
-
 
1221
  if (r == VT_CMP || (r & ~1) == VT_JMP)
-
 
1222
    gv(RC_INT);
-
 
1223
 
-
 
1224
  args_size = assign_regs(nb_args, float_abi, &plan, &todo);
-
 
1225
 
751
	  keep++;
1226
#ifdef TCC_ARM_EABI
-
 
1227
  if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
-
 
1228
    args_size = (args_size + 7) & ~7;
-
 
1229
    o(0xE24DD004); /* sub sp, sp, #4 */
752
	}
1230
  }
-
 
1231
#endif
-
 
1232
 
753
    }
1233
  nb_args += copy_params(nb_args, &plan, todo);
754
    args_size-=n*4;
1234
  tcc_free(plan.pplans);
755
  }
1235
 
-
 
1236
  /* Move fct SValue on top as required by gcall_or_jmp */
-
 
1237
  vrotb(nb_args + 1);
-
 
1238
  gcall_or_jmp(0);
-
 
1239
  if (args_size)
756
  vnrott(keep);
1240
      gadd_sp(args_size); /* pop all parameters passed on the stack */
757
  func_sym = vtop->type.ref;
1241
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-
 
1242
  if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
-
 
1243
    if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
-
 
1244
      o(0xEE000A10); /*vmov s0, r0 */
-
 
1245
    } else {
-
 
1246
      o(0xEE000B10); /* vmov.32 d0[0], r0 */
-
 
1247
      o(0xEE201B10); /* vmov.32 d0[1], r1 */
-
 
1248
    }
-
 
1249
  }
758
  gcall_or_jmp(0);
1250
#endif
Line 759... Line 1251...
759
  if (args_size)
1251
  vtop -= nb_args + 1; /* Pop all params and fct address from value stack */
760
      gadd_sp(args_size);
1252
  leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */
761
  vtop-=keep;
1253
  float_abi = def_float_abi;
762
}
1254
}
763
 
1255
 
-
 
1256
/* generate function prolog of type 't' */
-
 
1257
void gfunc_prolog(CType *func_type)
-
 
1258
{
-
 
1259
  Sym *sym,*sym2;
-
 
1260
  int n, nf, size, align, rs, struct_ret = 0;
-
 
1261
  int addr, pn, sn; /* pn=core, sn=stack */
Line 764... Line 1262...
764
/* generate function prolog of type 't' */
1262
  CType ret_type;
765
void gfunc_prolog(CType *func_type)
1263
 
-
 
1264
#ifdef TCC_ARM_EABI
Line 766... Line 1265...
766
{
1265
  struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
767
  Sym *sym,*sym2;
-
 
768
  int n,addr,size,align;
1266
#endif
769
 
1267
 
770
  sym = func_type->ref;
1268
  sym = func_type->ref;
771
  func_vt = sym->type;
1269
  func_vt = sym->type;
-
 
1270
  func_var = (func_type->ref->c == FUNC_ELLIPSIS);
-
 
1271
 
772
  
1272
  n = nf = 0;
773
  n=0;
1273
  if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
774
  addr=12;
1274
      !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs))
-
 
1275
  {
-
 
1276
    n++;
-
 
1277
    struct_ret = 1;
-
 
1278
    func_vc = 12; /* Offset from fp of the place to store the result */
775
  if((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1279
  }
-
 
1280
  for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {
-
 
1281
    size = type_size(&sym2->type, &align);
-
 
1282
#ifdef TCC_ARM_EABI
-
 
1283
    if (float_abi == ARM_HARD_FLOAT && !func_var &&
776
    func_vc = addr;
1284
        (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {
777
    addr += 4;
1285
      int tmpnf = assign_vfpreg(&avregs, align, size);
778
    n++;
1286
      tmpnf += (size + 3) / 4;
779
  }
1287
      nf = (tmpnf > nf) ? tmpnf : nf;
780
  for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {
1288
    } else
781
    size = type_size(&sym2->type, &align);
1289
#endif
782
    size = (size + 3) & ~3;
1290
    if (n < 4)
783
    n+=size/4;
1291
      n += (size + 3) / 4;
-
 
1292
  }
-
 
1293
  o(0xE1A0C00D); /* mov ip,sp */
-
 
1294
  if (func_var)
784
  }
1295
    n=4;
785
  o(0xE1A0C00D); /* mov ip,sp */
1296
  if (n) {
-
 
1297
    if(n>4)
-
 
1298
      n=4;
-
 
1299
#ifdef TCC_ARM_EABI
-
 
1300
    n=(n+1)&-2;
-
 
1301
#endif
-
 
1302
    o(0xE92D0000|((1<
786
  if(func_type->ref->c == FUNC_ELLIPSIS)
1303
  }
787
    n=4;
1304
  if (nf) {
788
  if(n) {
1305
    if (nf>16)
789
    if(n>4)
1306
      nf=16;
-
 
1307
    nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */
-
 
1308
    o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */
-
 
1309
  }
-
 
1310
  o(0xE92D5800); /* save fp, ip, lr */
-
 
1311
  o(0xE1A0B00D); /* mov fp, sp */
-
 
1312
  func_sub_sp_offset = ind;
-
 
1313
  o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */
-
 
1314
 
790
      n=4;
1315
#ifdef TCC_ARM_EABI
791
    o(0xE92D0000|((1<
1316
  if (float_abi == ARM_HARD_FLOAT) {
792
  }
1317
    func_vc += nf * 4;
793
  o(0xE92D5800); /* save fp, ip, lr*/
-
 
794
  o(0xE1A0B00D); /* mov fp,sp */
1318
    avregs = AVAIL_REGS_INITIALIZER;
795
  func_sub_sp_offset = ind;
1319
  }
-
 
1320
#endif
-
 
1321
  pn = struct_ret, sn = 0;
-
 
1322
  while ((sym = sym->next)) {
-
 
1323
    CType *type;
-
 
1324
    type = &sym->type;
-
 
1325
    size = type_size(type, &align);
-
 
1326
    size = (size + 3) >> 2;
-
 
1327
    align = (align + 3) & ~3;
-
 
1328
#ifdef TCC_ARM_EABI
-
 
1329
    if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t)
-
 
1330
        || is_hgen_float_aggr(&sym->type))) {
-
 
1331
      int fpn = assign_vfpreg(&avregs, align, size << 2);
-
 
1332
      if (fpn >= 0)
-
 
1333
        addr = fpn * 4;
-
 
1334
      else
-
 
1335
        goto from_stack;
-
 
1336
    } else
-
 
1337
#endif
-
 
1338
    if (pn < 4) {
-
 
1339
#ifdef TCC_ARM_EABI
-
 
1340
        pn = (pn + (align-1)/4) & -(align/4);
-
 
1341
#endif
-
 
1342
      addr = (nf + pn) * 4;
-
 
1343
      pn += size;
-
 
1344
      if (!sn && pn > 4)
796
  o(0xE1A00000); /* nop, leave space for stack adjustment */
1345
        sn = (pn - 4);
-
 
1346
    } else {
-
 
1347
#ifdef TCC_ARM_EABI
-
 
1348
from_stack:
797
  while ((sym = sym->next)) {
1349
        sn = (sn + (align-1)/4) & -(align/4);
798
    CType *type;
1350
#endif
-
 
1351
      addr = (n + nf + sn) * 4;
799
    type = &sym->type;
1352
      sn += size;
800
    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
1353
    }
Line 801... Line 1354...
801
    size = type_size(type, &align);
1354
    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),
802
    size = (size + 3) & ~3;
1355
             addr + 12);
803
    addr += size;
1356
  }
804
  }
1357
  last_itod_magic=0;
-
 
1358
  leaffunc = 1;
-
 
1359
  loc = 0;
-
 
1360
}
-
 
1361
 
-
 
1362
/* generate function epilog */
-
 
1363
void gfunc_epilog(void)
-
 
1364
{
-
 
1365
  uint32_t x;
-
 
1366
  int diff;
-
 
1367
  /* Copy float return value to core register if base standard is used and
-
 
1368
     float computation is made with VFP */
-
 
1369
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-
 
1370
  if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {
805
  last_itod_magic=0;
1371
    if((func_vt.t & VT_BTYPE) == VT_FLOAT)
-
 
1372
      o(0xEE100A10); /* fmrs r0, s0 */
-
 
1373
    else {
-
 
1374
      o(0xEE100B10); /* fmrdl r0, d0 */
-
 
1375
      o(0xEE301B10); /* fmrdh r1, d0 */
-
 
1376
    }
806
  loc = 0;
1377
  }
807
}
1378
#endif
808
 
1379
  o(0xE89BA800); /* restore fp, sp, pc */
809
/* generate function epilog */
1380
  diff = (-loc + 3) & -4;
810
void gfunc_epilog(void)
1381
#ifdef TCC_ARM_EABI
811
{
1382
  if(!leaffunc)
812
  unsigned long x;
1383
    diff = ((diff + 11) & -8) - 4;
813
  o(0xE89BA800); /* restore fp, sp, pc */
1384
#endif
814
  if(loc) {
1385
  if(diff > 0) {
815
    x=stuff_const(0xE24DD000, (-loc + 3) & -4); /* sub sp,sp,# */
1386
    x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
816
    if(x)
1387
    if(x)
817
      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x;
1388
      *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x;
818
    else {
1389
    else {
819
      unsigned long addr;
1390
      int addr;
820
      addr=ind;
1391
      addr=ind;
Line 821... Line 1392...
821
      o(0xE59FC004); /* ldr ip,[pc+4] */
1392
      o(0xE59FC004); /* ldr ip,[pc+4] */
Line 844... Line 1415...
844
 
1415
 
845
/* generate a test. set 'inv' to invert test. Stack entry is popped */
1416
/* generate a test. set 'inv' to invert test. Stack entry is popped */
846
int gtst(int inv, int t)
1417
int gtst(int inv, int t)
847
{
1418
{
848
  int v, r;
1419
  int v, r;
849
  unsigned long op;
1420
  uint32_t op;
850
  v = vtop->r & VT_VALMASK;
1421
  v = vtop->r & VT_VALMASK;
851
  r=ind;
1422
  r=ind;
852
  if (v == VT_CMP) {
1423
  if (v == VT_CMP) {
853
    op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
1424
    op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
Line 857... Line 1428...
857
  } else if (v == VT_JMP || v == VT_JMPI) {
1428
  } else if (v == VT_JMP || v == VT_JMPI) {
858
    if ((v & 1) == inv) {
1429
    if ((v & 1) == inv) {
859
      if(!vtop->c.i)
1430
      if(!vtop->c.i)
860
	vtop->c.i=t;
1431
	vtop->c.i=t;
861
      else {
1432
      else {
862
	unsigned long *x;
1433
	uint32_t *x;
863
	int p,lp;
1434
	int p,lp;
864
	if(t) {
1435
	if(t) {
865
          p = vtop->c.i;
1436
          p = vtop->c.i;
866
          do {
1437
          do {
867
	    p = decbranch(lp=p);
1438
	    p = decbranch(lp=p);
868
          } while(p);
1439
          } while(p);
869
	  x = (unsigned long *)(cur_text_section->data + lp);
1440
	  x = (uint32_t *)(cur_text_section->data + lp);
870
	  *x &= 0xff000000;
1441
	  *x &= 0xff000000;
871
	  *x |= encbranch(lp,t,1);
1442
	  *x |= encbranch(lp,t,1);
872
	}
1443
	}
873
	t = vtop->c.i;
1444
	t = vtop->c.i;
874
      }
1445
      }
875
    } else {
1446
    } else {
876
      t = gjmp(t);
1447
      t = gjmp(t);
877
      gsym(vtop->c.i);
1448
      gsym(vtop->c.i);
878
    }
1449
    }
879
  } else {
-
 
880
    if (is_float(vtop->type.t)) {
-
 
881
      r=gv(RC_FLOAT);
-
 
882
      o(0xEE90F118|fpr(r)<<16);
-
 
883
      vtop->r = VT_CMP;
-
 
884
      vtop->c.i = TOK_NE;
-
 
885
      return gtst(inv, t);
-
 
886
    } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
-
 
887
      /* constant jmp optimization */
-
 
888
      if ((vtop->c.i != 0) != inv) 
-
 
889
	t = gjmp(t);
-
 
890
    } else {
-
 
891
      v = gv(RC_INT);
-
 
892
      o(0xE3300000|(intr(v)<<16));
-
 
893
      vtop->r = VT_CMP;
-
 
894
      vtop->c.i = TOK_NE;
-
 
895
      return gtst(inv, t);
-
 
896
    }   
-
 
897
  }
1450
  }
898
  vtop--;
1451
  vtop--;
899
  return t;
1452
  return t;
900
}
1453
}
Line 901... Line 1454...
901
 
1454
 
902
/* generate an integer binary operation */
1455
/* generate an integer binary operation */
903
void gen_opi(int op)
1456
void gen_opi(int op)
904
{
1457
{
905
  int c, func = 0;
1458
  int c, func = 0;
-
 
1459
  uint32_t opc = 0, r, fr;
Line 906... Line 1460...
906
  unsigned long opc = 0,r,fr;
1460
  unsigned short retreg = REG_IRET;
907
 
1461
 
908
  c=0;
1462
  c=0;
909
  switch(op) {
1463
  switch(op) {
Line 970... Line 1524...
970
    case TOK_UDIV:
1524
    case TOK_UDIV:
971
      func=TOK___udivsi3;
1525
      func=TOK___udivsi3;
972
      c=3;
1526
      c=3;
973
      break;
1527
      break;
974
    case '%':
1528
    case '%':
-
 
1529
#ifdef TCC_ARM_EABI
-
 
1530
      func=TOK___aeabi_idivmod;
-
 
1531
      retreg=REG_LRET;
-
 
1532
#else
975
      func=TOK___modsi3;
1533
      func=TOK___modsi3;
-
 
1534
#endif
976
      c=3;
1535
      c=3;
977
      break;
1536
      break;
978
    case TOK_UMOD:
1537
    case TOK_UMOD:
-
 
1538
#ifdef TCC_ARM_EABI
-
 
1539
      func=TOK___aeabi_uidivmod;
-
 
1540
      retreg=REG_LRET;
-
 
1541
#else
979
      func=TOK___umodsi3;
1542
      func=TOK___umodsi3;
-
 
1543
#endif
980
      c=3;
1544
      c=3;
981
      break;
1545
      break;
982
    case TOK_UMULL:
1546
    case TOK_UMULL:
983
      gv2(RC_INT, RC_INT);
1547
      gv2(RC_INT, RC_INT);
984
      r=intr(vtop[-1].r2=get_reg(RC_INT));
1548
      r=intr(vtop[-1].r2=get_reg(RC_INT));
Line 1006... Line 1570...
1006
      vswap();
1570
      vswap();
1007
      c=intr(gv(RC_INT));
1571
      c=intr(gv(RC_INT));
1008
      vswap();
1572
      vswap();
1009
      opc=0xE0000000|(opc<<20)|(c<<16);
1573
      opc=0xE0000000|(opc<<20)|(c<<16);
1010
      if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1574
      if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1011
	unsigned long x;
1575
	uint32_t x;
1012
	x=stuff_const(opc|0x2000000,vtop->c.i);
1576
	x=stuff_const(opc|0x2000000,vtop->c.i);
1013
	if(x) {
1577
	if(x) {
1014
	  r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1578
	  r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1015
	  o(x|(r<<12));
1579
	  o(x|(r<<12));
1016
	  goto done;
1580
	  goto done;
Line 1049... Line 1613...
1049
    case 3:
1613
    case 3:
1050
      vpush_global_sym(&func_old_type, func);
1614
      vpush_global_sym(&func_old_type, func);
1051
      vrott(3);
1615
      vrott(3);
1052
      gfunc_call(2);
1616
      gfunc_call(2);
1053
      vpushi(0);
1617
      vpushi(0);
1054
      vtop->r = REG_IRET;
1618
      vtop->r = retreg;
1055
      break;
1619
      break;
1056
    default:
1620
    default:
1057
      error("gen_opi %i unimplemented!",op);
1621
      tcc_error("gen_opi %i unimplemented!",op);
1058
  }
1622
  }
1059
}
1623
}
Line -... Line 1624...
-
 
1624
 
-
 
1625
#ifdef TCC_ARM_VFP
-
 
1626
static int is_zero(int i)
-
 
1627
{
-
 
1628
  if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
-
 
1629
    return 0;
-
 
1630
  if (vtop[i].type.t == VT_FLOAT)
-
 
1631
    return (vtop[i].c.f == 0.f);
-
 
1632
  else if (vtop[i].type.t == VT_DOUBLE)
-
 
1633
    return (vtop[i].c.d == 0.0);
-
 
1634
  return (vtop[i].c.ld == 0.l);
-
 
1635
}
-
 
1636
 
-
 
1637
/* generate a floating point operation 'v = t1 op t2' instruction. The
-
 
1638
 *    two operands are guaranted to have the same floating point type */
-
 
1639
void gen_opf(int op)
-
 
1640
{
-
 
1641
  uint32_t x;
-
 
1642
  int fneg=0,r;
-
 
1643
  x=0xEE000A00|T2CPR(vtop->type.t);
-
 
1644
  switch(op) {
-
 
1645
    case '+':
-
 
1646
      if(is_zero(-1))
-
 
1647
        vswap();
-
 
1648
      if(is_zero(0)) {
-
 
1649
        vtop--;
-
 
1650
        return;
-
 
1651
      }
-
 
1652
      x|=0x300000;
-
 
1653
      break;
-
 
1654
    case '-':
-
 
1655
      x|=0x300040;
-
 
1656
      if(is_zero(0)) {
-
 
1657
        vtop--;
-
 
1658
        return;
-
 
1659
      }
-
 
1660
      if(is_zero(-1)) {
-
 
1661
        x|=0x810000; /* fsubX -> fnegX */
-
 
1662
        vswap();
-
 
1663
        vtop--;
-
 
1664
        fneg=1;
-
 
1665
      }
-
 
1666
      break;
-
 
1667
    case '*':
-
 
1668
      x|=0x200000;
-
 
1669
      break;
-
 
1670
    case '/':
-
 
1671
      x|=0x800000;
-
 
1672
      break;
-
 
1673
    default:
-
 
1674
      if(op < TOK_ULT || op > TOK_GT) {
-
 
1675
        tcc_error("unknown fp op %x!",op);
-
 
1676
        return;
-
 
1677
      }
-
 
1678
      if(is_zero(-1)) {
-
 
1679
        vswap();
-
 
1680
        switch(op) {
-
 
1681
          case TOK_LT: op=TOK_GT; break;
-
 
1682
          case TOK_GE: op=TOK_ULE; break;
-
 
1683
          case TOK_LE: op=TOK_GE; break;
-
 
1684
          case TOK_GT: op=TOK_ULT; break;
-
 
1685
        }
-
 
1686
      }
-
 
1687
      x|=0xB40040; /* fcmpX */
-
 
1688
      if(op!=TOK_EQ && op!=TOK_NE)
-
 
1689
        x|=0x80; /* fcmpX -> fcmpeX */
-
 
1690
      if(is_zero(0)) {
-
 
1691
        vtop--;
-
 
1692
        o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
-
 
1693
      } else {
-
 
1694
        x|=vfpr(gv(RC_FLOAT));
-
 
1695
        vswap();
-
 
1696
        o(x|(vfpr(gv(RC_FLOAT))<<12));
-
 
1697
        vtop--;
-
 
1698
      }
-
 
1699
      o(0xEEF1FA10); /* fmstat */
-
 
1700
 
-
 
1701
      switch(op) {
-
 
1702
        case TOK_LE: op=TOK_ULE; break;
-
 
1703
        case TOK_LT: op=TOK_ULT; break;
-
 
1704
        case TOK_UGE: op=TOK_GE; break;
-
 
1705
        case TOK_UGT: op=TOK_GT; break;
-
 
1706
      }
-
 
1707
 
-
 
1708
      vtop->r = VT_CMP;
-
 
1709
      vtop->c.i = op;
-
 
1710
      return;
-
 
1711
  }
-
 
1712
  r=gv(RC_FLOAT);
-
 
1713
  x|=vfpr(r);
-
 
1714
  r=regmask(r);
-
 
1715
  if(!fneg) {
-
 
1716
    int r2;
-
 
1717
    vswap();
-
 
1718
    r2=gv(RC_FLOAT);
-
 
1719
    x|=vfpr(r2)<<16;
-
 
1720
    r|=regmask(r2);
-
 
1721
  }
-
 
1722
  vtop->r=get_reg_ex(RC_FLOAT,r);
-
 
1723
  if(!fneg)
-
 
1724
    vtop--;
-
 
1725
  o(x|(vfpr(vtop->r)<<12));
-
 
1726
}
-
 
1727
 
1060
 
1728
#else
1061
static int is_fconst()
1729
static uint32_t is_fconst()
1062
{
1730
{
1063
  long double f;
1731
  long double f;
1064
  int r;
1732
  uint32_t r;
1065
  if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1733
  if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1066
    return 0;
1734
    return 0;
1067
  if (vtop->type.t == VT_FLOAT)
1735
  if (vtop->type.t == VT_FLOAT)
1068
    f = vtop->c.f;
1736
    f = vtop->c.f;
Line 1098... Line 1766...
1098
 
1766
 
1099
/* generate a floating point operation 'v = t1 op t2' instruction. The
1767
/* generate a floating point operation 'v = t1 op t2' instruction. The
1100
   two operands are guaranted to have the same floating point type */
1768
   two operands are guaranted to have the same floating point type */
1101
void gen_opf(int op)
1769
void gen_opf(int op)
1102
{
-
 
1103
  unsigned long x;
1770
{
1104
  int r,r2,c1,c2;
1771
  uint32_t x, r, r2, c1, c2;
1105
  //fputs("gen_opf\n",stderr);
1772
  //fputs("gen_opf\n",stderr);
1106
  vswap();
1773
  vswap();
1107
  c1 = is_fconst();
1774
  c1 = is_fconst();
1108
  vswap();
1775
  vswap();
Line 1191... Line 1858...
1191
      }     
1858
      }
1192
      break;
1859
      break;
1193
    default:
1860
    default:
1194
      if(op >= TOK_ULT && op <= TOK_GT) {
1861
      if(op >= TOK_ULT && op <= TOK_GT) {
1195
	x|=0xd0f110; // cmfe
1862
	x|=0xd0f110; // cmfe
-
 
1863
/* bug (intention?) in Linux FPU emulator
-
 
1864
   doesn't set carry if equal */
1196
	switch(op) {
1865
	switch(op) {
1197
	  case TOK_ULT:
1866
	  case TOK_ULT:
1198
	  case TOK_UGE:
1867
	  case TOK_UGE:
1199
	  case TOK_ULE:
1868
	  case TOK_ULE:
1200
	  case TOK_UGT:
1869
	  case TOK_UGT:
1201
	    fputs("unsigned comparision on floats?\n",stderr);
1870
            tcc_error("unsigned comparison on floats?");
1202
	    break;
1871
	    break;
1203
	  case TOK_LT:
1872
	  case TOK_LT:
1204
	    op=TOK_ULT;
-
 
1205
	    break;
-
 
1206
	  case TOK_GE:
-
 
1207
	    op=TOK_UGE;
1873
            op=TOK_Nset;
1208
	    break;
1874
	    break;
1209
	  case TOK_LE:
1875
	  case TOK_LE:
1210
	    op=TOK_ULE;
1876
            op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
1211
	    break;
-
 
1212
	  case TOK_GT:
-
 
1213
	    op=TOK_UGT;
-
 
1214
	    break;
1877
	    break;
1215
	  case TOK_EQ:
1878
	  case TOK_EQ:
1216
	  case TOK_NE:
1879
	  case TOK_NE:
1217
	    x&=~0x400000; // cmfe -> cmf
1880
	    x&=~0x400000; // cmfe -> cmf
1218
	    break;
1881
	    break;
1219
	}
1882
	}
1220
	if(c1 && !c2) {
1883
	if(c1 && !c2) {
1221
	  c2=c1;
1884
	  c2=c1;
1222
	  vswap();
1885
	  vswap();
1223
	  switch(op) {
1886
	  switch(op) {
1224
	    case TOK_ULT:
1887
            case TOK_Nset:
1225
	      op=TOK_UGT;
1888
              op=TOK_GT;
1226
	      break;
1889
	      break;
1227
	    case TOK_UGE:
1890
            case TOK_GE:
1228
	      op=TOK_ULE;
1891
	      op=TOK_ULE;
1229
	      break;
1892
	      break;
1230
	    case TOK_ULE:
1893
	    case TOK_ULE:
1231
	      op=TOK_UGE;
1894
              op=TOK_GE;
1232
	      break;
1895
	      break;
1233
	    case TOK_UGT:
1896
            case TOK_GT:
1234
	      op=TOK_ULT;
1897
              op=TOK_Nset;
1235
	      break;
1898
	      break;
1236
	  }
1899
	  }
1237
	}
1900
	}
1238
// bug (intention?) in Linux FPU emulator
-
 
1239
// doesn't set carry if equal
-
 
1240
	if(op==TOK_ULT)
-
 
1241
	  op=TOK_LT;
-
 
1242
	else if(op==TOK_UGE)
-
 
1243
	  op=TOK_GE;
-
 
1244
	vswap();
1901
	vswap();
1245
	r=fpr(gv(RC_FLOAT));
1902
	r=fpr(gv(RC_FLOAT));
1246
	vswap();
1903
	vswap();
1247
	if(c2) {
1904
	if(c2) {
1248
	  if(c2>0xf)
1905
	  if(c2>0xf)
Line 1252... Line 1909...
1252
	  r2=fpr(gv(RC_FLOAT));
1909
	  r2=fpr(gv(RC_FLOAT));
1253
	}
1910
	}
1254
	vtop[-1].r = VT_CMP;
1911
	vtop[-1].r = VT_CMP;
1255
	vtop[-1].c.i = op;
1912
	vtop[-1].c.i = op;
1256
      } else {
1913
      } else {
1257
	error("unknown fp op %x!\n",op);
1914
        tcc_error("unknown fp op %x!",op);
1258
	return;
1915
	return;
1259
      }
1916
      }
1260
  }
1917
  }
1261
  if(vtop[-1].r == VT_CMP)
1918
  if(vtop[-1].r == VT_CMP)
1262
    c1=15;
1919
    c1=15;
Line 1268... Line 1925...
1268
    c1=fpr(vtop[-1].r);
1925
    c1=fpr(vtop[-1].r);
1269
  }
1926
  }
1270
  vtop--;
1927
  vtop--;
1271
  o(x|(r<<16)|(c1<<12)|r2);
1928
  o(x|(r<<16)|(c1<<12)|r2);
1272
}
1929
}
-
 
1930
#endif
Line 1273... Line 1931...
1273
 
1931
 
1274
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1932
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1275
   and 'long long' cases. */
1933
   and 'long long' cases. */
1276
void gen_cvt_itof(int t)
1934
ST_FUNC void gen_cvt_itof1(int t)
-
 
1935
{
1277
{
1936
  uint32_t r, r2;
1278
  int r,r2,bt;
1937
  int bt;
1279
  bt=vtop->type.t & VT_BTYPE;
1938
  bt=vtop->type.t & VT_BTYPE;
-
 
1939
  if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
-
 
1940
#ifndef TCC_ARM_VFP
-
 
1941
    uint32_t dsize = 0;
1280
  if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
1942
#endif
-
 
1943
    r=intr(gv(RC_INT));
-
 
1944
#ifdef TCC_ARM_VFP
-
 
1945
    r2=vfpr(vtop->r=get_reg(RC_FLOAT));
-
 
1946
    o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
-
 
1947
    r2|=r2<<12;
-
 
1948
    if(!(vtop->type.t & VT_UNSIGNED))
-
 
1949
      r2|=0x80;                /* fuitoX -> fsituX */
-
 
1950
    o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
1281
    r=intr(gv(RC_INT));
1951
#else
-
 
1952
    r2=fpr(vtop->r=get_reg(RC_FLOAT));
-
 
1953
    if((t & VT_BTYPE) != VT_FLOAT)
1282
    r2=fpr(vtop->r=get_reg(RC_FLOAT));
1954
      dsize=0x80;    /* flts -> fltd */
1283
    o(0xEE000190|(r2<<16)|(r<<12));
1955
    o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */
1284
    if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
1956
    if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
1285
      unsigned int off=0;
1957
      uint32_t off = 0;
1286
      o(0xE3500000|(r<<12));
1958
      o(0xE3500000|(r<<12));        /* cmp */
1287
      r=fpr(get_reg(RC_FLOAT));
1959
      r=fpr(get_reg(RC_FLOAT));
1288
      if(last_itod_magic) {
1960
      if(last_itod_magic) {
1289
	off=ind+8-last_itod_magic;
1961
	off=ind+8-last_itod_magic;
1290
	off/=4;
1962
	off/=4;
1291
	if(off>255)
1963
	if(off>255)
1292
	  off=0;
1964
	  off=0;
1293
      }
1965
      }
1294
      o(0xBD1F8100|(r<<12)|off);
1966
      o(0xBD1F0100|(r<<12)|off);    /* ldflts */
1295
      if(!off) {
1967
      if(!off) {
1296
        o(0xEA000001);
1968
        o(0xEA000000);              /* b */
1297
        last_itod_magic=ind;
1969
        last_itod_magic=ind;
1298
        o(0x41F00000);
-
 
1299
        o(0);
1970
        o(0x4F800000);              /* 4294967296.0f */
1300
      }
1971
      }
1301
      o(0xBE000180|(r2<<16)|(r2<<12)|r);
1972
      o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */
-
 
1973
    }
1302
    }
1974
#endif
1303
    return;
1975
    return;
1304
  } else if(bt == VT_LLONG) {
1976
  } else if(bt == VT_LLONG) {
-
 
1977
    int func;
-
 
1978
    CType *func_type = 0;
-
 
1979
    if((t & VT_BTYPE) == VT_FLOAT) {
1305
    int func;
1980
      func_type = &func_float_type;
1306
    if(vtop->type.t & VT_UNSIGNED)
1981
      if(vtop->type.t & VT_UNSIGNED)
1307
      func=TOK___ulltold;
1982
        func=TOK___floatundisf;
-
 
1983
      else
-
 
1984
        func=TOK___floatdisf;
-
 
1985
#if LDOUBLE_SIZE != 8
-
 
1986
    } else if((t & VT_BTYPE) == VT_LDOUBLE) {
-
 
1987
      func_type = &func_ldouble_type;
-
 
1988
      if(vtop->type.t & VT_UNSIGNED)
-
 
1989
        func=TOK___floatundixf;
-
 
1990
      else
-
 
1991
        func=TOK___floatdixf;
-
 
1992
    } else if((t & VT_BTYPE) == VT_DOUBLE) {
-
 
1993
#else
-
 
1994
    } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
-
 
1995
#endif
-
 
1996
      func_type = &func_double_type;
-
 
1997
      if(vtop->type.t & VT_UNSIGNED)
-
 
1998
        func=TOK___floatundidf;
1308
    else
1999
      else
-
 
2000
        func=TOK___floatdidf;
-
 
2001
    }
1309
      func=TOK___slltold;
2002
    if(func_type) {
1310
    vpush_global_sym(&func_old_type, func);
2003
      vpush_global_sym(func_type, func);
1311
    vswap();
2004
      vswap();
1312
    gfunc_call(1);
2005
      gfunc_call(1);
1313
    vpushi(0);
2006
      vpushi(0);
1314
    vtop->r=TREG_F0;
2007
      vtop->r=TREG_F0;
1315
    return;
2008
      return;
-
 
2009
    }
1316
  }
2010
  }
1317
  error("unimplemented gen_cvt_itof %x!",vtop->type.t);
2011
  tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t);
Line 1318... Line 2012...
1318
}
2012
}
1319
 
2013
 
1320
/* convert fp to int 't' type */
2014
/* convert fp to int 't' type */
-
 
2015
void gen_cvt_ftoi(int t)
1321
void gen_cvt_ftoi(int t)
2016
{
1322
{
2017
  uint32_t r, r2;
1323
  int r,r2,u,func=0;
2018
  int u, func = 0;
1324
  u=t&VT_UNSIGNED;
2019
  u=t&VT_UNSIGNED;
1325
  t&=VT_BTYPE;
2020
  t&=VT_BTYPE;
-
 
2021
  r2=vtop->type.t & VT_BTYPE;
-
 
2022
  if(t==VT_INT) {
-
 
2023
#ifdef TCC_ARM_VFP
-
 
2024
    r=vfpr(gv(RC_FLOAT));
-
 
2025
    u=u?0:0x10000;
-
 
2026
    o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */
-
 
2027
    r2=intr(vtop->r=get_reg(RC_INT));
-
 
2028
    o(0xEE100A10|(r<<16)|(r2<<12));
1326
  r2=vtop->type.t & VT_BTYPE;
2029
    return;
1327
  if(t==VT_INT) {
2030
#else
1328
    if(u) {
2031
    if(u) {
1329
      if(r2 == VT_FLOAT)
-
 
1330
        func=TOK___fixunssfsi;
2032
      if(r2 == VT_FLOAT)
1331
      else if(r2 == VT_DOUBLE)
2033
        func=TOK___fixunssfsi;
1332
	func=TOK___fixunsdfsi;
-
 
1333
      else if(r2 == VT_LDOUBLE)
-
 
1334
#if LDOUBLE_SIZE == 8
-
 
1335
	func=TOK___fixunsdfsi;
2034
#if LDOUBLE_SIZE != 8
-
 
2035
      else if(r2 == VT_LDOUBLE)
-
 
2036
	func=TOK___fixunsxfsi;
-
 
2037
      else if(r2 == VT_DOUBLE)
1336
#else
2038
#else
-
 
2039
      else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
1337
	func=TOK___fixunsxfsi;
2040
#endif
1338
#endif
2041
	func=TOK___fixunsdfsi;
1339
    } else {
2042
    } else {
1340
      r=fpr(gv(RC_FLOAT));
2043
      r=fpr(gv(RC_FLOAT));
1341
      r2=intr(vtop->r=get_reg(RC_INT));
2044
      r2=intr(vtop->r=get_reg(RC_INT));
1342
      o(0xEE100170|(r2<<12)|r);
2045
      o(0xEE100170|(r2<<12)|r);
-
 
2046
      return;
1343
    return;
2047
    }
1344
    }
2048
#endif
1345
  } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
2049
  } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
1346
    if(r2 == VT_FLOAT)
-
 
1347
      func=TOK___fixsfdi;
2050
    if(r2 == VT_FLOAT)
1348
    else if(r2 == VT_DOUBLE)
2051
      func=TOK___fixsfdi;
1349
      func=TOK___fixdfdi;
-
 
1350
    else if(r2 == VT_LDOUBLE)
-
 
1351
#if LDOUBLE_SIZE == 8
-
 
1352
      func=TOK___fixdfdi;
2052
#if LDOUBLE_SIZE != 8
-
 
2053
    else if(r2 == VT_LDOUBLE)
-
 
2054
      func=TOK___fixxfdi;
-
 
2055
    else if(r2 == VT_DOUBLE)
1353
#else
2056
#else
-
 
2057
    else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
1354
      func=TOK___fixxfdi;
2058
#endif
1355
#endif
2059
      func=TOK___fixdfdi;
1356
    }
2060
  }
1357
  if(func) {
2061
  if(func) {
1358
    vpush_global_sym(&func_old_type, func);
2062
    vpush_global_sym(&func_old_type, func);
Line 1362... Line 2066...
1362
    if(t == VT_LLONG)
2066
    if(t == VT_LLONG)
1363
      vtop->r2 = REG_LRET;
2067
      vtop->r2 = REG_LRET;
1364
    vtop->r = REG_IRET;
2068
    vtop->r = REG_IRET;
1365
    return;
2069
    return;
1366
  }
2070
  }
1367
  error("unimplemented gen_cvt_ftoi!");
2071
  tcc_error("unimplemented gen_cvt_ftoi!");
1368
}
2072
}
Line 1369... Line 2073...
1369
 
2073
 
1370
/* convert from one floating point type to another */
2074
/* convert from one floating point type to another */
1371
void gen_cvt_ftof(int t)
2075
void gen_cvt_ftof(int t)
-
 
2076
{
-
 
2077
#ifdef TCC_ARM_VFP
-
 
2078
  if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
-
 
2079
    uint32_t r = vfpr(gv(RC_FLOAT));
-
 
2080
    o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
-
 
2081
  }
1372
{
2082
#else
1373
  /* all we have to do on i386 and ARM is to put the float in a register */
2083
  /* all we have to do on i386 and FPA ARM is to put the float in a register */
-
 
2084
  gv(RC_FLOAT);
1374
  gv(RC_FLOAT);
2085
#endif
Line 1375... Line 2086...
1375
}
2086
}
1376
 
2087
 
1377
/* computed goto support */
2088
/* computed goto support */
1378
void ggoto(void)
2089
void ggoto(void)
1379
{
2090
{
1380
  gcall_or_jmp(1);
2091
  gcall_or_jmp(1);
Line -... Line 2092...
-
 
2092
  vtop--;
-
 
2093
}
-
 
2094
 
-
 
2095
/* Save the stack pointer onto the stack and return the location of its address */
-
 
2096
ST_FUNC void gen_vla_sp_save(int addr) {
-
 
2097
    tcc_error("variable length arrays unsupported for this target");
-
 
2098
}
-
 
2099
 
-
 
2100
/* Restore the SP from a location on the stack */
-
 
2101
ST_FUNC void gen_vla_sp_restore(int addr) {
-
 
2102
    tcc_error("variable length arrays unsupported for this target");
-
 
2103
}
-
 
2104
 
-
 
2105
/* Subtract from the stack pointer, and push the resulting value onto the stack */
-
 
2106
ST_FUNC void gen_vla_alloc(CType *type, int align) {
1381
  vtop--;
2107
    tcc_error("variable length arrays unsupported for this target");
1382
}
2108
}
1383
 
2109
 
-
 
2110
/* end of ARM code generator */