History

clang-format on arm-gen.c and tcccoff.c.

They now mostly follow the same coding style as everything else.

gus knight committed 11 years ago

Commit 694d0fd1 parent 9e1b6bf2 files · +2155 −2140Browse files

Unified · Split

2 files
  1. arm-gen.c +1517 −1478
  2. tcccoff.c +638 −662
arm-gen.c+1517−1478
@@ -29,40 +29,40 @@ · 28 unmodified lines
29 29
30/* number of available registers */30/* number of available registers */
31#ifdef TCC_ARM_VFP31#ifdef TCC_ARM_VFP
32#define NB_REGS 1332#define NB_REGS 13
33#else33#else
34#define NB_REGS 934#define NB_REGS 9
35#endif35#endif
36 36
37typedef int RegArgs;37typedef int RegArgs;
38 38
39#ifndef TCC_ARM_VERSION39#ifndef TCC_ARM_VERSION
40# define TCC_ARM_VERSION 540#define TCC_ARM_VERSION 5
41#endif41#endif
42 42
43/* a register can belong to several classes. The classes must be43/* a register can belong to several classes. The classes must be
44 sorted from more general to more precise (see gv2() code which does44 sorted from more general to more precise (see gv2() code which does
45 assumptions on it). */45 assumptions on it). */
46#define RC_INT 0x0001 /* generic integer register */46#define RC_INT 0x0001 /* generic integer register */
47#define RC_FLOAT 0x0002 /* generic float register */47#define RC_FLOAT 0x0002 /* generic float register */
48#define RC_R0 0x000448#define RC_R0 0x0004
49#define RC_R1 0x000849#define RC_R1 0x0008
50#define RC_R2 0x001050#define RC_R2 0x0010
51#define RC_R3 0x002051#define RC_R3 0x0020
52#define RC_R12 0x004052#define RC_R12 0x0040
53#define RC_F0 0x008053#define RC_F0 0x0080
54#define RC_F1 0x010054#define RC_F1 0x0100
55#define RC_F2 0x020055#define RC_F2 0x0200
56#define RC_F3 0x040056#define RC_F3 0x0400
57#ifdef TCC_ARM_VFP57#ifdef TCC_ARM_VFP
58#define RC_F4 0x080058#define RC_F4 0x0800
59#define RC_F5 0x100059#define RC_F5 0x1000
60#define RC_F6 0x200060#define RC_F6 0x2000
61#define RC_F7 0x400061#define RC_F7 0x4000
62#endif62#endif
63#define RC_IRET RC_R0 /* function return: integer register */63#define RC_IRET RC_R0 /* function return: integer register */
64#define RC_LRET RC_R1 /* function return: second integer register */64#define RC_LRET RC_R1 /* function return: second integer register */
65#define RC_FRET RC_F0 /* function return: float register */65#define RC_FRET RC_F0 /* function return: float register */
66 66
67/* pretty names for the registers */67/* pretty names for the registers */
68enum {68enum {
@@ -84,7 +84,7 @@ enum { · 15 unmodified lines
84};84};
85 85
86#ifdef TCC_ARM_VFP86#ifdef TCC_ARM_VFP
87#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)87#define T2CPR(t) (((t)&VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
88#endif88#endif
89 89
90/* return registers for function */90/* return registers for function */
@@ -111,11 +111,11 @@ enum { · 20 unmodified lines
111 111
112/* long double size and alignment, in bytes */112/* long double size and alignment, in bytes */
113#ifdef TCC_ARM_VFP113#ifdef TCC_ARM_VFP
114#define LDOUBLE_SIZE 8114#define LDOUBLE_SIZE 8
115#endif115#endif
116 116
117#ifndef LDOUBLE_SIZE117#ifndef LDOUBLE_SIZE
118#define LDOUBLE_SIZE 8118#define LDOUBLE_SIZE 8
119#endif119#endif
120 120
121#ifdef TCC_ARM_EABI121#ifdef TCC_ARM_EABI
@@ -125,7 +125,7 @@ enum { · 3 unmodified lines
125#endif125#endif
126 126
127/* maximum alignment (for aligned attribute support) */127/* maximum alignment (for aligned attribute support) */
128#define MAX_ALIGN 8128#define MAX_ALIGN 8
129 129
130#define CHAR_IS_UNSIGNED130#define CHAR_IS_UNSIGNED
131 131
@@ -135,13 +135,13 @@ enum { · 3 unmodified lines
135#define EM_TCC_TARGET EM_ARM135#define EM_TCC_TARGET EM_ARM
136 136
137/* relocation type for 32 bit data relocation */137/* relocation type for 32 bit data relocation */
138#define R_DATA_32 R_ARM_ABS32138#define R_DATA_32 R_ARM_ABS32
139#define R_DATA_PTR R_ARM_ABS32139#define R_DATA_PTR R_ARM_ABS32
140#define R_JMP_SLOT R_ARM_JUMP_SLOT140#define R_JMP_SLOT R_ARM_JUMP_SLOT
141#define R_COPY R_ARM_COPY141#define R_COPY R_ARM_COPY
142 142
143#define ELF_START_ADDR 0x00008000143#define ELF_START_ADDR 0x00008000
144#define ELF_PAGE_SIZE 0x1000144#define ELF_PAGE_SIZE 0x1000
145 145
146enum float_abi {146enum float_abi {
147 ARM_SOFTFP_FLOAT,147 ARM_SOFTFP_FLOAT,
@@ -166,10 +166,10 @@ ST_DATA const int reg_classes[NB_REGS] = { · 18 unmodified lines
166 /* f2 */ RC_FLOAT | RC_F2,166 /* f2 */ RC_FLOAT | RC_F2,
167 /* f3 */ RC_FLOAT | RC_F3,167 /* f3 */ RC_FLOAT | RC_F3,
168#ifdef TCC_ARM_VFP168#ifdef TCC_ARM_VFP
169 /* d4/s8 */ RC_FLOAT | RC_F4,169 /* d4/s8 */ RC_FLOAT | RC_F4,
170/* d5/s10 */ RC_FLOAT | RC_F5,170 /* d5/s10 */ RC_FLOAT | RC_F5,
171/* d6/s12 */ RC_FLOAT | RC_F6,171 /* d6/s12 */ RC_FLOAT | RC_F6,
172/* d7/s14 */ RC_FLOAT | RC_F7,172 /* d7/s14 */ RC_FLOAT | RC_F7,
173#endif173#endif
174};174};
175 175
@@ -178,14 +178,16 @@ static int leaffunc; · 2 unmodified lines
178 178
179#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)179#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
180static CType float_type, double_type, func_float_type, func_double_type;180static CType float_type, double_type, func_float_type, func_double_type;
181ST_FUNC void arm_init(struct TCCState *s)181ST_FUNC void arm_init(struct TCCState* s)
182{182{
183 float_type.t = VT_FLOAT;183 float_type.t = VT_FLOAT;
184 double_type.t = VT_DOUBLE;184 double_type.t = VT_DOUBLE;
185 func_float_type.t = VT_FUNC;185 func_float_type.t = VT_FUNC;
186 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);186 func_float_type.ref =
187 sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
187 func_double_type.t = VT_FUNC;188 func_double_type.t = VT_FUNC;
188 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);189 func_double_type.ref =
190 sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
189 191
190 float_abi = s->float_abi;192 float_abi = s->float_abi;
191#ifndef TCC_ARM_HARDFLOAT193#ifndef TCC_ARM_HARDFLOAT
@@ -196,31 +198,33 @@ ST_FUNC void arm_init(struct TCCState *s) · 4 unmodified lines
196#define func_float_type func_old_type198#define func_float_type func_old_type
197#define func_double_type func_old_type199#define func_double_type func_old_type
198#define func_ldouble_type func_old_type200#define func_ldouble_type func_old_type
199ST_FUNC void arm_init(struct TCCState *s)201ST_FUNC void arm_init(struct TCCState* s)
200{202{
201#if !defined (TCC_ARM_VFP)203#if !defined(TCC_ARM_VFP)
202 tcc_warning("Support for FPA is deprecated and will be removed in next"204 tcc_warning("Support for FPA is deprecated and will be removed in next"
203 " release");205 " release");
204#endif206#endif
205#if !defined (TCC_ARM_EABI)207#if !defined(TCC_ARM_EABI)
206 tcc_warning("Support for OABI is deprecated and will be removed in next"208 tcc_warning("Support for OABI is deprecated and will be removed in next"
207 " release");209 " release");
208#endif210#endif
209}211}
210#endif212#endif
211 213
212static int two2mask(int a,int b) {214static int two2mask(int a, int b)
213 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);215{
216 return (reg_classes[a] | reg_classes[b]) & ~(RC_INT | RC_FLOAT);
214}217}
215 218
216static int regmask(int r) {219static int regmask(int r)
217 return reg_classes[r]&~(RC_INT|RC_FLOAT);220{
221 return reg_classes[r] & ~(RC_INT | RC_FLOAT);
218}222}
219 223
220/******************************************************/224/******************************************************/
221 225
222#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)226#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
223char *default_elfinterp(struct TCCState *s)227char* default_elfinterp(struct TCCState* s)
224{228{
225 if (s->float_abi == ARM_HARD_FLOAT)229 if (s->float_abi == ARM_HARD_FLOAT)
226 return "/lib/ld-linux-armhf.so.3";230 return "/lib/ld-linux-armhf.so.3";
@@ -231,551 +235,554 @@ char *default_elfinterp(struct TCCState *s) · 4 unmodified lines
231 235
232void o(uint32_t i)236void o(uint32_t i)
233{237{
234 /* this is a good place to start adding big-endian support*/238 /* this is a good place to start adding big-endian support*/
235 int ind1;239 int ind1;
236 240
237 ind1 = ind + 4;241 ind1 = ind + 4;
238 if (!cur_text_section)242 if (!cur_text_section)
239 tcc_error("compiler error! This happens f.ex. if the compiler\n"243 tcc_error("compiler error! This happens f.ex. if the compiler\n"
240 "can't evaluate constant expressions outside of a function.");244 "can't evaluate constant expressions outside of a function.");
241 if (ind1 > cur_text_section->data_allocated)245 if (ind1 > cur_text_section->data_allocated)
242 section_realloc(cur_text_section, ind1);246 section_realloc(cur_text_section, ind1);
243 cur_text_section->data[ind++] = i&255;247 cur_text_section->data[ind++] = i & 255;
244 i>>=8;248 i >>= 8;
245 cur_text_section->data[ind++] = i&255;249 cur_text_section->data[ind++] = i & 255;
246 i>>=8;250 i >>= 8;
247 cur_text_section->data[ind++] = i&255;251 cur_text_section->data[ind++] = i & 255;
248 i>>=8;252 i >>= 8;
249 cur_text_section->data[ind++] = i;253 cur_text_section->data[ind++] = i;
250}254}
251 255
252static uint32_t stuff_const(uint32_t op, uint32_t c)256static uint32_t stuff_const(uint32_t op, uint32_t c)
253{257{
254 int try_neg=0;258 int try_neg = 0;
255 uint32_t nc = 0, negop = 0;259 uint32_t nc = 0, negop = 0;
256 260
257 switch(op&0x1F00000)261 switch (op & 0x1F00000) {
258 {262 case 0x800000: // add
259 case 0x800000: //add263 case 0x400000: // sub
260 case 0x400000: //sub264 try_neg = 1;
261 try_neg=1;265 negop = op ^ 0xC00000;
262 negop=op^0xC00000;266 nc = -c;
263 nc=-c;267 break;
264 break;268 case 0x1A00000: // mov
265 case 0x1A00000: //mov269 case 0x1E00000: // mvn
266 case 0x1E00000: //mvn270 try_neg = 1;
267 try_neg=1;271 negop = op ^ 0x400000;
268 negop=op^0x400000;272 nc = ~c;
269 nc=~c;273 break;
270 break;274 case 0x200000: // xor
271 case 0x200000: //xor275 if (c == ~0)
272 if(c==~0)276 return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1E00000;
273 return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000;277 break;
274 break;278 case 0x0: // and
275 case 0x0: //and279 if (c == ~0)
276 if(c==~0)280 return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1A00000;
277 return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000;281 case 0x1C00000: // bic
278 case 0x1C00000: //bic282 try_neg = 1;
279 try_neg=1;283 negop = op ^ 0x1C00000;
280 negop=op^0x1C00000;284 nc = ~c;
281 nc=~c;285 break;
282 break;286 case 0x1800000: // orr
283 case 0x1800000: //orr287 if (c == ~0)
284 if(c==~0)288 return (op & 0xFFF0FFFF) | 0x1E00000;
285 return (op&0xFFF0FFFF)|0x1E00000;289 break;
286 break;
287 }
288 do {
289 uint32_t m;
290 int i;
291 if(c<256) /* catch undefined <<32 */
292 return op|c;
293 for(i=2;i<32;i+=2) {
294 m=(0xff>>i)|(0xff<<(32-i));
295 if(!(c&~m))
296 return op|(i<<7)|(c<<i)|(c>>(32-i));
297 }290 }
298 op=negop;291 do {
299 c=nc;292 uint32_t m;
300 } while(try_neg--);293 int i;
301 return 0;294 if (c < 256) /* catch undefined <<32 */
295 return op | c;
296 for (i = 2; i < 32; i += 2) {
297 m = (0xff >> i) | (0xff << (32 - i));
298 if (!(c & ~m))
299 return op | (i << 7) | (c << i) | (c >> (32 - i));
300 }
301 op = negop;
302 c = nc;
303 } while (try_neg--);
304 return 0;
302}305}
303 306
304 307// only add,sub
305//only add,sub308void stuff_const_harder(uint32_t op, uint32_t v)
306void stuff_const_harder(uint32_t op, uint32_t v) {309{
307 uint32_t x;310 uint32_t x;
308 x=stuff_const(op,v);311 x = stuff_const(op, v);
309 if(x)312 if (x)
310 o(x);313 o(x);
311 else {314 else {
312 uint32_t a[16], nv, no, o2, n2;315 uint32_t a[16], nv, no, o2, n2;
313 int i,j,k;316 int i, j, k;
314 a[0]=0xff;317 a[0] = 0xff;
315 o2=(op&0xfff0ffff)|((op&0xf000)<<4);;318 o2 = (op & 0xfff0ffff) | ((op & 0xf000) << 4);
316 for(i=1;i<16;i++)319 ;
317 a[i]=(a[i-1]>>2)|(a[i-1]<<30);320 for (i = 1; i < 16; i++)
318 for(i=0;i<12;i++)321 a[i] = (a[i - 1] >> 2) | (a[i - 1] << 30);
319 for(j=i<4?i+12:15;j>=i+4;j--)322 for (i = 0; i < 12; i++)
320 if((v&(a[i]|a[j]))==v) {323 for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--)
321 o(stuff_const(op,v&a[i]));324 if ((v & (a[i] | a[j])) == v) {
322 o(stuff_const(o2,v&a[j]));325 o(stuff_const(op, v & a[i]));
323 return;326 o(stuff_const(o2, v & a[j]));
324 }327 return;
325 no=op^0xC00000;328 }
326 n2=o2^0xC00000;329 no = op ^ 0xC00000;
327 nv=-v;330 n2 = o2 ^ 0xC00000;
328 for(i=0;i<12;i++)331 nv = -v;
329 for(j=i<4?i+12:15;j>=i+4;j--)332 for (i = 0; i < 12; i++)
330 if((nv&(a[i]|a[j]))==nv) {333 for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--)
331 o(stuff_const(no,nv&a[i]));334 if ((nv & (a[i] | a[j])) == nv) {
332 o(stuff_const(n2,nv&a[j]));335 o(stuff_const(no, nv & a[i]));
333 return;336 o(stuff_const(n2, nv & a[j]));
334 }337 return;
335 for(i=0;i<8;i++)338 }
336 for(j=i+4;j<12;j++)339 for (i = 0; i < 8; i++)
337 for(k=i<4?i+12:15;k>=j+4;k--)340 for (j = i + 4; j < 12; j++)
338 if((v&(a[i]|a[j]|a[k]))==v) {341 for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--)
339 o(stuff_const(op,v&a[i]));342 if ((v & (a[i] | a[j] | a[k])) == v) {
340 o(stuff_const(o2,v&a[j]));343 o(stuff_const(op, v & a[i]));
341 o(stuff_const(o2,v&a[k]));344 o(stuff_const(o2, v & a[j]));
342 return;345 o(stuff_const(o2, v & a[k]));
343 }346 return;
344 no=op^0xC00000;347 }
345 nv=-v;348 no = op ^ 0xC00000;
346 for(i=0;i<8;i++)349 nv = -v;
347 for(j=i+4;j<12;j++)350 for (i = 0; i < 8; i++)
348 for(k=i<4?i+12:15;k>=j+4;k--)351 for (j = i + 4; j < 12; j++)
349 if((nv&(a[i]|a[j]|a[k]))==nv) {352 for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--)
350 o(stuff_const(no,nv&a[i]));353 if ((nv & (a[i] | a[j] | a[k])) == nv) {
351 o(stuff_const(n2,nv&a[j]));354 o(stuff_const(no, nv & a[i]));
352 o(stuff_const(n2,nv&a[k]));355 o(stuff_const(n2, nv & a[j]));
353 return;356 o(stuff_const(n2, nv & a[k]));
354 }357 return;
355 o(stuff_const(op,v&a[0]));358 }
356 o(stuff_const(o2,v&a[4]));359 o(stuff_const(op, v & a[0]));
357 o(stuff_const(o2,v&a[8]));360 o(stuff_const(o2, v & a[4]));
358 o(stuff_const(o2,v&a[12]));361 o(stuff_const(o2, v & a[8]));
359 }362 o(stuff_const(o2, v & a[12]));
363 }
360}364}
361 365
362ST_FUNC uint32_t encbranch(int pos, int addr, int fail)366ST_FUNC uint32_t encbranch(int pos, int addr, int fail)
363{367{
364 addr-=pos+8;368 addr -= pos + 8;
365 addr/=4;369 addr /= 4;
366 if(addr>=0x1000000 || addr<-0x1000000) {370 if (addr >= 0x1000000 || addr < -0x1000000) {
367 if(fail)371 if (fail)
368 tcc_error("FIXME: function bigger than 32MB");372 tcc_error("FIXME: function bigger than 32MB");
369 return 0;373 return 0;
370 }374 }
371 return 0x0A000000|(addr&0xffffff);375 return 0x0A000000 | (addr & 0xffffff);
372}376}
373 377
374int decbranch(int pos)378int decbranch(int pos)
375{379{
376 int x;380 int x;
377 x=*(uint32_t *)(cur_text_section->data + pos);381 x = *(uint32_t*)(cur_text_section->data + pos);
378 x&=0x00ffffff;382 x &= 0x00ffffff;
379 if(x&0x800000)383 if (x & 0x800000)
380 x-=0x1000000;384 x -= 0x1000000;
381 return x*4+pos+8;385 return x * 4 + pos + 8;
382}386}
383 387
384/* output a symbol and patch all calls to it */388/* output a symbol and patch all calls to it */
385void gsym_addr(int t, int a)389void gsym_addr(int t, int a)
386{390{
387 uint32_t *x;391 uint32_t* x;
388 int lt;392 int lt;
389 while(t) {393 while (t) {
390 x=(uint32_t *)(cur_text_section->data + t);394 x = (uint32_t*)(cur_text_section->data + t);
391 t=decbranch(lt=t);395 t = decbranch(lt = t);
392 if(a==lt+4)396 if (a == lt + 4)
393 *x=0xE1A00000; // nop397 *x = 0xE1A00000; // nop
394 else {398 else {
395 *x &= 0xff000000;399 *x &= 0xff000000;
396 *x |= encbranch(lt,a,1);400 *x |= encbranch(lt, a, 1);
401 }
397 }402 }
398 }
399}403}
400 404
401void gsym(int t)405void gsym(int t)
402{406{
403 gsym_addr(t, ind);407 gsym_addr(t, ind);
404}408}
405 409
406#ifdef TCC_ARM_VFP410#ifdef TCC_ARM_VFP
407static uint32_t vfpr(int r)411static uint32_t vfpr(int r)
408{412{
409 if(r<TREG_F0 || r>TREG_F7)413 if (r < TREG_F0 || r > TREG_F7)
410 tcc_error("compiler error! register %i is no vfp register",r);414 tcc_error("compiler error! register %i is no vfp register", r);
411 return r-5;415 return r - 5;
412}416}
413#else417#else
414static uint32_t fpr(int r)418static uint32_t fpr(int r)
415{419{
416 if(r<TREG_F0 || r>TREG_F3)420 if (r < TREG_F0 || r > TREG_F3)
417 tcc_error("compiler error! register %i is no fpa register",r);421 tcc_error("compiler error! register %i is no fpa register", r);
418 return r-5;422 return r - 5;
419}423}
420#endif424#endif
421 425
422static uint32_t intr(int r)426static uint32_t intr(int r)
423{427{
424 if(r==4)428 if (r == 4)
425 return 12;429 return 12;
426 if((r<0 || r>4) && r!=14)430 if ((r < 0 || r > 4) && r != 14)
427 tcc_error("compiler error! register %i is no int register",r);431 tcc_error("compiler error! register %i is no int register", r);
428 return r;432 return r;
429}433}
430 434
431static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift)435static void calcaddr(uint32_t* base, int* off, int* sgn, int maxoff,
436 unsigned shift)
432{437{
433 if(*off>maxoff || *off&((1<<shift)-1)) {438 if (*off > maxoff || *off & ((1 << shift) - 1)) {
434 uint32_t x, y;439 uint32_t x, y;
435 x=0xE280E000;440 x = 0xE280E000;
436 if(*sgn)441 if (*sgn)
437 x=0xE240E000;442 x = 0xE240E000;
438 x|=(*base)<<16;443 x |= (*base) << 16;
439 *base=14; // lr444 *base = 14; // lr
440 y=stuff_const(x,*off&~maxoff);445 y = stuff_const(x, *off & ~maxoff);
441 if(y) {446 if (y) {
442 o(y);447 o(y);
443 *off&=maxoff;448 *off &= maxoff;
444 return;449 return;
445 }450 }
446 y=stuff_const(x,(*off+maxoff)&~maxoff);451 y = stuff_const(x, (*off + maxoff) & ~maxoff);
447 if(y) {452 if (y) {
448 o(y);453 o(y);
449 *sgn=!*sgn;454 *sgn = !*sgn;
450 *off=((*off+maxoff)&~maxoff)-*off;455 *off = ((*off + maxoff) & ~maxoff) - *off;
451 return;456 return;
457 }
458 stuff_const_harder(x, *off & ~maxoff);
459 *off &= maxoff;
452 }460 }
453 stuff_const_harder(x,*off&~maxoff);
454 *off&=maxoff;
455 }
456}461}
457 462
458static uint32_t mapcc(int cc)463static uint32_t mapcc(int cc)
459{464{
460 switch(cc)465 switch (cc) {
461 {
462 case TOK_ULT:466 case TOK_ULT:
463 return 0x30000000; /* CC/LO */467 return 0x30000000; /* CC/LO */
464 case TOK_UGE:468 case TOK_UGE:
465 return 0x20000000; /* CS/HS */469 return 0x20000000; /* CS/HS */
466 case TOK_EQ:470 case TOK_EQ:
467 return 0x00000000; /* EQ */471 return 0x00000000; /* EQ */
468 case TOK_NE:472 case TOK_NE:
469 return 0x10000000; /* NE */473 return 0x10000000; /* NE */
470 case TOK_ULE:474 case TOK_ULE:
471 return 0x90000000; /* LS */475 return 0x90000000; /* LS */
472 case TOK_UGT:476 case TOK_UGT:
473 return 0x80000000; /* HI */477 return 0x80000000; /* HI */
474 case TOK_Nset:478 case TOK_Nset:
475 return 0x40000000; /* MI */479 return 0x40000000; /* MI */
476 case TOK_Nclear:480 case TOK_Nclear:
477 return 0x50000000; /* PL */481 return 0x50000000; /* PL */
478 case TOK_LT:482 case TOK_LT:
479 return 0xB0000000; /* LT */483 return 0xB0000000; /* LT */
480 case TOK_GE:484 case TOK_GE:
481 return 0xA0000000; /* GE */485 return 0xA0000000; /* GE */
482 case TOK_LE:486 case TOK_LE:
483 return 0xD0000000; /* LE */487 return 0xD0000000; /* LE */
484 case TOK_GT:488 case TOK_GT:
485 return 0xC0000000; /* GT */489 return 0xC0000000; /* GT */
486 }490 }
487 tcc_error("unexpected condition code");491 tcc_error("unexpected condition code");
488 return 0xE0000000; /* AL */492 return 0xE0000000; /* AL */
489}493}
490 494
491static int negcc(int cc)495static int negcc(int cc)
492{496{
493 switch(cc)497 switch (cc) {
494 {
495 case TOK_ULT:498 case TOK_ULT:
496 return TOK_UGE;499 return TOK_UGE;
497 case TOK_UGE:500 case TOK_UGE:
498 return TOK_ULT;501 return TOK_ULT;
499 case TOK_EQ:502 case TOK_EQ:
500 return TOK_NE;503 return TOK_NE;
501 case TOK_NE:504 case TOK_NE:
502 return TOK_EQ;505 return TOK_EQ;
503 case TOK_ULE:506 case TOK_ULE:
504 return TOK_UGT;507 return TOK_UGT;
505 case TOK_UGT:508 case TOK_UGT:
506 return TOK_ULE;509 return TOK_ULE;
507 case TOK_Nset:510 case TOK_Nset:
508 return TOK_Nclear;511 return TOK_Nclear;
509 case TOK_Nclear:512 case TOK_Nclear:
510 return TOK_Nset;513 return TOK_Nset;
511 case TOK_LT:514 case TOK_LT:
512 return TOK_GE;515 return TOK_GE;
513 case TOK_GE:516 case TOK_GE:
514 return TOK_LT;517 return TOK_LT;
515 case TOK_LE:518 case TOK_LE:
516 return TOK_GT;519 return TOK_GT;
517 case TOK_GT:520 case TOK_GT:
518 return TOK_LE;521 return TOK_LE;
519 }522 }
520 tcc_error("unexpected condition code");523 tcc_error("unexpected condition code");
521 return TOK_NE;524 return TOK_NE;
522}525}
523 526
524/* load 'r' from value 'sv' */527/* load 'r' from value 'sv' */
525void load(int r, SValue *sv)528void load(int r, SValue* sv)
526{529{
527 int v, ft, fc, fr, sign;530 int v, ft, fc, fr, sign;
528 uint32_t op;531 uint32_t op;
529 SValue v1;532 SValue v1;
530 533
531 fr = sv->r;534 fr = sv->r;
532 ft = sv->type.t;535 ft = sv->type.t;
533 fc = sv->c.ul;536 fc = sv->c.ul;
534 537
535 if(fc>=0)538 if (fc >= 0)
536 sign=0;539 sign = 0;
537 else {540 else {
538 sign=1;541 sign = 1;
539 fc=-fc;542 fc = -fc;
540 }
541
542 v = fr & VT_VALMASK;
543 if (fr & VT_LVAL) {
544 uint32_t base = 0xB; // fp
545 if(v == VT_LLOCAL) {
546 v1.type.t = VT_PTR;
547 v1.r = VT_LOCAL | VT_LVAL;
548 v1.c.ul = sv->c.ul;
549 load(base=14 /* lr */, &v1);
550 fc=sign=0;
551 v=VT_LOCAL;
552 } else if(v == VT_CONST) {
553 v1.type.t = VT_PTR;
554 v1.r = fr&~VT_LVAL;
555 v1.c.ul = sv->c.ul;
556 v1.sym=sv->sym;
557 load(base=14, &v1);
558 fc=sign=0;
559 v=VT_LOCAL;
560 } else if(v < VT_CONST) {
561 base=intr(v);
562 fc=sign=0;
563 v=VT_LOCAL;
564 }543 }
565 if(v == VT_LOCAL) {544
566 if(is_float(ft)) {545 v = fr & VT_VALMASK;
567 calcaddr(&base,&fc,&sign,1020,2);546 if (fr & VT_LVAL) {
547 uint32_t base = 0xB; // fp
548 if (v == VT_LLOCAL) {
549 v1.type.t = VT_PTR;
550 v1.r = VT_LOCAL | VT_LVAL;
551 v1.c.ul = sv->c.ul;
552 load(base = 14 /* lr */, &v1);
553 fc = sign = 0;
554 v = VT_LOCAL;
555 } else if (v == VT_CONST) {
556 v1.type.t = VT_PTR;
557 v1.r = fr & ~VT_LVAL;
558 v1.c.ul = sv->c.ul;
559 v1.sym = sv->sym;
560 load(base = 14, &v1);
561 fc = sign = 0;
562 v = VT_LOCAL;
563 } else if (v < VT_CONST) {
564 base = intr(v);
565 fc = sign = 0;
566 v = VT_LOCAL;
567 }
568 if (v == VT_LOCAL) {
569 if (is_float(ft)) {
570 calcaddr(&base, &fc, &sign, 1020, 2);
568#ifdef TCC_ARM_VFP571#ifdef TCC_ARM_VFP
569 op=0xED100A00; /* flds */572 op = 0xED100A00; /* flds */
570 if(!sign)573 if (!sign)
571 op|=0x800000;574 op |= 0x800000;
572 if ((ft & VT_BTYPE) != VT_FLOAT)575 if ((ft & VT_BTYPE) != VT_FLOAT)
573 op|=0x100; /* flds -> fldd */576 op |= 0x100; /* flds -> fldd */
574 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));577 o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16));
575#else578#else
576 op=0xED100100;579 op = 0xED100100;
577 if(!sign)580 if (!sign)
578 op|=0x800000;581 op |= 0x800000;
579#if LDOUBLE_SIZE == 8582#if LDOUBLE_SIZE == 8
580 if ((ft & VT_BTYPE) != VT_FLOAT)583 if ((ft & VT_BTYPE) != VT_FLOAT)
581 op|=0x8000;584 op |= 0x8000;
582#else585#else
583 if ((ft & VT_BTYPE) == VT_DOUBLE)586 if ((ft & VT_BTYPE) == VT_DOUBLE)
584 op|=0x8000;587 op |= 0x8000;
585 else if ((ft & VT_BTYPE) == VT_LDOUBLE)588 else if ((ft & VT_BTYPE) == VT_LDOUBLE)
586 op|=0x400000;589 op |= 0x400000;
587#endif590#endif
588 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));591 o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16));
589#endif592#endif
590 } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE593 } else if ((ft & (VT_BTYPE | VT_UNSIGNED)) == VT_BYTE ||
591 || (ft & VT_BTYPE) == VT_SHORT) {594 (ft & VT_BTYPE) == VT_SHORT) {
592 calcaddr(&base,&fc,&sign,255,0);595 calcaddr(&base, &fc, &sign, 255, 0);
593 op=0xE1500090;596 op = 0xE1500090;
594 if ((ft & VT_BTYPE) == VT_SHORT)597 if ((ft & VT_BTYPE) == VT_SHORT)
595 op|=0x20;598 op |= 0x20;
596 if ((ft & VT_UNSIGNED) == 0)599 if ((ft & VT_UNSIGNED) == 0)
597 op|=0x40;600 op |= 0x40;
598 if(!sign)601 if (!sign)
599 op|=0x800000;602 op |= 0x800000;
600 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));603 o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) |
601 } else {604 (fc & 0xf));
602 calcaddr(&base,&fc,&sign,4095,0);605 } else {
603 op=0xE5100000;606 calcaddr(&base, &fc, &sign, 4095, 0);
604 if(!sign)607 op = 0xE5100000;
605 op|=0x800000;608 if (!sign)
606 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)609 op |= 0x800000;
607 op|=0x400000;610 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
608 o(op|(intr(r)<<12)|fc|(base<<16));611 op |= 0x400000;
609 }612 o(op | (intr(r) << 12) | fc | (base << 16));
610 return;613 }
611 }614 return;
612 } else {615 }
613 if (v == VT_CONST) {616 } else {
614 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul);617 if (v == VT_CONST) {
615 if (fr & VT_SYM || !op) {618 op = stuff_const(0xE3A00000 | (intr(r) << 12), sv->c.ul);
616 o(0xE59F0000|(intr(r)<<12));619 if (fr & VT_SYM || !op) {
617 o(0xEA000000);620 o(0xE59F0000 | (intr(r) << 12));
618 if(fr & VT_SYM)621 o(0xEA000000);
619 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);622 if (fr & VT_SYM)
620 o(sv->c.ul);623 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
621 } else624 o(sv->c.ul);
622 o(op);625 } else
623 return;626 o(op);
624 } else if (v == VT_LOCAL) {627 return;
625 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul);628 } else if (v == VT_LOCAL) {
626 if (fr & VT_SYM || !op) {629 op = stuff_const(0xE28B0000 | (intr(r) << 12), sv->c.ul);
627 o(0xE59F0000|(intr(r)<<12));630 if (fr & VT_SYM || !op) {
628 o(0xEA000000);631 o(0xE59F0000 | (intr(r) << 12));
629 if(fr & VT_SYM) // needed ?632 o(0xEA000000);
630 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);633 if (fr & VT_SYM) // needed ?
631 o(sv->c.ul);634 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
632 o(0xE08B0000|(intr(r)<<12)|intr(r));635 o(sv->c.ul);
633 } else636 o(0xE08B0000 | (intr(r) << 12) | intr(r));
634 o(op);637 } else
635 return;638 o(op);
636 } else if(v == VT_CMP) {639 return;
637 o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12));640 } else if (v == VT_CMP) {
638 o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12));641 o(mapcc(sv->c.ul) | 0x3A00001 | (intr(r) << 12));
639 return;642 o(mapcc(negcc(sv->c.ul)) | 0x3A00000 | (intr(r) << 12));
640 } else if (v == VT_JMP || v == VT_JMPI) {643 return;
641 int t;644 } else if (v == VT_JMP || v == VT_JMPI) {
642 t = v & 1;645 int t;
643 o(0xE3A00000|(intr(r)<<12)|t);646 t = v & 1;
644 o(0xEA000000);647 o(0xE3A00000 | (intr(r) << 12) | t);
645 gsym(sv->c.ul);648 o(0xEA000000);
646 o(0xE3A00000|(intr(r)<<12)|(t^1));649 gsym(sv->c.ul);
647 return;650 o(0xE3A00000 | (intr(r) << 12) | (t ^ 1));
648 } else if (v < VT_CONST) {651 return;
649 if(is_float(ft))652 } else if (v < VT_CONST) {
653 if (is_float(ft))
650#ifdef TCC_ARM_VFP654#ifdef TCC_ARM_VFP
651 o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */655 o(0xEEB00A40 | (vfpr(r) << 12) | vfpr(v) |
656 T2CPR(ft)); /* fcpyX */
652#else657#else
653 o(0xEE008180|(fpr(r)<<12)|fpr(v));658 o(0xEE008180 | (fpr(r) << 12) | fpr(v));
654#endif659#endif
655 else660 else
656 o(0xE1A00000|(intr(r)<<12)|intr(v));661 o(0xE1A00000 | (intr(r) << 12) | intr(v));
657 return;662 return;
663 }
658 }664 }
659 }665 tcc_error("load unimplemented!");
660 tcc_error("load unimplemented!");
661}666}
662 667
663/* store register 'r' in lvalue 'v' */668/* store register 'r' in lvalue 'v' */
664void store(int r, SValue *sv)669void store(int r, SValue* sv)
665{670{
666 SValue v1;671 SValue v1;
667 int v, ft, fc, fr, sign;672 int v, ft, fc, fr, sign;
668 uint32_t op;673 uint32_t op;
669 674
670 fr = sv->r;675 fr = sv->r;
671 ft = sv->type.t;676 ft = sv->type.t;
672 fc = sv->c.ul;677 fc = sv->c.ul;
673 678
674 if(fc>=0)679 if (fc >= 0)
675 sign=0;680 sign = 0;
676 else {681 else {
677 sign=1;682 sign = 1;
678 fc=-fc;683 fc = -fc;
679 }
680
681 v = fr & VT_VALMASK;
682 if (fr & VT_LVAL || fr == VT_LOCAL) {
683 uint32_t base = 0xb;
684 if(v < VT_CONST) {
685 base=intr(v);
686 v=VT_LOCAL;
687 fc=sign=0;
688 } else if(v == VT_CONST) {
689 v1.type.t = ft;
690 v1.r = fr&~VT_LVAL;
691 v1.c.ul = sv->c.ul;
692 v1.sym=sv->sym;
693 load(base=14, &v1);
694 fc=sign=0;
695 v=VT_LOCAL;
696 }684 }
697 if(v == VT_LOCAL) {685
698 if(is_float(ft)) {686 v = fr & VT_VALMASK;
699 calcaddr(&base,&fc,&sign,1020,2);687 if (fr & VT_LVAL || fr == VT_LOCAL) {
688 uint32_t base = 0xb;
689 if (v < VT_CONST) {
690 base = intr(v);
691 v = VT_LOCAL;
692 fc = sign = 0;
693 } else if (v == VT_CONST) {
694 v1.type.t = ft;
695 v1.r = fr & ~VT_LVAL;
696 v1.c.ul = sv->c.ul;
697 v1.sym = sv->sym;
698 load(base = 14, &v1);
699 fc = sign = 0;
700 v = VT_LOCAL;
701 }
702 if (v == VT_LOCAL) {
703 if (is_float(ft)) {
704 calcaddr(&base, &fc, &sign, 1020, 2);
700#ifdef TCC_ARM_VFP705#ifdef TCC_ARM_VFP
701 op=0xED000A00; /* fsts */706 op = 0xED000A00; /* fsts */
702 if(!sign)707 if (!sign)
703 op|=0x800000;708 op |= 0x800000;
704 if ((ft & VT_BTYPE) != VT_FLOAT)709 if ((ft & VT_BTYPE) != VT_FLOAT)
705 op|=0x100; /* fsts -> fstd */710 op |= 0x100; /* fsts -> fstd */
706 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));711 o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16));
707#else712#else
708 op=0xED000100;713 op = 0xED000100;
709 if(!sign)714 if (!sign)
710 op|=0x800000;715 op |= 0x800000;
711#if LDOUBLE_SIZE == 8716#if LDOUBLE_SIZE == 8
712 if ((ft & VT_BTYPE) != VT_FLOAT)717 if ((ft & VT_BTYPE) != VT_FLOAT)
713 op|=0x8000;718 op |= 0x8000;
714#else719#else
715 if ((ft & VT_BTYPE) == VT_DOUBLE)720 if ((ft & VT_BTYPE) == VT_DOUBLE)
716 op|=0x8000;721 op |= 0x8000;
717 if ((ft & VT_BTYPE) == VT_LDOUBLE)722 if ((ft & VT_BTYPE) == VT_LDOUBLE)
718 op|=0x400000;723 op |= 0x400000;
719#endif724#endif
720 o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));725 o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16));
721#endif726#endif
722 return;727 return;
723 } else if((ft & VT_BTYPE) == VT_SHORT) {728 } else if ((ft & VT_BTYPE) == VT_SHORT) {
724 calcaddr(&base,&fc,&sign,255,0);729 calcaddr(&base, &fc, &sign, 255, 0);
725 op=0xE14000B0;730 op = 0xE14000B0;
726 if(!sign)731 if (!sign)
727 op|=0x800000;732 op |= 0x800000;
728 o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf));733 o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) |
729 } else {734 (fc & 0xf));
730 calcaddr(&base,&fc,&sign,4095,0);735 } else {
731 op=0xE5000000;736 calcaddr(&base, &fc, &sign, 4095, 0);
732 if(!sign)737 op = 0xE5000000;
733 op|=0x800000;738 if (!sign)
734 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)739 op |= 0x800000;
735 op|=0x400000;740 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL)
736 o(op|(intr(r)<<12)|fc|(base<<16));741 op |= 0x400000;
737 }742 o(op | (intr(r) << 12) | fc | (base << 16));
738 return;743 }
744 return;
745 }
739 }746 }
740 }747 tcc_error("store unimplemented");
741 tcc_error("store unimplemented");
742}748}
743 749
744static void gadd_sp(int val)750static void gadd_sp(int val)
745{751{
746 stuff_const_harder(0xE28DD000,val);752 stuff_const_harder(0xE28DD000, val);
747}753}
748 754
749/* 'is_jmp' is '1' if it is a jump */755/* 'is_jmp' is '1' if it is a jump */
750static void gcall_or_jmp(int is_jmp)756static void gcall_or_jmp(int is_jmp)
751{757{
752 int r;758 int r;
753 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {759 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
754 uint32_t x;760 uint32_t x;
755 /* constant case */761 /* constant case */
756 x=encbranch(ind,ind+vtop->c.ul,0);762 x = encbranch(ind, ind + vtop->c.ul, 0);
757 if(x) {763 if (x) {
758 if (vtop->r & VT_SYM) {764 if (vtop->r & VT_SYM) {
759 /* relocation case */765 /* relocation case */
760 greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);766 greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
761 } else767 } else
762 put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);768 put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24,
763 o(x|(is_jmp?0xE0000000:0xE1000000));769 0);
770 o(x | (is_jmp ? 0xE0000000 : 0xE1000000));
771 } else {
772 if (!is_jmp)
773 o(0xE28FE004); // add lr,pc,#4
774 o(0xE51FF004); // ldr pc,[pc,#-4]
775 if (vtop->r & VT_SYM)
776 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
777 o(vtop->c.ul);
778 }
764 } else {779 } else {
765 if(!is_jmp)780 /* otherwise, indirect call */
766 o(0xE28FE004); // add lr,pc,#4781 r = gv(RC_INT);
767 o(0xE51FF004); // ldr pc,[pc,#-4]782 if (!is_jmp)
768 if (vtop->r & VT_SYM)783 o(0xE1A0E00F); // mov lr,pc
769 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);784 o(0xE1A0F000 | intr(r)); // mov pc,r
770 o(vtop->c.ul);
771 }785 }
772 } else {
773 /* otherwise, indirect call */
774 r = gv(RC_INT);
775 if(!is_jmp)
776 o(0xE1A0E00F); // mov lr,pc
777 o(0xE1A0F000|intr(r)); // mov pc,r
778 }
779}786}
780 787
781/* Return whether a structure is an homogeneous float aggregate or not.788/* Return whether a structure is an homogeneous float aggregate or not.
@@ -783,27 +790,30 @@ static void gcall_or_jmp(int is_jmp) · 1 unmodified line
783 primitive float type and there is less than 4 elements.790 primitive float type and there is less than 4 elements.
784 791
785 type: the type corresponding to the structure to be tested */792 type: the type corresponding to the structure to be tested */
786static int is_hgen_float_aggr(CType *type)793static int is_hgen_float_aggr(CType* type)
787{794{
788 if ((type->t & VT_BTYPE) == VT_STRUCT) {795 if ((type->t & VT_BTYPE) == VT_STRUCT) {
789 struct Sym *ref;796 struct Sym* ref;
790 int btype, nb_fields = 0;797 int btype, nb_fields = 0;
791 798
792 ref = type->ref->next;799 ref = type->ref->next;
793 btype = ref->type.t & VT_BTYPE;800 btype = ref->type.t & VT_BTYPE;
794 if (btype == VT_FLOAT || btype == VT_DOUBLE) {801 if (btype == VT_FLOAT || btype == VT_DOUBLE) {
795 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);802 for (; ref && btype == (ref->type.t & VT_BTYPE);
796 return !ref && nb_fields <= 4;803 ref = ref->next, nb_fields++)
804 ;
805 return !ref && nb_fields <= 4;
806 }
797 }807 }
798 }808 return 0;
799 return 0;
800}809}
801 810
802struct avail_regs {811struct avail_regs {
803 signed char avail[3]; /* 3 holes max with only float and double alignments */812 signed char
804 int first_hole; /* first available hole */813 avail[3]; /* 3 holes max with only float and double alignments */
805 int last_hole; /* last available hole (none if equal to first_hole) */814 int first_hole; /* first available hole */
806 int first_free_reg; /* next free register in the sequence, hole excluded */815 int last_hole; /* last available hole (none if equal to first_hole) */
816 int first_free_reg; /* next free register in the sequence, hole excluded */
807};817};
808 818
809#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }819#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
@@ -817,40 +827,40 @@ struct avail_regs { · 7 unmodified lines
817 avregs: opaque structure to keep track of available VFP co-processor regs827 avregs: opaque structure to keep track of available VFP co-processor regs
818 align: alignment contraints for the param, as returned by type_size()828 align: alignment contraints for the param, as returned by type_size()
819 size: size of the parameter, as returned by type_size() */829 size: size of the parameter, as returned by type_size() */
820int assign_vfpreg(struct avail_regs *avregs, int align, int size)830int assign_vfpreg(struct avail_regs* avregs, int align, int size)
821{831{
822 int first_reg = 0;832 int first_reg = 0;
823 833
824 if (avregs->first_free_reg == -1)834 if (avregs->first_free_reg == -1)
835 return -1;
836 if (align >> 3) { /* double alignment */
837 first_reg = avregs->first_free_reg;
838 /* alignment contraint not respected so use next reg and record hole */
839 if (first_reg & 1)
840 avregs->avail[avregs->last_hole++] = first_reg++;
841 } else { /* no special alignment (float or array of float) */
842 /* if single float and a hole is available, assign the param to it */
843 if (size == 4 && avregs->first_hole != avregs->last_hole)
844 return avregs->avail[avregs->first_hole++];
845 else
846 first_reg = avregs->first_free_reg;
847 }
848 if (first_reg + size / 4 <= 16) {
849 avregs->first_free_reg = first_reg + size / 4;
850 return first_reg;
851 }
852 avregs->first_free_reg = -1;
825 return -1;853 return -1;
826 if (align >> 3) { /* double alignment */
827 first_reg = avregs->first_free_reg;
828 /* alignment contraint not respected so use next reg and record hole */
829 if (first_reg & 1)
830 avregs->avail[avregs->last_hole++] = first_reg++;
831 } else { /* no special alignment (float or array of float) */
832 /* if single float and a hole is available, assign the param to it */
833 if (size == 4 && avregs->first_hole != avregs->last_hole)
834 return avregs->avail[avregs->first_hole++];
835 else
836 first_reg = avregs->first_free_reg;
837 }
838 if (first_reg + size / 4 <= 16) {
839 avregs->first_free_reg = first_reg + size / 4;
840 return first_reg;
841 }
842 avregs->first_free_reg = -1;
843 return -1;
844}854}
845 855
846/* Returns whether all params need to be passed in core registers or not.856/* Returns whether all params need to be passed in core registers or not.
847 This is the case for function part of the runtime ABI. */857 This is the case for function part of the runtime ABI. */
848int floats_in_core_regs(SValue *sval)858int floats_in_core_regs(SValue* sval)
849{859{
850 if (!sval->sym)860 if (!sval->sym)
851 return 0;861 return 0;
852 862
853 switch (sval->sym->v) {863 switch (sval->sym->v) {
854 case TOK___floatundisf:864 case TOK___floatundisf:
855 case TOK___floatundidf:865 case TOK___floatundidf:
856 case TOK___fixunssfdi:866 case TOK___fixunssfdi:
@@ -862,34 +872,36 @@ int floats_in_core_regs(SValue *sval) · 5 unmodified lines
862 case TOK___floatdidf:872 case TOK___floatdidf:
863 case TOK___fixsfdi:873 case TOK___fixsfdi:
864 case TOK___fixdfdi:874 case TOK___fixdfdi:
865 return 1;875 return 1;
866 876
867 default:877 default:
868 return 0;878 return 0;
869 }879 }
870}880}
871 881
872ST_FUNC int regargs_nregs(RegArgs *args)882ST_FUNC int regargs_nregs(RegArgs* args)
873{883{
874 return *args;884 return *args;
875}885}
876 886
877/* Return the number of registers needed to return the struct, or 0 if887/* Return the number of registers needed to return the struct, or 0 if
878 returning via struct pointer. */888 returning via struct pointer. */
879ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize, RegArgs *args) {889ST_FUNC int gfunc_sret(CType* vt, int variadic, CType* ret, int* ret_align,
890 int* regsize, RegArgs* args)
891{
880#ifdef TCC_ARM_EABI892#ifdef TCC_ARM_EABI
881 int size, align;893 int size, align;
882 size = type_size(vt, &align);894 size = type_size(vt, &align);
883 if (float_abi == ARM_HARD_FLOAT && !variadic &&895 if (float_abi == ARM_HARD_FLOAT && !variadic &&
884 (is_float(vt->t) || is_hgen_float_aggr(vt))) {896 (is_float(vt->t) || is_hgen_float_aggr(vt))) {
885 *ret_align = 8;897 *ret_align = 8;
886 *regsize = 8;898 *regsize = 8;
887 ret->ref = NULL;899 ret->ref = NULL;
888 ret->t = VT_DOUBLE;900 ret->t = VT_DOUBLE;
889 *args = (size + 7) >> 3;901 *args = (size + 7) >> 3;
890 } else if (size <= 4) {902 } else if (size <= 4) {
891 *ret_align = 4;903 *ret_align = 4;
892 *regsize = 4;904 *regsize = 4;
893 ret->ref = NULL;905 ret->ref = NULL;
894 ret->t = VT_INT;906 ret->t = VT_INT;
895 *args = 1;907 *args = 1;
@@ -912,32 +924,33 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int · 16 unmodified lines
912 - VFP_STRUCT_CLASS must come after VFP_CLASS.924 - VFP_STRUCT_CLASS must come after VFP_CLASS.
913 See the comment for the main loop in copy_params() for the reason. */925 See the comment for the main loop in copy_params() for the reason. */
914enum reg_class {926enum reg_class {
915 STACK_CLASS = 0,927 STACK_CLASS = 0,
916 CORE_STRUCT_CLASS,928 CORE_STRUCT_CLASS,
917 VFP_CLASS,929 VFP_CLASS,
918 VFP_STRUCT_CLASS,930 VFP_STRUCT_CLASS,
919 CORE_CLASS,931 CORE_CLASS,
920 NB_CLASSES932 NB_CLASSES
921};933};
922 934
923struct param_plan {935struct param_plan {
924 int start; /* first reg or addr used depending on the class */936 int start; /* first reg or addr used depending on the class */
925 int end; /* last reg used or next free addr depending on the class */937 int end; /* last reg used or next free addr depending on the class */
926 SValue *sval; /* pointer to SValue on the value stack */938 SValue* sval; /* pointer to SValue on the value stack */
927 struct param_plan *prev; /* previous element in this class */939 struct param_plan* prev; /* previous element in this class */
928};940};
929 941
930struct plan {942struct plan {
931 struct param_plan *pplans; /* array of all the param plans */943 struct param_plan* pplans; /* array of all the param plans */
932 struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */944 struct param_plan*
945 clsplans[NB_CLASSES]; /* per class lists of param plans */
933};946};
934 947
935#define add_param_plan(plan,pplan,class) \948#define add_param_plan(plan, pplan, class) \
936 do { \949 do { \
937 pplan.prev = plan->clsplans[class]; \950 pplan.prev = plan->clsplans[class]; \
938 plan->pplans[plan ## _nb] = pplan; \951 plan->pplans[plan##_nb] = pplan; \
939 plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \952 plan->clsplans[class] = &plan->pplans[plan##_nb++]; \
940 } while(0)953 } while (0)
941 954
942/* Assign parameters to registers and stack with alignment according to the955/* Assign parameters to registers and stack with alignment according to the
943 rules in the procedure call standard for the ARM architecture (AAPCS).956 rules in the procedure call standard for the ARM architecture (AAPCS).
@@ -956,90 +969,93 @@ struct plan { · 12 unmodified lines
956 Note: this function allocated an array in plan->pplans with tcc_malloc. It969 Note: this function allocated an array in plan->pplans with tcc_malloc. It
957 is the responsibility of the caller to free this array once used (ie not970 is the responsibility of the caller to free this array once used (ie not
958 before copy_params). */971 before copy_params). */
959static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)972static int assign_regs(int nb_args, int float_abi, struct plan* plan, int* todo)
960{973{
961 int i, size, align;974 int i, size, align;
962 int ncrn /* next core register number */, nsaa /* next stacked argument address*/;975 int ncrn /* next core register number */,
963 int plan_nb = 0;976 nsaa /* next stacked argument address*/;
964 struct param_plan pplan;977 int plan_nb = 0;
965 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;978 struct param_plan pplan;
966 979 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
967 ncrn = nsaa = 0;980
968 *todo = 0;981 ncrn = nsaa = 0;
969 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));982 *todo = 0;
970 memset(plan->clsplans, 0, sizeof(plan->clsplans));983 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
971 for(i = nb_args; i-- ;) {984 memset(plan->clsplans, 0, sizeof(plan->clsplans));
972 int j, start_vfpreg = 0;985 for (i = nb_args; i--;) {
973 CType type = vtop[-i].type;986 int j, start_vfpreg = 0;
974 type.t &= ~VT_ARRAY;987 CType type = vtop[-i].type;
975 size = type_size(&type, &align);988 type.t &= ~VT_ARRAY;
976 size = (size + 3) & ~3;989 size = type_size(&type, &align);
977 align = (align + 3) & ~3;990 size = (size + 3) & ~3;
978 switch(vtop[-i].type.t & VT_BTYPE) {991 align = (align + 3) & ~3;
979 case VT_STRUCT:992 switch (vtop[-i].type.t & VT_BTYPE) {
980 case VT_FLOAT:993 case VT_STRUCT:
981 case VT_DOUBLE:994 case VT_FLOAT:
982 case VT_LDOUBLE:995 case VT_DOUBLE:
983 if (float_abi == ARM_HARD_FLOAT) {996 case VT_LDOUBLE:
984 int is_hfa = 0; /* Homogeneous float aggregate */997 if (float_abi == ARM_HARD_FLOAT) {
985 998 int is_hfa = 0; /* Homogeneous float aggregate */
986 if (is_float(vtop[-i].type.t)999
987 || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {1000 if (is_float(vtop[-i].type.t) ||
988 int end_vfpreg;1001 (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) {
989 1002 int end_vfpreg;
990 start_vfpreg = assign_vfpreg(&avregs, align, size);1003
991 end_vfpreg = start_vfpreg + ((size - 1) >> 2);1004 start_vfpreg = assign_vfpreg(&avregs, align, size);
992 if (start_vfpreg >= 0) {1005 end_vfpreg = start_vfpreg + ((size - 1) >> 2);
993 pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};1006 if (start_vfpreg >= 0) {
994 if (is_hfa)1007 pplan = (struct param_plan){start_vfpreg, end_vfpreg,
995 add_param_plan(plan, pplan, VFP_STRUCT_CLASS);1008 &vtop[-i]};
996 else1009 if (is_hfa)
997 add_param_plan(plan, pplan, VFP_CLASS);1010 add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
1011 else
1012 add_param_plan(plan, pplan, VFP_CLASS);
1013 continue;
1014 } else
1015 break;
1016 }
1017 }
1018 ncrn = (ncrn + (align - 1) / 4) & ~((align / 4) - 1);
1019 if (ncrn + size / 4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) {
1020 /* The parameter is allocated both in core register and on
1021 * stack. As
1022 * such, it can be of either class: it would either be the last of
1023 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */
1024 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
1025 *todo |= (1 << j);
1026 pplan = (struct param_plan){ncrn, j, &vtop[-i]};
1027 add_param_plan(plan, pplan, CORE_STRUCT_CLASS);
1028 ncrn += size / 4;
1029 if (ncrn > 4)
1030 nsaa = (ncrn - 4) * 4;
1031 } else {
1032 ncrn = 4;
1033 break;
1034 }
998 continue;1035 continue;
999 } else1036 default:
1000 break;1037 if (ncrn < 4) {
1001 }1038 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
1002 }1039
1003 ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1);1040 if (is_long) {
1004 if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) {1041 ncrn = (ncrn + 1) & -2;
1005 /* The parameter is allocated both in core register and on stack. As1042 if (ncrn == 4)
1006 * such, it can be of either class: it would either be the last of1043 break;
1007 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */1044 }
1008 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)1045 pplan = (struct param_plan){ncrn, ncrn, &vtop[-i]};
1009 *todo|=(1<<j);1046 ncrn++;
1010 pplan = (struct param_plan) {ncrn, j, &vtop[-i]};1047 if (is_long)
1011 add_param_plan(plan, pplan, CORE_STRUCT_CLASS);1048 pplan.end = ncrn++;
1012 ncrn += size/4;1049 add_param_plan(plan, pplan, CORE_CLASS);
1013 if (ncrn > 4)1050 continue;
1014 nsaa = (ncrn - 4) * 4;1051 }
1015 } else {
1016 ncrn = 4;
1017 break;
1018 }
1019 continue;
1020 default:
1021 if (ncrn < 4) {
1022 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
1023
1024 if (is_long) {
1025 ncrn = (ncrn + 1) & -2;
1026 if (ncrn == 4)
1027 break;
1028 }1052 }
1029 pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]};1053 nsaa = (nsaa + (align - 1)) & ~(align - 1);
1030 ncrn++;1054 pplan = (struct param_plan){nsaa, nsaa + size, &vtop[-i]};
1031 if (is_long)1055 add_param_plan(plan, pplan, STACK_CLASS);
1032 pplan.end = ncrn++;1056 nsaa += size; /* size already rounded up before */
1033 add_param_plan(plan, pplan, CORE_CLASS);
1034 continue;
1035 }
1036 }1057 }
1037 nsaa = (nsaa + (align - 1)) & ~(align - 1);1058 return nsaa;
1038 pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]};
1039 add_param_plan(plan, pplan, STACK_CLASS);
1040 nsaa += size; /* size already rounded up before */
1041 }
1042 return nsaa;
1043}1059}
1044 1060
1045#undef add_param_plan1061#undef add_param_plan
@@ -1052,156 +1068,165 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) · 6 unmodified lines
1052 todo: a bitmap indicating what core reg will hold a parameter1068 todo: a bitmap indicating what core reg will hold a parameter
1053 1069
1054 Returns the number of SValue added by this function on the value stack */1070 Returns the number of SValue added by this function on the value stack */
1055static int copy_params(int nb_args, struct plan *plan, int todo)1071static int copy_params(int nb_args, struct plan* plan, int todo)
1056{1072{
1057 int size, align, r, i, nb_extra_sval = 0;1073 int size, align, r, i, nb_extra_sval = 0;
1058 struct param_plan *pplan;1074 struct param_plan* pplan;
1059 1075
1060 /* Several constraints require parameters to be copied in a specific order:1076 /* Several constraints require parameters to be copied in a specific order:
1061 - structures are copied to the stack before being loaded in a reg;1077 - structures are copied to the stack before being loaded in a reg;
1062 - floats loaded to an odd numbered VFP reg are first copied to the1078 - floats loaded to an odd numbered VFP reg are first copied to the
1063 preceding even numbered VFP reg and then moved to the next VFP reg.1079 preceding even numbered VFP reg and then moved to the next VFP reg.
1064 1080
1065 It is thus important that:1081 It is thus important that:
1066 - structures assigned to core regs must be copied after parameters1082 - structures assigned to core regs must be copied after parameters
1067 assigned to the stack but before structures assigned to VFP regs because1083 assigned to the stack but before structures assigned to VFP regs
1068 a structure can lie partly in core registers and partly on the stack;1084 because a structure can lie partly in core registers and partly on
1069 - parameters assigned to the stack and all structures be copied before1085 the stack;
1070 parameters assigned to a core reg since copying a parameter to the stack1086 - parameters assigned to the stack and all structures be copied before
1071 require using a core reg;1087 parameters assigned to a core reg since copying a parameter to the
1072 - parameters assigned to VFP regs be copied before structures assigned to1088 stack require using a core reg;
1073 VFP regs as the copy might use an even numbered VFP reg that already1089 - parameters assigned to VFP regs be copied before structures assigned to
1074 holds part of a structure. */1090 VFP regs as the copy might use an even numbered VFP reg that already
1075 for(i = 0; i < NB_CLASSES; i++) {1091 holds part of a structure. */
1076 for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {1092 for (i = 0; i < NB_CLASSES; i++) {
1077 vpushv(pplan->sval);1093 for (pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
1078 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */1094 vpushv(pplan->sval);
1079 switch(i) {1095 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
1080 case STACK_CLASS:1096 switch (i) {
1081 case CORE_STRUCT_CLASS:1097 case STACK_CLASS:
1082 case VFP_STRUCT_CLASS:1098 case CORE_STRUCT_CLASS:
1083 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {1099 case VFP_STRUCT_CLASS:
1084 int padding = 0;1100 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
1085 size = type_size(&pplan->sval->type, &align);1101 int padding = 0;
1086 /* align to stack align size */1102 size = type_size(&pplan->sval->type, &align);
1087 size = (size + 3) & ~3;1103 /* align to stack align size */
1088 if (i == STACK_CLASS && pplan->prev)1104 size = (size + 3) & ~3;
1089 padding = pplan->start - pplan->prev->end;1105 if (i == STACK_CLASS && pplan->prev)
1090 size += padding; /* Add padding if any */1106 padding = pplan->start - pplan->prev->end;
1091 /* allocate the necessary size on stack */1107 size += padding; /* Add padding if any */
1092 gadd_sp(-size);1108 /* allocate the necessary size on stack */
1093 /* generate structure store */1109 gadd_sp(-size);
1094 r = get_reg(RC_INT);1110 /* generate structure store */
1095 o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */1111 r = get_reg(RC_INT);
1096 vset(&vtop->type, r | VT_LVAL, 0);1112 o(0xE28D0000 | (intr(r) << 12) |
1097 vswap();1113 padding); /* add r, sp, padding */
1098 vstore(); /* memcpy to current sp + potential padding */1114 vset(&vtop->type, r | VT_LVAL, 0);
1099 1115 vswap();
1100 /* Homogeneous float aggregate are loaded to VFP registers1116 vstore(); /* memcpy to current sp + potential padding */
1101 immediately since there is no way of loading data in multiple1117
1102 non consecutive VFP registers as what is done for other1118 /* Homogeneous float aggregate are loaded to VFP registers
1103 structures (see the use of todo). */1119 immediately since there is no way of loading data in
1104 if (i == VFP_STRUCT_CLASS) {1120 multiple non consecutive VFP registers as what is done
1105 int first = pplan->start, nb = pplan->end - first + 1;1121 for other structures (see the use of todo). */
1106 /* vpop.32 {pplan->start, ..., pplan->end} */1122 if (i == VFP_STRUCT_CLASS) {
1107 o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);1123 int first = pplan->start, nb = pplan->end - first + 1;
1108 /* No need to write the register used to a SValue since VFP regs1124 /* vpop.32 {pplan->start, ..., pplan->end} */
1109 cannot be used for gcall_or_jmp */1125 o(0xECBD0A00 | (first & 1) << 22 | (first >> 1) << 12 |
1110 }1126 nb);
1111 } else {1127 /* No need to write the register used to a SValue since
1112 if (is_float(pplan->sval->type.t)) {1128 VFP regs cannot be used for gcall_or_jmp */
1129 }
1130 } else {
1131 if (is_float(pplan->sval->type.t)) {
1113#ifdef TCC_ARM_VFP1132#ifdef TCC_ARM_VFP
1114 r = vfpr(gv(RC_FLOAT)) << 12;1133 r = vfpr(gv(RC_FLOAT)) << 12;
1115 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)1134 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1116 size = 4;1135 size = 4;
1117 else {1136 else {
1118 size = 8;1137 size = 8;
1119 r |= 0x101; /* vpush.32 -> vpush.64 */1138 r |= 0x101; /* vpush.32 -> vpush.64 */
1120 }1139 }
1121 o(0xED2D0A01 + r); /* vpush */1140 o(0xED2D0A01 + r); /* vpush */
1122#else1141#else
1123 r = fpr(gv(RC_FLOAT)) << 12;1142 r = fpr(gv(RC_FLOAT)) << 12;
1124 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)1143 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
1125 size = 4;1144 size = 4;
1126 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)1145 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
1127 size = 8;1146 size = 8;
1128 else1147 else
1129 size = LDOUBLE_SIZE;1148 size = LDOUBLE_SIZE;
1130 1149
1131 if (size == 12)1150 if (size == 12)
1132 r |= 0x400000;1151 r |= 0x400000;
1133 else if(size == 8)1152 else if (size == 8)
1134 r|=0x8000;1153 r |= 0x8000;
1135 1154
1136 o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */1155 o(0xED2D0100 | r | (size >> 2)); /* some kind of vpush for FPA */
1137#endif1156#endif
1138 } else {1157 } else {
1139 /* simple type (currently always same size) */1158 /* simple type (currently always same size) */
1140 /* XXX: implicit cast ? */1159 /* XXX: implicit cast ? */
1141 size=4;1160 size = 4;
1142 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {1161 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1143 lexpand_nr();1162 lexpand_nr();
1144 size = 8;1163 size = 8;
1145 r = gv(RC_INT);1164 r = gv(RC_INT);
1146 o(0xE52D0004|(intr(r)<<12)); /* push r */1165 o(0xE52D0004 | (intr(r) << 12)); /* push r */
1147 vtop--;1166 vtop--;
1148 }1167 }
1149 r = gv(RC_INT);1168 r = gv(RC_INT);
1150 o(0xE52D0004|(intr(r)<<12)); /* push r */1169 o(0xE52D0004 | (intr(r) << 12)); /* push r */
1170 }
1171 if (i == STACK_CLASS && pplan->prev)
1172 gadd_sp(pplan->prev->end -
1173 pplan->start); /* Add padding if any */
1174 }
1175 break;
1176
1177 case VFP_CLASS:
1178 gv(regmask(TREG_F0 + (pplan->start >> 1)));
1179 if (pplan->start &
1180 1) { /* Must be in upper part of double register */
1181 o(0xEEF00A40 | ((pplan->start >> 1) << 12) |
1182 (pplan->start >> 1)); /* vmov.f32 s(n+1), sn */
1183 vtop->r =
1184 VT_CONST; /* avoid being saved on stack by gv for next
1185 float */
1186 }
1187 break;
1188
1189 case CORE_CLASS:
1190 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1191 lexpand_nr();
1192 gv(regmask(pplan->end));
1193 pplan->sval->r2 = vtop->r;
1194 vtop--;
1195 }
1196 gv(regmask(pplan->start));
1197 /* Mark register as used so that gcall_or_jmp use another one
1198 (regs >=4 are free as never used to pass parameters) */
1199 pplan->sval->r = vtop->r;
1200 break;
1151 }1201 }
1152 if (i == STACK_CLASS && pplan->prev)
1153 gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
1154 }
1155 break;
1156
1157 case VFP_CLASS:
1158 gv(regmask(TREG_F0 + (pplan->start >> 1)));
1159 if (pplan->start & 1) { /* Must be in upper part of double register */
1160 o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
1161 vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
1162 }
1163 break;
1164
1165 case CORE_CLASS:
1166 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
1167 lexpand_nr();
1168 gv(regmask(pplan->end));
1169 pplan->sval->r2 = vtop->r;
1170 vtop--;1202 vtop--;
1171 }1203 }
1172 gv(regmask(pplan->start));
1173 /* Mark register as used so that gcall_or_jmp use another one
1174 (regs >=4 are free as never used to pass parameters) */
1175 pplan->sval->r = vtop->r;
1176 break;
1177 }
1178 vtop--;
1179 }1204 }
1180 }1205
1181 1206 /* Manually free remaining registers since next parameters are loaded
1182 /* Manually free remaining registers since next parameters are loaded1207 * manually, without the help of gv(int). */
1183 * manually, without the help of gv(int). */1208 save_regs(nb_args);
1184 save_regs(nb_args);1209
1185 1210 if (todo) {
1186 if(todo) {1211 o(0xE8BD0000 | todo); /* pop {todo} */
1187 o(0xE8BD0000|todo); /* pop {todo} */1212 for (pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan;
1188 for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {1213 pplan = pplan->prev) {
1189 int r;1214 int r;
1190 pplan->sval->r = pplan->start;1215 pplan->sval->r = pplan->start;
1191 /* An SValue can only pin 2 registers at best (r and r2) but a structure1216 /* An SValue can only pin 2 registers at best (r and r2) but a
1192 can occupy more than 2 registers. Thus, we need to push on the value1217 structure can occupy more than 2 registers. Thus, we need to
1193 stack some fake parameter to have on SValue for each registers used1218 push on the value stack some fake parameter to have on SValue
1194 by a structure (r2 is not used). */1219 for each registers used by a structure (r2 is not used). */
1195 for (r = pplan->start + 1; r <= pplan->end; r++) {1220 for (r = pplan->start + 1; r <= pplan->end; r++) {
1196 if (todo & (1 << r)) {1221 if (todo & (1 << r)) {
1197 nb_extra_sval++;1222 nb_extra_sval++;
1198 vpushi(0);1223 vpushi(0);
1199 vtop->r = r;1224 vtop->r = r;
1225 }
1226 }
1200 }1227 }
1201 }
1202 }1228 }
1203 }1229 return nb_extra_sval;
1204 return nb_extra_sval;
1205}1230}
1206 1231
1207/* Generate function call. The function address is pushed first, then1232/* Generate function call. The function address is pushed first, then
@@ -1209,733 +1234,738 @@ static int copy_params(int nb_args, struct plan *plan, int todo) · 1 unmodified line
1209 parameters and the function address. */1234 parameters and the function address. */
1210void gfunc_call(int nb_args)1235void gfunc_call(int nb_args)
1211{1236{
1212 int r, args_size;1237 int r, args_size;
1213 int def_float_abi = float_abi;1238 int def_float_abi = float_abi;
1214 int todo;1239 int todo;
1215 struct plan plan;1240 struct plan plan;
1216 1241
1217#ifdef TCC_ARM_EABI1242#ifdef TCC_ARM_EABI
1218 int variadic;1243 int variadic;
1219 1244
1220 if (float_abi == ARM_HARD_FLOAT) {1245 if (float_abi == ARM_HARD_FLOAT) {
1221 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);1246 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
1222 if (variadic || floats_in_core_regs(&vtop[-nb_args]))1247 if (variadic || floats_in_core_regs(&vtop[-nb_args]))
1223 float_abi = ARM_SOFTFP_FLOAT;1248 float_abi = ARM_SOFTFP_FLOAT;
1224 }1249 }
1225#endif1250#endif
1226 /* cannot let cpu flags if other instruction are generated. Also avoid leaving1251 /* cannot let cpu flags if other instruction are generated. Also avoid
1227 VT_JMP anywhere except on the top of the stack because it would complicate1252 leaving VT_JMP anywhere except on the top of the stack because it
1228 the code generator. */1253 would complicate the code generator. */
1229 r = vtop->r & VT_VALMASK;1254 r = vtop->r & VT_VALMASK;
1230 if (r == VT_CMP || (r & ~1) == VT_JMP)1255 if (r == VT_CMP || (r & ~1) == VT_JMP)
1231 gv(RC_INT);1256 gv(RC_INT);
1232 1257
1233 args_size = assign_regs(nb_args, float_abi, &plan, &todo);1258 args_size = assign_regs(nb_args, float_abi, &plan, &todo);
1234 1259
1235#ifdef TCC_ARM_EABI1260#ifdef TCC_ARM_EABI
1236 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */1261 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
1237 args_size = (args_size + 7) & ~7;1262 args_size = (args_size + 7) & ~7;
1238 o(0xE24DD004); /* sub sp, sp, #4 */1263 o(0xE24DD004); /* sub sp, sp, #4 */
1239 }1264 }
1240#endif1265#endif
1241 1266
1242 nb_args += copy_params(nb_args, &plan, todo);1267 nb_args += copy_params(nb_args, &plan, todo);
1243 tcc_free(plan.pplans);1268 tcc_free(plan.pplans);
1244 1269
1245 /* Move fct SValue on top as required by gcall_or_jmp */1270 /* Move fct SValue on top as required by gcall_or_jmp */
1246 vrotb(nb_args + 1);1271 vrotb(nb_args + 1);
1247 gcall_or_jmp(0);1272 gcall_or_jmp(0);
1248 if (args_size)1273 if (args_size)
1249 gadd_sp(args_size); /* pop all parameters passed on the stack */1274 gadd_sp(args_size); /* pop all parameters passed on the stack */
1250#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)1275#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1251 if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {1276 if (float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
1252 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {1277 if ((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
1253 o(0xEE000A10); /*vmov s0, r0 */1278 o(0xEE000A10); /*vmov s0, r0 */
1254 } else {1279 } else {
1255 o(0xEE000B10); /* vmov.32 d0[0], r0 */1280 o(0xEE000B10); /* vmov.32 d0[0], r0 */
1256 o(0xEE201B10); /* vmov.32 d0[1], r1 */1281 o(0xEE201B10); /* vmov.32 d0[1], r1 */
1282 }
1257 }1283 }
1258 }
1259#endif1284#endif
1260 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */1285 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */
1261 leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */1286 leaffunc =
1262 float_abi = def_float_abi;1287 0; /* we are calling a function, so we aren't in a leaf function */
1288 float_abi = def_float_abi;
1263}1289}
1264 1290
1265/* generate function prolog of type 't' */1291/* generate function prolog of type 't' */
1266void gfunc_prolog(CType *func_type)1292void gfunc_prolog(CType* func_type)
1267{1293{
1268 Sym *sym,*sym2;1294 Sym* sym, *sym2;
1269 int n, nf, size, align, rs, struct_ret = 0;1295 int n, nf, size, align, rs, struct_ret = 0;
1270 int addr, pn, sn; /* pn=core, sn=stack */1296 int addr, pn, sn; /* pn=core, sn=stack */
1271 CType ret_type;1297 CType ret_type;
1272 RegArgs dummy;1298 RegArgs dummy;
1273 1299
1274#ifdef TCC_ARM_EABI1300#ifdef TCC_ARM_EABI
1275 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;1301 struct avail_regs avregs = AVAIL_REGS_INITIALIZER;
1276#endif1302#endif
1277 1303
1278 sym = func_type->ref;1304 sym = func_type->ref;
1279 func_vt = sym->type;1305 func_vt = sym->type;
1280 func_var = (func_type->ref->c == FUNC_ELLIPSIS);1306 func_var = (func_type->ref->c == FUNC_ELLIPSIS);
1281 1307
1282 n = nf = 0;1308 n = nf = 0;
1283 if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&1309 if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&
1284 !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy))1310 !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy)) {
1285 {1311 n++;
1286 n++;1312 struct_ret = 1;
1287 struct_ret = 1;1313 func_vc = 12; /* Offset from fp of the place to store the result */
1288 func_vc = 12; /* Offset from fp of the place to store the result */1314 }
1289 }1315 for (sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {
1290 for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) {1316 size = type_size(&sym2->type, &align);
1291 size = type_size(&sym2->type, &align);
1292#ifdef TCC_ARM_EABI1317#ifdef TCC_ARM_EABI
1293 if (float_abi == ARM_HARD_FLOAT && !func_var &&1318 if (float_abi == ARM_HARD_FLOAT && !func_var &&
1294 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {1319 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) {
1295 int tmpnf = assign_vfpreg(&avregs, align, size);1320 int tmpnf = assign_vfpreg(&avregs, align, size);
1296 tmpnf += (size + 3) / 4;1321 tmpnf += (size + 3) / 4;
1297 nf = (tmpnf > nf) ? tmpnf : nf;1322 nf = (tmpnf > nf) ? tmpnf : nf;
1298 } else1323 } else
1299#endif1324#endif
1300 if (n < 4)1325 if (n < 4)
1301 n += (size + 3) / 4;1326 n += (size + 3) / 4;
1302 }1327 }
1303 o(0xE1A0C00D); /* mov ip,sp */1328 o(0xE1A0C00D); /* mov ip,sp */
1304 if (func_var)1329 if (func_var)
1305 n=4;1330 n = 4;
1306 if (n) {1331 if (n) {
1307 if(n>4)1332 if (n > 4)
1308 n=4;1333 n = 4;
1309#ifdef TCC_ARM_EABI1334#ifdef TCC_ARM_EABI
1310 n=(n+1)&-2;1335 n = (n + 1) & -2;
1311#endif1336#endif
1312 o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */1337 o(0xE92D0000 | ((1 << n) - 1)); /* save r0-r4 on stack if needed */
1313 }1338 }
1314 if (nf) {1339 if (nf) {
1315 if (nf>16)1340 if (nf > 16)
1316 nf=16;1341 nf = 16;
1317 nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */1342 nf = (nf + 1) & -2; /* nf => HARDFLOAT => EABI */
1318 o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */1343 o(0xED2D0A00 | nf); /* save s0-s15 on stack if needed */
1319 }1344 }
1320 o(0xE92D5800); /* save fp, ip, lr */1345 o(0xE92D5800); /* save fp, ip, lr */
1321 o(0xE1A0B00D); /* mov fp, sp */1346 o(0xE1A0B00D); /* mov fp, sp */
1322 func_sub_sp_offset = ind;1347 func_sub_sp_offset = ind;
1323 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */1348 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */
1324 1349
1325#ifdef TCC_ARM_EABI1350#ifdef TCC_ARM_EABI
1326 if (float_abi == ARM_HARD_FLOAT) {1351 if (float_abi == ARM_HARD_FLOAT) {
1327 func_vc += nf * 4;1352 func_vc += nf * 4;
1328 avregs = AVAIL_REGS_INITIALIZER;1353 avregs = AVAIL_REGS_INITIALIZER;
1329 }1354 }
1330#endif1355#endif
1331 pn = struct_ret, sn = 0;1356 pn = struct_ret, sn = 0;
1332 while ((sym = sym->next)) {1357 while ((sym = sym->next)) {
1333 CType *type;1358 CType* type;
1334 type = &sym->type;1359 type = &sym->type;
1335 size = type_size(type, &align);1360 size = type_size(type, &align);
1336 size = (size + 3) >> 2;1361 size = (size + 3) >> 2;
1337 align = (align + 3) & ~3;1362 align = (align + 3) & ~3;
1338#ifdef TCC_ARM_EABI1363#ifdef TCC_ARM_EABI
1339 if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t)1364 if (float_abi == ARM_HARD_FLOAT && !func_var &&
1340 || is_hgen_float_aggr(&sym->type))) {1365 (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) {
1341 int fpn = assign_vfpreg(&avregs, align, size << 2);1366 int fpn = assign_vfpreg(&avregs, align, size << 2);
1342 if (fpn >= 0)1367 if (fpn >= 0)
1343 addr = fpn * 4;1368 addr = fpn * 4;
1344 else1369 else
1345 goto from_stack;1370 goto from_stack;
1346 } else1371 } else
1347#endif1372#endif
1348 if (pn < 4) {1373 if (pn < 4) {
1349#ifdef TCC_ARM_EABI1374#ifdef TCC_ARM_EABI
1350 pn = (pn + (align-1)/4) & -(align/4);1375 pn = (pn + (align - 1) / 4) & -(align / 4);
1351#endif1376#endif
1352 addr = (nf + pn) * 4;1377 addr = (nf + pn) * 4;
1353 pn += size;1378 pn += size;
1354 if (!sn && pn > 4)1379 if (!sn && pn > 4)
1355 sn = (pn - 4);1380 sn = (pn - 4);
1356 } else {1381 } else {
1357#ifdef TCC_ARM_EABI1382#ifdef TCC_ARM_EABI
1358from_stack:1383 from_stack:
1359 sn = (sn + (align-1)/4) & -(align/4);1384 sn = (sn + (align - 1) / 4) & -(align / 4);
1360#endif1385#endif
1361 addr = (n + nf + sn) * 4;1386 addr = (n + nf + sn) * 4;
1362 sn += size;1387 sn += size;
1388 }
1389 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),
1390 addr + 12);
1363 }1391 }
1364 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t),1392 last_itod_magic = 0;
1365 addr + 12);1393 leaffunc = 1;
1366 }1394 loc = 0;
1367 last_itod_magic=0;
1368 leaffunc = 1;
1369 loc = 0;
1370}1395}
1371 1396
1372/* generate function epilog */1397/* generate function epilog */
1373void gfunc_epilog(void)1398void gfunc_epilog(void)
1374{1399{
1375 uint32_t x;1400 uint32_t x;
1376 int diff;1401 int diff;
1377 /* Copy float return value to core register if base standard is used and1402/* Copy float return value to core register if base standard is used and
1378 float computation is made with VFP */1403 float computation is made with VFP */
1379#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)1404#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
1380 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {1405 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) {
1381 if((func_vt.t & VT_BTYPE) == VT_FLOAT)1406 if ((func_vt.t & VT_BTYPE) == VT_FLOAT)
1382 o(0xEE100A10); /* fmrs r0, s0 */1407 o(0xEE100A10); /* fmrs r0, s0 */
1383 else {1408 else {
1384 o(0xEE100B10); /* fmrdl r0, d0 */1409 o(0xEE100B10); /* fmrdl r0, d0 */
1385 o(0xEE301B10); /* fmrdh r1, d0 */1410 o(0xEE301B10); /* fmrdh r1, d0 */
1411 }
1386 }1412 }
1387 }
1388#endif1413#endif
1389 o(0xE89BA800); /* restore fp, sp, pc */1414 o(0xE89BA800); /* restore fp, sp, pc */
1390 diff = (-loc + 3) & -4;1415 diff = (-loc + 3) & -4;
1391#ifdef TCC_ARM_EABI1416#ifdef TCC_ARM_EABI
1392 if(!leaffunc)1417 if (!leaffunc)
1393 diff = ((diff + 11) & -8) - 4;1418 diff = ((diff + 11) & -8) - 4;
1394#endif1419#endif
1395 if(diff > 0) {1420 if (diff > 0) {
1396 x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */1421 x = stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
1397 if(x)1422 if (x)
1398 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x;1423 *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) = x;
1399 else {1424 else {
1400 int addr;1425 int addr;
1401 addr=ind;1426 addr = ind;
1402 o(0xE59FC004); /* ldr ip,[pc+4] */1427 o(0xE59FC004); /* ldr ip,[pc+4] */
1403 o(0xE04BD00C); /* sub sp,fp,ip */1428 o(0xE04BD00C); /* sub sp,fp,ip */
1404 o(0xE1A0F00E); /* mov pc,lr */1429 o(0xE1A0F00E); /* mov pc,lr */
1405 o(diff);1430 o(diff);
1406 *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);1431 *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) =
1432 0xE1000000 | encbranch(func_sub_sp_offset, addr, 1);
1433 }
1407 }1434 }
1408 }
1409}1435}
1410 1436
1411/* generate a jump to a label */1437/* generate a jump to a label */
1412int gjmp(int t)1438int gjmp(int t)
1413{1439{
1414 int r;1440 int r;
1415 r=ind;1441 r = ind;
1416 o(0xE0000000|encbranch(r,t,1));1442 o(0xE0000000 | encbranch(r, t, 1));
1417 return r;1443 return r;
1418}1444}
1419 1445
1420/* generate a jump to a fixed address */1446/* generate a jump to a fixed address */
1421void gjmp_addr(int a)1447void gjmp_addr(int a)
1422{1448{
1423 gjmp(a);1449 gjmp(a);
1424}1450}
1425 1451
1426/* generate a test. set 'inv' to invert test. Stack entry is popped */1452/* generate a test. set 'inv' to invert test. Stack entry is popped */
1427int gtst(int inv, int t)1453int gtst(int inv, int t)
1428{1454{
1429 int v, r;1455 int v, r;
1430 uint32_t op;1456 uint32_t op;
1431 v = vtop->r & VT_VALMASK;1457 v = vtop->r & VT_VALMASK;
1432 r=ind;1458 r = ind;
1433 if (v == VT_CMP) {1459 if (v == VT_CMP) {
1434 op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);1460 op = mapcc(inv ? negcc(vtop->c.i) : vtop->c.i);
1435 op|=encbranch(r,t,1);1461 op |= encbranch(r, t, 1);
1436 o(op);1462 o(op);
1437 t=r;1463 t = r;
1438 } else if (v == VT_JMP || v == VT_JMPI) {1464 } else if (v == VT_JMP || v == VT_JMPI) {
1439 if ((v & 1) == inv) {1465 if ((v & 1) == inv) {
1440 if(!vtop->c.i)1466 if (!vtop->c.i)
1441 vtop->c.i=t;1467 vtop->c.i = t;
1442 else {1468 else {
1443 uint32_t *x;1469 uint32_t* x;
1444 int p,lp;1470 int p, lp;
1445 if(t) {1471 if (t) {
1446 p = vtop->c.i;1472 p = vtop->c.i;
1447 do {1473 do {
1448 p = decbranch(lp=p);1474 p = decbranch(lp = p);
1449 } while(p);1475 } while (p);
1450 x = (uint32_t *)(cur_text_section->data + lp);1476 x = (uint32_t*)(cur_text_section->data + lp);
1451 *x &= 0xff000000;1477 *x &= 0xff000000;
1452 *x |= encbranch(lp,t,1);1478 *x |= encbranch(lp, t, 1);
1453 }1479 }
1454 t = vtop->c.i;1480 t = vtop->c.i;
1455 }1481 }
1456 } else {1482 } else {
1457 t = gjmp(t);1483 t = gjmp(t);
1458 gsym(vtop->c.i);1484 gsym(vtop->c.i);
1485 }
1459 }1486 }
1460 }1487 vtop--;
1461 vtop--;1488 return t;
1462 return t;
1463}1489}
1464 1490
1465/* generate an integer binary operation */1491/* generate an integer binary operation */
1466void gen_opi(int op)1492void gen_opi(int op)
1467{1493{
1468 int c, func = 0;1494 int c, func = 0;
1469 uint32_t opc = 0, r, fr;1495 uint32_t opc = 0, r, fr;
1470 unsigned short retreg = REG_IRET;1496 unsigned short retreg = REG_IRET;
1471 1497
1472 c=0;1498 c = 0;
1473 switch(op) {1499 switch (op) {
1474 case '+':1500 case '+':
1475 opc = 0x8;1501 opc = 0x8;
1476 c=1;1502 c = 1;
1477 break;1503 break;
1478 case TOK_ADDC1: /* add with carry generation */1504 case TOK_ADDC1: /* add with carry generation */
1479 opc = 0x9;1505 opc = 0x9;
1480 c=1;1506 c = 1;
1481 break;1507 break;
1482 case '-':1508 case '-':
1483 opc = 0x4;1509 opc = 0x4;
1484 c=1;1510 c = 1;
1485 break;1511 break;
1486 case TOK_SUBC1: /* sub with carry generation */1512 case TOK_SUBC1: /* sub with carry generation */
1487 opc = 0x5;1513 opc = 0x5;
1488 c=1;1514 c = 1;
1489 break;1515 break;
1490 case TOK_ADDC2: /* add with carry use */1516 case TOK_ADDC2: /* add with carry use */
1491 opc = 0xA;1517 opc = 0xA;
1492 c=1;1518 c = 1;
1493 break;1519 break;
1494 case TOK_SUBC2: /* sub with carry use */1520 case TOK_SUBC2: /* sub with carry use */
1495 opc = 0xC;1521 opc = 0xC;
1496 c=1;1522 c = 1;
1497 break;1523 break;
1498 case '&':1524 case '&':
1499 opc = 0x0;1525 opc = 0x0;
1500 c=1;1526 c = 1;
1501 break;1527 break;
1502 case '^':1528 case '^':
1503 opc = 0x2;1529 opc = 0x2;
1504 c=1;1530 c = 1;
1505 break;1531 break;
1506 case '|':1532 case '|':
1507 opc = 0x18;1533 opc = 0x18;
1508 c=1;1534 c = 1;
1509 break;1535 break;
1510 case '*':1536 case '*':
1511 gv2(RC_INT, RC_INT);1537 gv2(RC_INT, RC_INT);
1512 r = vtop[-1].r;1538 r = vtop[-1].r;
1513 fr = vtop[0].r;1539 fr = vtop[0].r;
1514 vtop--;1540 vtop--;
1515 o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr));1541 o(0xE0000090 | (intr(r) << 16) | (intr(r) << 8) | intr(fr));
1516 return;1542 return;
1517 case TOK_SHL:1543 case TOK_SHL:
1518 opc = 0;1544 opc = 0;
1519 c=2;1545 c = 2;
1520 break;1546 break;
1521 case TOK_SHR:1547 case TOK_SHR:
1522 opc = 1;1548 opc = 1;
1523 c=2;1549 c = 2;
1524 break;1550 break;
1525 case TOK_SAR:1551 case TOK_SAR:
1526 opc = 2;1552 opc = 2;
1527 c=2;1553 c = 2;
1528 break;1554 break;
1529 case '/':1555 case '/':
1530 case TOK_PDIV:1556 case TOK_PDIV:
1531 func=TOK___divsi3;1557 func = TOK___divsi3;
1532 c=3;1558 c = 3;
1533 break;1559 break;
1534 case TOK_UDIV:1560 case TOK_UDIV:
1535 func=TOK___udivsi3;1561 func = TOK___udivsi3;
1536 c=3;1562 c = 3;
1537 break;1563 break;
1538 case '%':1564 case '%':
1539#ifdef TCC_ARM_EABI1565#ifdef TCC_ARM_EABI
1540 func=TOK___aeabi_idivmod;1566 func = TOK___aeabi_idivmod;
1541 retreg=REG_LRET;1567 retreg = REG_LRET;
1542#else1568#else
1543 func=TOK___modsi3;1569 func = TOK___modsi3;
1544#endif1570#endif
1545 c=3;1571 c = 3;
1546 break;1572 break;
1547 case TOK_UMOD:1573 case TOK_UMOD:
1548#ifdef TCC_ARM_EABI1574#ifdef TCC_ARM_EABI
1549 func=TOK___aeabi_uidivmod;1575 func = TOK___aeabi_uidivmod;
1550 retreg=REG_LRET;1576 retreg = REG_LRET;
1551#else1577#else
1552 func=TOK___umodsi3;1578 func = TOK___umodsi3;
1553#endif1579#endif
1554 c=3;1580 c = 3;
1555 break;1581 break;
1556 case TOK_UMULL:1582 case TOK_UMULL:
1557 gv2(RC_INT, RC_INT);1583 gv2(RC_INT, RC_INT);
1558 r=intr(vtop[-1].r2=get_reg(RC_INT));1584 r = intr(vtop[-1].r2 = get_reg(RC_INT));
1559 c=vtop[-1].r;1585 c = vtop[-1].r;
1560 vtop[-1].r=get_reg_ex(RC_INT,regmask(c));1586 vtop[-1].r = get_reg_ex(RC_INT, regmask(c));
1561 vtop--;1587 vtop--;
1562 o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r));1588 o(0xE0800090 | (r << 16) | (intr(vtop->r) << 12) | (intr(c) << 8) |
1563 return;1589 intr(vtop[1].r));
1590 return;
1564 default:1591 default:
1565 opc = 0x15;1592 opc = 0x15;
1566 c=1;1593 c = 1;
1567 break;1594 break;
1568 }1595 }
1569 switch(c) {1596 switch (c) {
1570 case 1:1597 case 1:
1571 if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1598 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1572 if(opc == 4 || opc == 5 || opc == 0xc) {1599 if (opc == 4 || opc == 5 || opc == 0xc) {
1573 vswap();1600 vswap();
1574 opc|=2; // sub -> rsb1601 opc |= 2; // sub -> rsb
1575 }1602 }
1576 }1603 }
1577 if ((vtop->r & VT_VALMASK) == VT_CMP ||1604 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1578 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)1605 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1579 gv(RC_INT);1606 gv(RC_INT);
1580 vswap();1607 vswap();
1581 c=intr(gv(RC_INT));1608 c = intr(gv(RC_INT));
1582 vswap();1609 vswap();
1583 opc=0xE0000000|(opc<<20)|(c<<16);1610 opc = 0xE0000000 | (opc << 20) | (c << 16);
1584 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1611 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1585 uint32_t x;1612 uint32_t x;
1586 x=stuff_const(opc|0x2000000,vtop->c.i);1613 x = stuff_const(opc | 0x2000000, vtop->c.i);
1587 if(x) {1614 if (x) {
1588 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));1615 r = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r)));
1589 o(x|(r<<12));1616 o(x | (r << 12));
1590 goto done;1617 goto done;
1591 }1618 }
1592 }1619 }
1593 fr=intr(gv(RC_INT));1620 fr = intr(gv(RC_INT));
1594 r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));1621 r = intr(vtop[-1].r =
1595 o(opc|(r<<12)|fr);1622 get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r)));
1596done:1623 o(opc | (r << 12) | fr);
1597 vtop--;1624 done:
1598 if (op >= TOK_ULT && op <= TOK_GT) {1625 vtop--;
1599 vtop->r = VT_CMP;1626 if (op >= TOK_ULT && op <= TOK_GT) {
1600 vtop->c.i = op;1627 vtop->r = VT_CMP;
1601 }1628 vtop->c.i = op;
1602 break;1629 }
1630 break;
1603 case 2:1631 case 2:
1604 opc=0xE1A00000|(opc<<5);1632 opc = 0xE1A00000 | (opc << 5);
1605 if ((vtop->r & VT_VALMASK) == VT_CMP ||1633 if ((vtop->r & VT_VALMASK) == VT_CMP ||
1606 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)1634 (vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
1607 gv(RC_INT);1635 gv(RC_INT);
1608 vswap();1636 vswap();
1609 r=intr(gv(RC_INT));1637 r = intr(gv(RC_INT));
1610 vswap();1638 vswap();
1611 opc|=r;1639 opc |= r;
1612 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1640 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1613 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));1641 fr = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r)));
1614 c = vtop->c.i & 0x1f;1642 c = vtop->c.i & 0x1f;
1615 o(opc|(c<<7)|(fr<<12));1643 o(opc | (c << 7) | (fr << 12));
1616 } else {1644 } else {
1617 fr=intr(gv(RC_INT));1645 fr = intr(gv(RC_INT));
1618 c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));1646 c = intr(vtop[-1].r =
1619 o(opc|(c<<12)|(fr<<8)|0x10);1647 get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r)));
1620 }1648 o(opc | (c << 12) | (fr << 8) | 0x10);
1621 vtop--;1649 }
1622 break;1650 vtop--;
1651 break;
1623 case 3:1652 case 3:
1624 vpush_global_sym(&func_old_type, func);1653 vpush_global_sym(&func_old_type, func);
1625 vrott(3);1654 vrott(3);
1626 gfunc_call(2);1655 gfunc_call(2);
1627 vpushi(0);1656 vpushi(0);
1628 vtop->r = retreg;1657 vtop->r = retreg;
1629 break;1658 break;
1630 default:1659 default:
1631 tcc_error("gen_opi %i unimplemented!",op);1660 tcc_error("gen_opi %i unimplemented!", op);
1632 }1661 }
1633}1662}
1634 1663
1635#ifdef TCC_ARM_VFP1664#ifdef TCC_ARM_VFP
1636static int is_zero(int i)1665static int is_zero(int i)
1637{1666{
1638 if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)1667 if ((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1639 return 0;1668 return 0;
1640 if (vtop[i].type.t == VT_FLOAT)1669 if (vtop[i].type.t == VT_FLOAT)
1641 return (vtop[i].c.f == 0.f);1670 return (vtop[i].c.f == 0.f);
1642 else if (vtop[i].type.t == VT_DOUBLE)1671 else if (vtop[i].type.t == VT_DOUBLE)
1643 return (vtop[i].c.d == 0.0);1672 return (vtop[i].c.d == 0.0);
1644 return (vtop[i].c.ld == 0.l);1673 return (vtop[i].c.ld == 0.l);
1645}1674}
1646 1675
1647/* generate a floating point operation 'v = t1 op t2' instruction. The1676/* generate a floating point operation 'v = t1 op t2' instruction. The
1648 * two operands are guaranted to have the same floating point type */1677 * two operands are guaranted to have the same floating point type */
1649void gen_opf(int op)1678void gen_opf(int op)
1650{1679{
1651 uint32_t x;1680 uint32_t x;
1652 int fneg=0,r;1681 int fneg = 0, r;
1653 x=0xEE000A00|T2CPR(vtop->type.t);1682 x = 0xEE000A00 | T2CPR(vtop->type.t);
1654 switch(op) {1683 switch (op) {
1655 case '+':1684 case '+':
1656 if(is_zero(-1))1685 if (is_zero(-1))
1657 vswap();1686 vswap();
1658 if(is_zero(0)) {1687 if (is_zero(0)) {
1659 vtop--;1688 vtop--;
1660 return;1689 return;
1661 }1690 }
1662 x|=0x300000;1691 x |= 0x300000;
1663 break;1692 break;
1664 case '-':1693 case '-':
1665 x|=0x300040;1694 x |= 0x300040;
1666 if(is_zero(0)) {1695 if (is_zero(0)) {
1667 vtop--;1696 vtop--;
1668 return;1697 return;
1669 }1698 }
1670 if(is_zero(-1)) {1699 if (is_zero(-1)) {
1671 x|=0x810000; /* fsubX -> fnegX */1700 x |= 0x810000; /* fsubX -> fnegX */
1672 vswap();1701 vswap();
1673 vtop--;1702 vtop--;
1674 fneg=1;1703 fneg = 1;
1675 }1704 }
1676 break;1705 break;
1677 case '*':1706 case '*':
1678 x|=0x200000;1707 x |= 0x200000;
1679 break;1708 break;
1680 case '/':1709 case '/':
1681 x|=0x800000;1710 x |= 0x800000;
1682 break;1711 break;
1683 default:1712 default:
1684 if(op < TOK_ULT || op > TOK_GT) {1713 if (op < TOK_ULT || op > TOK_GT) {
1685 tcc_error("unknown fp op %x!",op);1714 tcc_error("unknown fp op %x!", op);
1686 return;1715 return;
1687 }1716 }
1688 if(is_zero(-1)) {1717 if (is_zero(-1)) {
1689 vswap();1718 vswap();
1690 switch(op) {1719 switch(op) {
1691 case TOK_LT: op=TOK_GT; break;1720 case TOK_LT: op = TOK_GT; break;
1692 case TOK_GE: op=TOK_ULE; break;1721 case TOK_GE: op = TOK_ULE; break;
1693 case TOK_LE: op=TOK_GE; break;1722 case TOK_LE: op = TOK_GE; break;
1694 case TOK_GT: op=TOK_ULT; break;1723 case TOK_GT: op = TOK_ULT; break;
1695 }1724 }
1696 }1725 }
1697 x|=0xB40040; /* fcmpX */1726 x |= 0xB40040; /* fcmpX */
1698 if(op!=TOK_EQ && op!=TOK_NE)1727 if (op != TOK_EQ && op != TOK_NE)
1699 x|=0x80; /* fcmpX -> fcmpeX */1728 x |= 0x80; /* fcmpX -> fcmpeX */
1700 if(is_zero(0)) {1729 if (is_zero(0)) {
1701 vtop--;1730 vtop--;
1702 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */1731 o(x | 0x10000 |
1703 } else {1732 (vfpr(gv(RC_FLOAT)) << 12)); /* fcmp(e)X -> fcmp(e)zX */
1704 x|=vfpr(gv(RC_FLOAT));1733 } else {
1705 vswap();1734 x |= vfpr(gv(RC_FLOAT));
1706 o(x|(vfpr(gv(RC_FLOAT))<<12));1735 vswap();
1707 vtop--;1736 o(x | (vfpr(gv(RC_FLOAT)) << 12));
1708 }1737 vtop--;
1709 o(0xEEF1FA10); /* fmstat */1738 }
1739 o(0xEEF1FA10); /* fmstat */
1710 1740
1711 switch(op) {1741 switch(op) {
1712 case TOK_LE: op=TOK_ULE; break;1742 case TOK_LE: op = TOK_ULE; break;
1713 case TOK_LT: op=TOK_ULT; break;1743 case TOK_LT: op = TOK_ULT; break;
1714 case TOK_UGE: op=TOK_GE; break;1744 case TOK_UGE: op = TOK_GE; break;
1715 case TOK_UGT: op=TOK_GT; break;1745 case TOK_UGT: op = TOK_GT; break;
1716 }1746 }
1717 1747
1718 vtop->r = VT_CMP;1748 vtop->r = VT_CMP;
1719 vtop->c.i = op;1749 vtop->c.i = op;
1720 return;1750 return;
1721 }1751 }
1722 r=gv(RC_FLOAT);1752 r = gv(RC_FLOAT);
1723 x|=vfpr(r);1753 x |= vfpr(r);
1724 r=regmask(r);1754 r = regmask(r);
1725 if(!fneg) {1755 if (!fneg) {
1726 int r2;1756 int r2;
1727 vswap();1757 vswap();
1728 r2=gv(RC_FLOAT);1758 r2 = gv(RC_FLOAT);
1729 x|=vfpr(r2)<<16;1759 x |= vfpr(r2) << 16;
1730 r|=regmask(r2);1760 r |= regmask(r2);
1731 }1761 }
1732 vtop->r=get_reg_ex(RC_FLOAT,r);1762 vtop->r = get_reg_ex(RC_FLOAT, r);
1733 if(!fneg)1763 if (!fneg)
1734 vtop--;1764 vtop--;
1735 o(x|(vfpr(vtop->r)<<12));1765 o(x | (vfpr(vtop->r) << 12));
1736}1766}
1737 1767
1738#else1768#else
1739static uint32_t is_fconst()1769static uint32_t is_fconst()
1740{1770{
1741 long double f;1771 long double f;
1742 uint32_t r;1772 uint32_t r;
1743 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)1773 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1744 return 0;1774 return 0;
1745 if (vtop->type.t == VT_FLOAT)1775 if (vtop->type.t == VT_FLOAT)
1746 f = vtop->c.f;1776 f = vtop->c.f;
1747 else if (vtop->type.t == VT_DOUBLE)1777 else if (vtop->type.t == VT_DOUBLE)
1748 f = vtop->c.d;1778 f = vtop->c.d;
1749 else1779 else
1750 f = vtop->c.ld;1780 f = vtop->c.ld;
1751 if(!ieee_finite(f))1781 if (!ieee_finite(f))
1782 return 0;
1783 r = 0x8;
1784 if (f < 0.0) {
1785 r = 0x18;
1786 f = -f;
1787 }
1788 if (f == 0.0)
1789 return r;
1790 if (f == 1.0)
1791 return r | 1;
1792 if (f == 2.0)
1793 return r | 2;
1794 if (f == 3.0)
1795 return r | 3;
1796 if (f == 4.0)
1797 return r | 4;
1798 if (f == 5.0)
1799 return r | 5;
1800 if (f == 0.5)
1801 return r | 6;
1802 if (f == 10.0)
1803 return r | 7;
1752 return 0;1804 return 0;
1753 r=0x8;
1754 if(f<0.0) {
1755 r=0x18;
1756 f=-f;
1757 }
1758 if(f==0.0)
1759 return r;
1760 if(f==1.0)
1761 return r|1;
1762 if(f==2.0)
1763 return r|2;
1764 if(f==3.0)
1765 return r|3;
1766 if(f==4.0)
1767 return r|4;
1768 if(f==5.0)
1769 return r|5;
1770 if(f==0.5)
1771 return r|6;
1772 if(f==10.0)
1773 return r|7;
1774 return 0;
1775}1805}
1776 1806
1777/* generate a floating point operation 'v = t1 op t2' instruction. The1807/* generate a floating point operation 'v = t1 op t2' instruction. The
1778 two operands are guaranted to have the same floating point type */1808 two operands are guaranted to have the same floating point type */
1779void gen_opf(int op)1809void gen_opf(int op)
1780{1810{
1781 uint32_t x, r, r2, c1, c2;1811 uint32_t x, r, r2, c1, c2;
1782 //fputs("gen_opf\n",stderr);1812 // fputs("gen_opf\n",stderr);
1783 vswap();1813 vswap();
1784 c1 = is_fconst();1814 c1 = is_fconst();
1785 vswap();1815 vswap();
1786 c2 = is_fconst();1816 c2 = is_fconst();
1787 x=0xEE000100;1817 x = 0xEE000100;
1788#if LDOUBLE_SIZE == 81818#if LDOUBLE_SIZE == 8
1789 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)1819 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
1790 x|=0x80;1820 x |= 0x80;
1791#else1821#else
1792 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)1822 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1793 x|=0x80;1823 x |= 0x80;
1794 else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)1824 else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
1795 x|=0x80000;1825 x |= 0x80000;
1796#endif1826#endif
1797 switch(op)1827 switch (op) {
1798 {
1799 case '+':1828 case '+':
1800 if(!c2) {1829 if (!c2) {
1801 vswap();1830 vswap();
1802 c2=c1;1831 c2 = c1;
1803 }1832 }
1804 vswap();1833 vswap();
1805 r=fpr(gv(RC_FLOAT));1834 r = fpr(gv(RC_FLOAT));
1806 vswap();1835 vswap();
1807 if(c2) {1836 if (c2) {
1808 if(c2>0xf)1837 if (c2 > 0xf)
1809 x|=0x200000; // suf1838 x |= 0x200000; // suf
1810 r2=c2&0xf;1839 r2 = c2 & 0xf;
1811 } else {1840 } else {
1812 r2=fpr(gv(RC_FLOAT));1841 r2 = fpr(gv(RC_FLOAT));
1813 }1842 }
1814 break;1843 break;
1815 case '-':1844 case '-':
1816 if(c2) {1845 if (c2) {
1817 if(c2<=0xf)1846 if (c2 <= 0xf)
1818 x|=0x200000; // suf1847 x |= 0x200000; // suf
1819 r2=c2&0xf;1848 r2 = c2 & 0xf;
1820 vswap();1849 vswap();
1821 r=fpr(gv(RC_FLOAT));1850 r = fpr(gv(RC_FLOAT));
1822 vswap();1851 vswap();
1823 } else if(c1 && c1<=0xf) {1852 } else if (c1 && c1 <= 0xf) {
1824 x|=0x300000; // rsf1853 x |= 0x300000; // rsf
1825 r2=c1;1854 r2 = c1;
1826 r=fpr(gv(RC_FLOAT));1855 r = fpr(gv(RC_FLOAT));
1827 vswap();1856 vswap();
1828 } else {1857 } else {
1829 x|=0x200000; // suf1858 x |= 0x200000; // suf
1830 vswap();1859 vswap();
1831 r=fpr(gv(RC_FLOAT));1860 r = fpr(gv(RC_FLOAT));
1832 vswap();1861 vswap();
1833 r2=fpr(gv(RC_FLOAT));1862 r2 = fpr(gv(RC_FLOAT));
1834 }1863 }
1835 break;1864 break;
1836 case '*':1865 case '*':
1837 if(!c2 || c2>0xf) {1866 if (!c2 || c2 > 0xf) {
1838 vswap();1867 vswap();
1839 c2=c1;1868 c2 = c1;
1840 }1869 }
1841 vswap();1870 vswap();
1842 r=fpr(gv(RC_FLOAT));1871 r = fpr(gv(RC_FLOAT));
1843 vswap();1872 vswap();
1844 if(c2 && c2<=0xf)1873 if (c2 && c2 <= 0xf)
1845 r2=c2;1874 r2 = c2;
1846 else1875 else
1847 r2=fpr(gv(RC_FLOAT));1876 r2 = fpr(gv(RC_FLOAT));
1848 x|=0x100000; // muf1877 x |= 0x100000; // muf
1849 break;1878 break;
1850 case '/':1879 case '/':
1851 if(c2 && c2<=0xf) {1880 if (c2 && c2 <= 0xf) {
1852 x|=0x400000; // dvf1881 x |= 0x400000; // dvf
1853 r2=c2;1882 r2 = c2;
1854 vswap();1883 vswap();
1855 r=fpr(gv(RC_FLOAT));1884 r = fpr(gv(RC_FLOAT));
1856 vswap();1885 vswap();
1857 } else if(c1 && c1<=0xf) {1886 } else if (c1 && c1 <= 0xf) {
1858 x|=0x500000; // rdf1887 x |= 0x500000; // rdf
1859 r2=c1;1888 r2 = c1;
1860 r=fpr(gv(RC_FLOAT));1889 r = fpr(gv(RC_FLOAT));
1861 vswap();1890 vswap();
1862 } else {1891 } else {
1863 x|=0x400000; // dvf1892 x |= 0x400000; // dvf
1864 vswap();1893 vswap();
1865 r=fpr(gv(RC_FLOAT));1894 r = fpr(gv(RC_FLOAT));
1866 vswap();1895 vswap();
1867 r2=fpr(gv(RC_FLOAT));1896 r2 = fpr(gv(RC_FLOAT));
1868 }1897 }
1869 break;1898 break;
1870 default:1899 default:
1871 if(op >= TOK_ULT && op <= TOK_GT) {1900 if (op >= TOK_ULT && op <= TOK_GT) {
1872 x|=0xd0f110; // cmfe1901 x |= 0xd0f110; // cmfe
1873/* bug (intention?) in Linux FPU emulator1902 /* bug (intention?) in Linux FPU emulator
1874 doesn't set carry if equal */1903 doesn't set carry if equal */
1875 switch(op) {1904 switch (op) {
1876 case TOK_ULT:1905 case TOK_ULT:
1877 case TOK_UGE:1906 case TOK_UGE:
1878 case TOK_ULE:1907 case TOK_ULE:
1879 case TOK_UGT:1908 case TOK_UGT:
1880 tcc_error("unsigned comparison on floats?");1909 tcc_error("unsigned comparison on floats?");
1881 break;1910 break;
1882 case TOK_LT:1911 case TOK_LT:
1883 op=TOK_Nset;1912 op = TOK_Nset;
1884 break;1913 break;
1885 case TOK_LE:1914 case TOK_LE:
1886 op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */1915 op = TOK_ULE; /* correct in unordered case only if AC bit in
1887 break;1916 FPSR set */
1888 case TOK_EQ:1917 break;
1889 case TOK_NE:1918 case TOK_EQ:
1890 x&=~0x400000; // cmfe -> cmf1919 case TOK_NE:
1891 break;1920 x &= ~0x400000; // cmfe -> cmf
1892 }1921 break;
1893 if(c1 && !c2) {1922 }
1894 c2=c1;1923 if (c1 && !c2) {
1895 vswap();1924 c2 = c1;
1896 switch(op) {1925 vswap();
1897 case TOK_Nset:1926 switch (op) {
1898 op=TOK_GT;1927 case TOK_Nset:
1899 break;1928 op = TOK_GT;
1900 case TOK_GE:1929 break;
1901 op=TOK_ULE;1930 case TOK_GE:
1902 break;1931 op = TOK_ULE;
1903 case TOK_ULE:1932 break;
1904 op=TOK_GE;1933 case TOK_ULE:
1905 break;1934 op = TOK_GE;
1906 case TOK_GT:1935 break;
1907 op=TOK_Nset;1936 case TOK_GT:
1908 break;1937 op = TOK_Nset;
1909 }1938 break;
1910 }1939 }
1911 vswap();1940 }
1912 r=fpr(gv(RC_FLOAT));1941 vswap();
1913 vswap();1942 r = fpr(gv(RC_FLOAT));
1914 if(c2) {1943 vswap();
1915 if(c2>0xf)1944 if (c2) {
1916 x|=0x200000;1945 if (c2 > 0xf)
1917 r2=c2&0xf;1946 x |= 0x200000;
1918 } else {1947 r2 = c2 & 0xf;
1919 r2=fpr(gv(RC_FLOAT));1948 } else {
1920 }1949 r2 = fpr(gv(RC_FLOAT));
1921 vtop[-1].r = VT_CMP;1950 }
1922 vtop[-1].c.i = op;1951 vtop[-1].r = VT_CMP;
1923 } else {1952 vtop[-1].c.i = op;
1924 tcc_error("unknown fp op %x!",op);1953 } else {
1925 return;1954 tcc_error("unknown fp op %x!", op);
1926 }1955 return;
1927 }1956 }
1928 if(vtop[-1].r == VT_CMP)1957 }
1929 c1=15;1958 if (vtop[-1].r == VT_CMP)
1930 else {1959 c1 = 15;
1931 c1=vtop->r;1960 else {
1932 if(r2&0x8)1961 c1 = vtop->r;
1933 c1=vtop[-1].r;1962 if (r2 & 0x8)
1934 vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1));1963 c1 = vtop[-1].r;
1935 c1=fpr(vtop[-1].r);1964 vtop[-1].r = get_reg_ex(RC_FLOAT, two2mask(vtop[-1].r, c1));
1936 }1965 c1 = fpr(vtop[-1].r);
1937 vtop--;1966 }
1938 o(x|(r<<16)|(c1<<12)|r2);1967 vtop--;
1968 o(x | (r << 16) | (c1 << 12) | r2);
1939}1969}
1940#endif1970#endif
1941 1971
@@ -1943,177 +1973,186 @@ void gen_opf(int op) · 1 unmodified line
1943 and 'long long' cases. */1973 and 'long long' cases. */
1944ST_FUNC void gen_cvt_itof1(int t)1974ST_FUNC void gen_cvt_itof1(int t)
1945{1975{
1946 uint32_t r, r2;1976 uint32_t r, r2;
1947 int bt;1977 int bt;
1948 bt=vtop->type.t & VT_BTYPE;1978 bt = vtop->type.t & VT_BTYPE;
1949 if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {1979 if (bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
1950#ifndef TCC_ARM_VFP1980#ifndef TCC_ARM_VFP
1951 uint32_t dsize = 0;1981 uint32_t dsize = 0;
1952#endif1982#endif
1953 r=intr(gv(RC_INT));1983 r = intr(gv(RC_INT));
1954#ifdef TCC_ARM_VFP1984#ifdef TCC_ARM_VFP
1955 r2=vfpr(vtop->r=get_reg(RC_FLOAT));1985 r2 = vfpr(vtop->r = get_reg(RC_FLOAT));
1956 o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */1986 o(0xEE000A10 | (r << 12) | (r2 << 16)); /* fmsr */
1957 r2|=r2<<12;1987 r2 |= r2 << 12;
1958 if(!(vtop->type.t & VT_UNSIGNED))1988 if (!(vtop->type.t & VT_UNSIGNED))
1959 r2|=0x80; /* fuitoX -> fsituX */1989 r2 |= 0x80; /* fuitoX -> fsituX */
1960 o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/1990 o(0xEEB80A40 | r2 | T2CPR(t)); /* fYitoX*/
1961#else1991#else
1962 r2=fpr(vtop->r=get_reg(RC_FLOAT));1992 r2 = fpr(vtop->r = get_reg(RC_FLOAT));
1963 if((t & VT_BTYPE) != VT_FLOAT)1993 if ((t & VT_BTYPE) != VT_FLOAT)
1964 dsize=0x80; /* flts -> fltd */1994 dsize = 0x80; /* flts -> fltd */
1965 o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */1995 o(0xEE000110 | dsize | (r2 << 16) | (r << 12)); /* flts */
1966 if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {1996 if ((vtop->type.t & (VT_UNSIGNED | VT_BTYPE)) ==
1967 uint32_t off = 0;1997 (VT_UNSIGNED | VT_INT)) {
1968 o(0xE3500000|(r<<12)); /* cmp */1998 uint32_t off = 0;
1969 r=fpr(get_reg(RC_FLOAT));1999 o(0xE3500000 | (r << 12)); /* cmp */
1970 if(last_itod_magic) {2000 r = fpr(get_reg(RC_FLOAT));
1971 off=ind+8-last_itod_magic;2001 if (last_itod_magic) {
1972 off/=4;2002 off = ind + 8 - last_itod_magic;
1973 if(off>255)2003 off /= 4;
1974 off=0;2004 if (off > 255)
1975 }2005 off = 0;
1976 o(0xBD1F0100|(r<<12)|off); /* ldflts */2006 }
1977 if(!off) {2007 o(0xBD1F0100 | (r << 12) | off); /* ldflts */
1978 o(0xEA000000); /* b */2008 if (!off) {
1979 last_itod_magic=ind;2009 o(0xEA000000); /* b */
1980 o(0x4F800000); /* 4294967296.0f */2010 last_itod_magic = ind;
1981 }2011 o(0x4F800000); /* 4294967296.0f */
1982 o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */2012 }
1983 }2013 o(0xBE000100 | dsize | (r2 << 16) | (r2 << 12) | r); /* adflt */
2014 }
1984#endif2015#endif
1985 return;2016 return;
1986 } else if(bt == VT_LLONG) {2017 } else if (bt == VT_LLONG) {
1987 int func;2018 int func;
1988 CType *func_type = 0;2019 CType* func_type = 0;
1989 if((t & VT_BTYPE) == VT_FLOAT) {2020 if ((t & VT_BTYPE) == VT_FLOAT) {
1990 func_type = &func_float_type;2021 func_type = &func_float_type;
1991 if(vtop->type.t & VT_UNSIGNED)2022 if (vtop->type.t & VT_UNSIGNED)
1992 func=TOK___floatundisf;2023 func = TOK___floatundisf;
1993 else2024 else
1994 func=TOK___floatdisf;2025 func = TOK___floatdisf;
1995#if LDOUBLE_SIZE != 82026#if LDOUBLE_SIZE != 8
1996 } else if((t & VT_BTYPE) == VT_LDOUBLE) {2027 } else if ((t & VT_BTYPE) == VT_LDOUBLE) {
1997 func_type = &func_ldouble_type;2028 func_type = &func_ldouble_type;
1998 if(vtop->type.t & VT_UNSIGNED)2029 if (vtop->type.t & VT_UNSIGNED)
1999 func=TOK___floatundixf;2030 func = TOK___floatundixf;
2000 else2031 else
2001 func=TOK___floatdixf;2032 func = TOK___floatdixf;
2002 } else if((t & VT_BTYPE) == VT_DOUBLE) {2033 } else if ((t & VT_BTYPE) == VT_DOUBLE) {
2003#else2034#else
2004 } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {2035 } else if ((t & VT_BTYPE) == VT_DOUBLE ||
2036 (t & VT_BTYPE) == VT_LDOUBLE) {
2005#endif2037#endif
2006 func_type = &func_double_type;2038 func_type = &func_double_type;
2007 if(vtop->type.t & VT_UNSIGNED)2039 if (vtop->type.t & VT_UNSIGNED)
2008 func=TOK___floatundidf;2040 func = TOK___floatundidf;
2009 else2041 else
2010 func=TOK___floatdidf;2042 func = TOK___floatdidf;
2011 }2043 }
2012 if(func_type) {2044 if (func_type) {
2013 vpush_global_sym(func_type, func);2045 vpush_global_sym(func_type, func);
2014 vswap();2046 vswap();
2015 gfunc_call(1);2047 gfunc_call(1);
2016 vpushi(0);2048 vpushi(0);
2017 vtop->r=TREG_F0;2049 vtop->r = TREG_F0;
2018 return;2050 return;
2051 }
2019 }2052 }
2020 }2053 tcc_error("unimplemented gen_cvt_itof %x!", vtop->type.t);
2021 tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t);
2022}2054}
2023 2055
2024/* convert fp to int 't' type */2056/* convert fp to int 't' type */
2025void gen_cvt_ftoi(int t)2057void gen_cvt_ftoi(int t)
2026{2058{
2027 uint32_t r, r2;2059 uint32_t r, r2;
2028 int u, func = 0;2060 int u, func = 0;
2029 u=t&VT_UNSIGNED;2061 u = t & VT_UNSIGNED;
2030 t&=VT_BTYPE;2062 t &= VT_BTYPE;
2031 r2=vtop->type.t & VT_BTYPE;2063 r2 = vtop->type.t & VT_BTYPE;
2032 if(t==VT_INT) {2064 if (t == VT_INT) {
2033#ifdef TCC_ARM_VFP2065#ifdef TCC_ARM_VFP
2034 r=vfpr(gv(RC_FLOAT));2066 r = vfpr(gv(RC_FLOAT));
2035 u=u?0:0x10000;2067 u = u ? 0 : 0x10000;
2036 o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */2068 o(0xEEBC0AC0 | (r << 12) | r | T2CPR(r2) | u); /* ftoXizY */
2037 r2=intr(vtop->r=get_reg(RC_INT));2069 r2 = intr(vtop->r = get_reg(RC_INT));
2038 o(0xEE100A10|(r<<16)|(r2<<12));2070 o(0xEE100A10 | (r << 16) | (r2 << 12));
2039 return;2071 return;
2040#else2072#else
2041 if(u) {2073 if (u) {
2042 if(r2 == VT_FLOAT)2074 if (r2 == VT_FLOAT)
2043 func=TOK___fixunssfsi;2075 func = TOK___fixunssfsi;
2044#if LDOUBLE_SIZE != 82076#if LDOUBLE_SIZE != 8
2045 else if(r2 == VT_LDOUBLE)2077 else if (r2 == VT_LDOUBLE)
2046 func=TOK___fixunsxfsi;2078 func = TOK___fixunsxfsi;
2047 else if(r2 == VT_DOUBLE)2079 else if (r2 == VT_DOUBLE)
2048#else2080#else
2049 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)2081 else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2050#endif2082#endif
2051 func=TOK___fixunsdfsi;2083 func = TOK___fixunsdfsi;
2052 } else {2084 } else {
2053 r=fpr(gv(RC_FLOAT));2085 r = fpr(gv(RC_FLOAT));
2054 r2=intr(vtop->r=get_reg(RC_INT));2086 r2 = intr(vtop->r = get_reg(RC_INT));
2055 o(0xEE100170|(r2<<12)|r);2087 o(0xEE100170 | (r2 << 12) | r);
2056 return;2088 return;
2057 }2089 }
2058#endif2090#endif
2059 } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi12091 } else if (t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
2060 if(r2 == VT_FLOAT)2092 if (r2 == VT_FLOAT)
2061 func=TOK___fixsfdi;2093 func = TOK___fixsfdi;
2062#if LDOUBLE_SIZE != 82094#if LDOUBLE_SIZE != 8
2063 else if(r2 == VT_LDOUBLE)2095 else if (r2 == VT_LDOUBLE)
2064 func=TOK___fixxfdi;2096 func = TOK___fixxfdi;
2065 else if(r2 == VT_DOUBLE)2097 else if (r2 == VT_DOUBLE)
2066#else2098#else
2067 else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)2099 else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
2068#endif2100#endif
2069 func=TOK___fixdfdi;2101 func = TOK___fixdfdi;
2070 }2102 }
2071 if(func) {2103 if (func) {
2072 vpush_global_sym(&func_old_type, func);2104 vpush_global_sym(&func_old_type, func);
2073 vswap();2105 vswap();
2074 gfunc_call(1);2106 gfunc_call(1);
2075 vpushi(0);2107 vpushi(0);
2076 if(t == VT_LLONG)2108 if (t == VT_LLONG)
2077 vtop->r2 = REG_LRET;2109 vtop->r2 = REG_LRET;
2078 vtop->r = REG_IRET;2110 vtop->r = REG_IRET;
2079 return;2111 return;
2080 }2112 }
2081 tcc_error("unimplemented gen_cvt_ftoi!");2113 tcc_error("unimplemented gen_cvt_ftoi!");
2082}2114}
2083 2115
2084/* convert from one floating point type to another */2116/* convert from one floating point type to another */
2085void gen_cvt_ftof(int t)2117void gen_cvt_ftof(int t)
2086{2118{
2087#ifdef TCC_ARM_VFP2119#ifdef TCC_ARM_VFP
2088 if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {2120 if (((vtop->type.t & VT_BTYPE) == VT_FLOAT) !=
2089 uint32_t r = vfpr(gv(RC_FLOAT));2121 ((t & VT_BTYPE) == VT_FLOAT)) {
2090 o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));2122 uint32_t r = vfpr(gv(RC_FLOAT));
2091 }2123 o(0xEEB70AC0 | (r << 12) | r | T2CPR(vtop->type.t));
2124 }
2092#else2125#else
2093 /* all we have to do on i386 and FPA ARM is to put the float in a register */2126 /* all we have to do on i386 and FPA ARM is to put the float in a register
2094 gv(RC_FLOAT);2127 */
2128 gv(RC_FLOAT);
2095#endif2129#endif
2096}2130}
2097 2131
2098/* computed goto support */2132/* computed goto support */
2099void ggoto(void)2133void ggoto(void)
2100{2134{
2101 gcall_or_jmp(1);2135 gcall_or_jmp(1);
2102 vtop--;2136 vtop--;
2103}2137}
2104 2138
2105/* Save the stack pointer onto the stack and return the location of its address */2139/* Save the stack pointer onto the stack and return the location of its address
2106ST_FUNC void gen_vla_sp_save(int addr) {2140 */
2141ST_FUNC void gen_vla_sp_save(int addr)
2142{
2107 tcc_error("variable length arrays unsupported for this target");2143 tcc_error("variable length arrays unsupported for this target");
2108}2144}
2109 2145
2110/* Restore the SP from a location on the stack */2146/* Restore the SP from a location on the stack */
2111ST_FUNC void gen_vla_sp_restore(int addr) {2147ST_FUNC void gen_vla_sp_restore(int addr)
2148{
2112 tcc_error("variable length arrays unsupported for this target");2149 tcc_error("variable length arrays unsupported for this target");
2113}2150}
2114 2151
2115/* Subtract from the stack pointer, and push the resulting value onto the stack */2152/* Subtract from the stack pointer, and push the resulting value onto the stack
2116ST_FUNC void gen_vla_alloc(CType *type, int align) {2153 */
2154ST_FUNC void gen_vla_alloc(CType* type, int align)
2155{
2117 tcc_error("variable length arrays unsupported for this target");2156 tcc_error("variable length arrays unsupported for this target");
2118}2157}
2119 2158
tcccoff.c+638−662
@@ -21,9 +21,9 @@ · 20 unmodified lines
21 21
22#include "tcc.h"22#include "tcc.h"
23 23
24#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */24#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
25#define MAX_STR_TABLE 100000025#define MAX_STR_TABLE 1000000
26AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */26AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
27 27
28SCNHDR section_header[MAXNSCNS];28SCNHDR section_header[MAXNSCNS];
29 29
@@ -38,14 +38,14 @@ int EndAddress[MAX_FUNCS]; · 8 unmodified lines
38int LastLineNo[MAX_FUNCS];38int LastLineNo[MAX_FUNCS];
39int FuncEntries[MAX_FUNCS];39int FuncEntries[MAX_FUNCS];
40 40
41int OutputTheSection(Section * sect);41int OutputTheSection(Section* sect);
42short int GetCoffFlags(const char *s);42short int GetCoffFlags(const char* s);
43void SortSymbolTable(void);43void SortSymbolTable(void);
44Section *FindSection(TCCState * s1, const char *sname);44Section* FindSection(TCCState* s1, const char* sname);
45 45
46int C67_main_entry_point;46int C67_main_entry_point;
47 47
48int FindCoffSymbolIndex(const char *func_name);48int FindCoffSymbolIndex(const char* func_name);
49int nb_syms;49int nb_syms;
50 50
51typedef struct {51typedef struct {
@@ -74,15 +74,15 @@ typedef struct { · 22 unmodified lines
74 unsigned short dummy4;74 unsigned short dummy4;
75} AUXEF;75} AUXEF;
76 76
77ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)77ST_FUNC int tcc_output_coff(TCCState* s1, FILE* f)
78{78{
79 Section *tcc_sect;79 Section* tcc_sect;
80 SCNHDR *coff_sec;80 SCNHDR* coff_sec;
81 int file_pointer;81 int file_pointer;
82 char *Coff_str_table, *pCoff_str_table;82 char* Coff_str_table, *pCoff_str_table;
83 int CoffTextSectionNo, coff_nb_syms;83 int CoffTextSectionNo, coff_nb_syms;
84 FILHDR file_hdr; /* FILE HEADER STRUCTURE */84 FILHDR file_hdr; /* FILE HEADER STRUCTURE */
85 Section *stext, *sdata, *sbss;85 Section* stext, *sdata, *sbss;
86 int i, NSectionsToOutput = 0;86 int i, NSectionsToOutput = 0;
87 87
88 Coff_str_table = pCoff_str_table = NULL;88 Coff_str_table = pCoff_str_table = NULL;
@@ -94,21 +94,21 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) · 5 unmodified lines
94 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);94 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
95 coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");95 coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");
96 96
97 file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */97 file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
98 file_hdr.f_timdat = 0; /* time & date stamp */98 file_hdr.f_timdat = 0; /* time & date stamp */
99 file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */99 file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
100 file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */100 file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
101 file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */101 file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
102 102
103 o_filehdr.magic = 0x0108; /* see magic.h */103 o_filehdr.magic = 0x0108; /* see magic.h */
104 o_filehdr.vstamp = 0x0190; /* version stamp */104 o_filehdr.vstamp = 0x0190; /* version stamp */
105 o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */105 o_filehdr.tsize =
106 o_filehdr.dsize = sdata->data_offset; /* initialized data " " */106 stext->data_offset; /* text size in bytes, padded to FW bdry */
107 o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */107 o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
108 o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */108 o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
109 o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */109 o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
110 o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */110 o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
111 111 o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
112 112
113 // create all the section headers113 // create all the section headers
114 114
@@ -117,831 +117,807 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) · 2 unmodified lines
117 CoffTextSectionNo = -1;117 CoffTextSectionNo = -1;
118 118
119 for (i = 1; i < s1->nb_sections; i++) {119 for (i = 1; i < s1->nb_sections; i++) {
120 coff_sec = &section_header[i];120 coff_sec = &section_header[i];
121 tcc_sect = s1->sections[i];121 tcc_sect = s1->sections[i];
122 122
123 if (OutputTheSection(tcc_sect)) {123 if (OutputTheSection(tcc_sect)) {
124 NSectionsToOutput++;124 NSectionsToOutput++;
125 125
126 if (CoffTextSectionNo == -1 && tcc_sect == stext)126 if (CoffTextSectionNo == -1 && tcc_sect == stext)
127 CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is127 CoffTextSectionNo = NSectionsToOutput; // rem which coff sect
128 128 // number the .text sect
129 strcpy(coff_sec->s_name, tcc_sect->name); /* section name */129 // is
130 130
131 coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */131 strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
132 coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */132
133 coff_sec->s_size = tcc_sect->data_offset; /* section size */133 coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
134 coff_sec->s_scnptr = 0; /* file ptr to raw data for section */134 coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
135 coff_sec->s_relptr = 0; /* file ptr to relocation */135 coff_sec->s_size = tcc_sect->data_offset; /* section size */
136 coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */136 coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
137 coff_sec->s_nreloc = 0; /* number of relocation entries */137 coff_sec->s_relptr = 0; /* file ptr to relocation */
138 coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */138 coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
139 coff_sec->s_reserved = 0; /* reserved byte */139 coff_sec->s_nreloc = 0; /* number of relocation entries */
140 coff_sec->s_page = 0; /* memory page id */140 coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
141 141 coff_sec->s_reserved = 0; /* reserved byte */
142 file_pointer += sizeof(SCNHDR);142 coff_sec->s_page = 0; /* memory page id */
143 }143
144 file_pointer += sizeof(SCNHDR);
145 }
144 }146 }
145 147
146 file_hdr.f_nscns = NSectionsToOutput; /* number of sections */148 file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
147 149
148 // now loop through and determine file pointer locations150 // now loop through and determine file pointer locations
149 // for the raw data151 // for the raw data
150 152
151
152 for (i = 1; i < s1->nb_sections; i++) {153 for (i = 1; i < s1->nb_sections; i++) {
153 coff_sec = &section_header[i];154 coff_sec = &section_header[i];
154 tcc_sect = s1->sections[i];155 tcc_sect = s1->sections[i];
155 156
156 if (OutputTheSection(tcc_sect)) {157 if (OutputTheSection(tcc_sect)) {
157 // put raw data158 // put raw data
158 coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */159 coff_sec->s_scnptr =
159 file_pointer += coff_sec->s_size;160 file_pointer; /* file ptr to raw data for section */
160 }161 file_pointer += coff_sec->s_size;
162 }
161 }163 }
162 164
163 // now loop through and determine file pointer locations165 // now loop through and determine file pointer locations
164 // for the relocation data166 // for the relocation data
165 167
166 for (i = 1; i < s1->nb_sections; i++) {168 for (i = 1; i < s1->nb_sections; i++) {
167 coff_sec = &section_header[i];169 coff_sec = &section_header[i];
168 tcc_sect = s1->sections[i];170 tcc_sect = s1->sections[i];
169 171
170 if (OutputTheSection(tcc_sect)) {172 if (OutputTheSection(tcc_sect)) {
171 // put relocations data173 // put relocations data
172 if (coff_sec->s_nreloc > 0) {174 if (coff_sec->s_nreloc > 0) {
173 coff_sec->s_relptr = file_pointer; /* file ptr to relocation */175 coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
174 file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);176 file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
175 }177 }
176 }178 }
177 }179 }
178 180
179 // now loop through and determine file pointer locations181 // now loop through and determine file pointer locations
180 // for the line number data182 // for the line number data
181 183
182 for (i = 1; i < s1->nb_sections; i++) {184 for (i = 1; i < s1->nb_sections; i++) {
183 coff_sec = &section_header[i];185 coff_sec = &section_header[i];
184 tcc_sect = s1->sections[i];186 tcc_sect = s1->sections[i];
185 187
186 coff_sec->s_nlnno = 0;188 coff_sec->s_nlnno = 0;
187 coff_sec->s_lnnoptr = 0;189 coff_sec->s_lnnoptr = 0;
188 190
189 if (s1->do_debug && tcc_sect == stext) {191 if (s1->do_debug && tcc_sect == stext) {
190 // count how many line nos data192 // count how many line nos data
191 193
192 // also find association between source file name and function194 // also find association between source file name and function
193 // so we can sort the symbol table195 // so we can sort the symbol table
194 196
195 197 Stab_Sym* sym, *sym_end;
196 Stab_Sym *sym, *sym_end;198 char func_name[MAX_FUNC_NAME_LENGTH],
197 char func_name[MAX_FUNC_NAME_LENGTH],199 last_func_name[MAX_FUNC_NAME_LENGTH];
198 last_func_name[MAX_FUNC_NAME_LENGTH];200 unsigned long func_addr, last_pc, pc;
199 unsigned long func_addr, last_pc, pc;201 const char* incl_files[INCLUDE_STACK_SIZE];
200 const char *incl_files[INCLUDE_STACK_SIZE];202 int incl_index, len, last_line_num;
201 int incl_index, len, last_line_num;203 const char* str, *p;
202 const char *str, *p;204
203 205 coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
204 coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */206
205 207 func_name[0] = '\0';
206 208 func_addr = 0;
207 func_name[0] = '\0';209 incl_index = 0;
208 func_addr = 0;210 last_func_name[0] = '\0';
209 incl_index = 0;211 last_pc = 0xffffffff;
210 last_func_name[0] = '\0';212 last_line_num = 1;
211 last_pc = 0xffffffff;213 sym = (Stab_Sym*)stab_section->data + 1;
212 last_line_num = 1;214 sym_end =
213 sym = (Stab_Sym *) stab_section->data + 1;215 (Stab_Sym*)(stab_section->data + stab_section->data_offset);
214 sym_end =216
215 (Stab_Sym *) (stab_section->data +217 nFuncs = 0;
216 stab_section->data_offset);218 while (sym < sym_end) {
217 219 switch (sym->n_type) {
218 nFuncs = 0;220 /* function start or end */
219 while (sym < sym_end) {221 case N_FUN:
220 switch (sym->n_type) {222 if (sym->n_strx == 0) {
221 /* function start or end */223 // end of function
222 case N_FUN:224
223 if (sym->n_strx == 0) {225 coff_sec->s_nlnno++;
224 // end of function226 file_pointer += LINESZ;
225 227
226 coff_sec->s_nlnno++;228 pc = sym->n_value + func_addr;
227 file_pointer += LINESZ;229 func_name[0] = '\0';
228 230 func_addr = 0;
229 pc = sym->n_value + func_addr;231 EndAddress[nFuncs] = pc;
230 func_name[0] = '\0';232 FuncEntries[nFuncs] =
231 func_addr = 0;233 (file_pointer - LineNoFilePtr[nFuncs]) / LINESZ - 1;
232 EndAddress[nFuncs] = pc;234 LastLineNo[nFuncs++] = last_line_num + 1;
233 FuncEntries[nFuncs] =235 } else {
234 (file_pointer -236 // beginning of function
235 LineNoFilePtr[nFuncs]) / LINESZ - 1;237
236 LastLineNo[nFuncs++] = last_line_num + 1;238 LineNoFilePtr[nFuncs] = file_pointer;
237 } else {239 coff_sec->s_nlnno++;
238 // beginning of function240 file_pointer += LINESZ;
239 241
240 LineNoFilePtr[nFuncs] = file_pointer;242 str = (const char*)stabstr_section->data + sym->n_strx;
241 coff_sec->s_nlnno++;243
242 file_pointer += LINESZ;244 p = strchr(str, ':');
243 245 if (!p) {
244 str =246 pstrcpy(func_name, sizeof(func_name), str);
245 (const char *) stabstr_section->data +247 pstrcpy(Func[nFuncs], sizeof(func_name), str);
246 sym->n_strx;248 } else {
247 249 len = p - str;
248 p = strchr(str, ':');250 if (len > sizeof(func_name) - 1)
249 if (!p) {251 len = sizeof(func_name) - 1;
250 pstrcpy(func_name, sizeof(func_name), str);252 memcpy(func_name, str, len);
251 pstrcpy(Func[nFuncs], sizeof(func_name), str);253 memcpy(Func[nFuncs], str, len);
252 } else {254 func_name[len] = '\0';
253 len = p - str;255 }
254 if (len > sizeof(func_name) - 1)256
255 len = sizeof(func_name) - 1;257 // save the file that it came in so we can sort later
256 memcpy(func_name, str, len);258 pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
257 memcpy(Func[nFuncs], str, len);259 incl_files[incl_index - 1]);
258 func_name[len] = '\0';260
259 }261 func_addr = sym->n_value;
260 262 }
261 // save the file that it came in so we can sort later263 break;
262 pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),264
263 incl_files[incl_index - 1]);265 /* line number info */
264 266 case N_SLINE:
265 func_addr = sym->n_value;267 pc = sym->n_value + func_addr;
266 }268
267 break;269 last_pc = pc;
268 270 last_line_num = sym->n_desc;
269 /* line number info */271
270 case N_SLINE:272 /* XXX: slow! */
271 pc = sym->n_value + func_addr;273 strcpy(last_func_name, func_name);
272 274
273 last_pc = pc;275 coff_sec->s_nlnno++;
274 last_line_num = sym->n_desc;276 file_pointer += LINESZ;
275 277 break;
276 /* XXX: slow! */278 /* include files */
277 strcpy(last_func_name, func_name);279 case N_BINCL:
278 280 str = (const char*)stabstr_section->data + sym->n_strx;
279 coff_sec->s_nlnno++;281 add_incl:
280 file_pointer += LINESZ;282 if (incl_index < INCLUDE_STACK_SIZE) {
281 break;283 incl_files[incl_index++] = str;
282 /* include files */284 }
283 case N_BINCL:285 break;
284 str =286 case N_EINCL:
285 (const char *) stabstr_section->data + sym->n_strx;287 if (incl_index > 1)
286 add_incl:288 incl_index--;
287 if (incl_index < INCLUDE_STACK_SIZE) {289 break;
288 incl_files[incl_index++] = str;290 case N_SO:
289 }291 if (sym->n_strx == 0) {
290 break;292 incl_index = 0; /* end of translation unit */
291 case N_EINCL:293 } else {
292 if (incl_index > 1)294 str = (const char*)stabstr_section->data + sym->n_strx;
293 incl_index--;295 /* do not add path */
294 break;296 len = strlen(str);
295 case N_SO:297 if (len > 0 && str[len - 1] != '/')
296 if (sym->n_strx == 0) {298 goto add_incl;
297 incl_index = 0; /* end of translation unit */299 }
298 } else {300 break;
299 str =301 }
300 (const char *) stabstr_section->data +302 sym++;
301 sym->n_strx;303 }
302 /* do not add path */304 }
303 len = strlen(str);
304 if (len > 0 && str[len - 1] != '/')
305 goto add_incl;
306 }
307 break;
308 }
309 sym++;
310 }
311 }
312
313 }305 }
314 306
315 file_hdr.f_symptr = file_pointer; /* file pointer to symtab */307 file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
316 308
317 if (s1->do_debug)309 if (s1->do_debug)
318 file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */310 file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
319 else311 else
320 file_hdr.f_nsyms = 0;312 file_hdr.f_nsyms = 0;
321 313
322 file_pointer += file_hdr.f_nsyms * SYMNMLEN;314 file_pointer += file_hdr.f_nsyms * SYMNMLEN;
323 315
324 // OK now we are all set to write the file316 // OK now we are all set to write the file
325 317
326
327 fwrite(&file_hdr, FILHSZ, 1, f);318 fwrite(&file_hdr, FILHSZ, 1, f);
328 fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);319 fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
329 320
330 // write section headers321 // write section headers
331 for (i = 1; i < s1->nb_sections; i++) {322 for (i = 1; i < s1->nb_sections; i++) {
332 coff_sec = &section_header[i];323 coff_sec = &section_header[i];
333 tcc_sect = s1->sections[i];324 tcc_sect = s1->sections[i];
334 325
335 if (OutputTheSection(tcc_sect)) {326 if (OutputTheSection(tcc_sect)) {
336 fwrite(coff_sec, sizeof(SCNHDR), 1, f);327 fwrite(coff_sec, sizeof(SCNHDR), 1, f);
337 }328 }
338 }329 }
339 330
340 // write raw data331 // write raw data
341 for (i = 1; i < s1->nb_sections; i++) {332 for (i = 1; i < s1->nb_sections; i++) {
342 coff_sec = &section_header[i];333 coff_sec = &section_header[i];
343 tcc_sect = s1->sections[i];334 tcc_sect = s1->sections[i];
344 335
345 if (OutputTheSection(tcc_sect)) {336 if (OutputTheSection(tcc_sect)) {
346 fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);337 fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
347 }338 }
348 }339 }
349 340
350 // write relocation data341 // write relocation data
351 for (i = 1; i < s1->nb_sections; i++) {342 for (i = 1; i < s1->nb_sections; i++) {
352 coff_sec = &section_header[i];343 coff_sec = &section_header[i];
353 tcc_sect = s1->sections[i];344 tcc_sect = s1->sections[i];
354 345
355 if (OutputTheSection(tcc_sect)) {346 if (OutputTheSection(tcc_sect)) {
356 // put relocations data347 // put relocations data
357 if (coff_sec->s_nreloc > 0) {348 if (coff_sec->s_nreloc > 0) {
358 fwrite(tcc_sect->reloc,349 fwrite(tcc_sect->reloc,
359 coff_sec->s_nreloc * sizeof(struct reloc), 1, f);350 coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
360 }351 }
361 }352 }
362 }353 }
363 354
364
365 // group the symbols in order of filename, func1, func2, etc355 // group the symbols in order of filename, func1, func2, etc
366 // finally global symbols356 // finally global symbols
367 357
368 if (s1->do_debug)358 if (s1->do_debug)
369 SortSymbolTable();359 SortSymbolTable();
370 360
371 // write line no data361 // write line no data
372 362
373 for (i = 1; i < s1->nb_sections; i++) {363 for (i = 1; i < s1->nb_sections; i++) {
374 coff_sec = &section_header[i];364 coff_sec = &section_header[i];
375 tcc_sect = s1->sections[i];365 tcc_sect = s1->sections[i];
376 366
377 if (s1->do_debug && tcc_sect == stext) {367 if (s1->do_debug && tcc_sect == stext) {
378 // count how many line nos data368 // count how many line nos data
379 369
380 370 Stab_Sym* sym, *sym_end;
381 Stab_Sym *sym, *sym_end;371 char func_name[128], last_func_name[128];
382 char func_name[128], last_func_name[128];372 unsigned long func_addr, last_pc, pc;
383 unsigned long func_addr, last_pc, pc;373 const char* incl_files[INCLUDE_STACK_SIZE];
384 const char *incl_files[INCLUDE_STACK_SIZE];374 int incl_index, len, last_line_num;
385 int incl_index, len, last_line_num;375 const char* str, *p;
386 const char *str, *p;376
387 377 LINENO CoffLineNo;
388 LINENO CoffLineNo;378
389 379 func_name[0] = '\0';
390 func_name[0] = '\0';380 func_addr = 0;
391 func_addr = 0;381 incl_index = 0;
392 incl_index = 0;382 last_func_name[0] = '\0';
393 last_func_name[0] = '\0';383 last_pc = 0;
394 last_pc = 0;384 last_line_num = 1;
395 last_line_num = 1;385 sym = (Stab_Sym*)stab_section->data + 1;
396 sym = (Stab_Sym *) stab_section->data + 1;386 sym_end =
397 sym_end =387 (Stab_Sym*)(stab_section->data + stab_section->data_offset);
398 (Stab_Sym *) (stab_section->data +388
399 stab_section->data_offset);389 while (sym < sym_end) {
400 390 switch (sym->n_type) {
401 while (sym < sym_end) {391 /* function start or end */
402 switch (sym->n_type) {392 case N_FUN:
403 /* function start or end */393 if (sym->n_strx == 0) {
404 case N_FUN:394 // end of function
405 if (sym->n_strx == 0) {395
406 // end of function396 CoffLineNo.l_addr.l_paddr = last_pc;
407 397 CoffLineNo.l_lnno = last_line_num + 1;
408 CoffLineNo.l_addr.l_paddr = last_pc;398 fwrite(&CoffLineNo, 6, 1, f);
409 CoffLineNo.l_lnno = last_line_num + 1;399
410 fwrite(&CoffLineNo, 6, 1, f);400 pc = sym->n_value + func_addr;
411 401 func_name[0] = '\0';
412 pc = sym->n_value + func_addr;402 func_addr = 0;
413 func_name[0] = '\0';403 } else {
414 func_addr = 0;404 // beginning of function
415 } else {405
416 // beginning of function406 str = (const char*)stabstr_section->data + sym->n_strx;
417 407
418 str =408 p = strchr(str, ':');
419 (const char *) stabstr_section->data +409 if (!p) {
420 sym->n_strx;410 pstrcpy(func_name, sizeof(func_name), str);
421 411 } else {
422 412 len = p - str;
423 p = strchr(str, ':');413 if (len > sizeof(func_name) - 1)
424 if (!p) {414 len = sizeof(func_name) - 1;
425 pstrcpy(func_name, sizeof(func_name), str);415 memcpy(func_name, str, len);
426 } else {416 func_name[len] = '\0';
427 len = p - str;417 }
428 if (len > sizeof(func_name) - 1)418 func_addr = sym->n_value;
429 len = sizeof(func_name) - 1;419 last_pc = func_addr;
430 memcpy(func_name, str, len);420 last_line_num = -1;
431 func_name[len] = '\0';421
432 }422 // output a function begin
433 func_addr = sym->n_value;423
434 last_pc = func_addr;424 CoffLineNo.l_addr.l_symndx =
435 last_line_num = -1;425 FindCoffSymbolIndex(func_name);
436 426 CoffLineNo.l_lnno = 0;
437 // output a function begin427
438 428 fwrite(&CoffLineNo, 6, 1, f);
439 CoffLineNo.l_addr.l_symndx =429 }
440 FindCoffSymbolIndex(func_name);430 break;
441 CoffLineNo.l_lnno = 0;431
442 432 /* line number info */
443 fwrite(&CoffLineNo, 6, 1, f);433 case N_SLINE:
444 }434 pc = sym->n_value + func_addr;
445 break;435
446 436 /* XXX: slow! */
447 /* line number info */437 strcpy(last_func_name, func_name);
448 case N_SLINE:438
449 pc = sym->n_value + func_addr;439 // output a line reference
450 440
451 441 CoffLineNo.l_addr.l_paddr = last_pc;
452 /* XXX: slow! */442
453 strcpy(last_func_name, func_name);443 if (last_line_num == -1) {
454 444 CoffLineNo.l_lnno = sym->n_desc;
455 // output a line reference445 } else {
456 446 CoffLineNo.l_lnno = last_line_num + 1;
457 CoffLineNo.l_addr.l_paddr = last_pc;447 }
458 448
459 if (last_line_num == -1) {449 fwrite(&CoffLineNo, 6, 1, f);
460 CoffLineNo.l_lnno = sym->n_desc;450
461 } else {451 last_pc = pc;
462 CoffLineNo.l_lnno = last_line_num + 1;452 last_line_num = sym->n_desc;
463 }453
464 454 break;
465 fwrite(&CoffLineNo, 6, 1, f);455
466 456 /* include files */
467 last_pc = pc;457 case N_BINCL:
468 last_line_num = sym->n_desc;458 str = (const char*)stabstr_section->data + sym->n_strx;
469 459 add_incl2:
470 break;460 if (incl_index < INCLUDE_STACK_SIZE) {
471 461 incl_files[incl_index++] = str;
472 /* include files */462 }
473 case N_BINCL:463 break;
474 str =464 case N_EINCL:
475 (const char *) stabstr_section->data + sym->n_strx;465 if (incl_index > 1)
476 add_incl2:466 incl_index--;
477 if (incl_index < INCLUDE_STACK_SIZE) {467 break;
478 incl_files[incl_index++] = str;468 case N_SO:
479 }469 if (sym->n_strx == 0) {
480 break;470 incl_index = 0; /* end of translation unit */
481 case N_EINCL:471 } else {
482 if (incl_index > 1)472 str = (const char*)stabstr_section->data + sym->n_strx;
483 incl_index--;473 /* do not add path */
484 break;474 len = strlen(str);
485 case N_SO:475 if (len > 0 && str[len - 1] != '/')
486 if (sym->n_strx == 0) {476 goto add_incl2;
487 incl_index = 0; /* end of translation unit */477 }
488 } else {478 break;
489 str =479 }
490 (const char *) stabstr_section->data +480 sym++;
491 sym->n_strx;481 }
492 /* do not add path */482 }
493 len = strlen(str);
494 if (len > 0 && str[len - 1] != '/')
495 goto add_incl2;
496 }
497 break;
498 }
499 sym++;
500 }
501 }
502 }483 }
503 484
504 // write symbol table485 // write symbol table
505 if (s1->do_debug) {486 if (s1->do_debug) {
506 int k;487 int k;
507 struct syment csym;488 struct syment csym;
508 AUXFUNC auxfunc;489 AUXFUNC auxfunc;
509 AUXBF auxbf;490 AUXBF auxbf;
510 AUXEF auxef;491 AUXEF auxef;
511 int i;492 int i;
512 Elf32_Sym *p;493 Elf32_Sym* p;
513 const char *name;494 const char* name;
514 int nstr;495 int nstr;
515 int n = 0;496 int n = 0;
516 497
517 Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);498 Coff_str_table = (char*)tcc_malloc(MAX_STR_TABLE);
518 pCoff_str_table = Coff_str_table;499 pCoff_str_table = Coff_str_table;
519 nstr = 0;500 nstr = 0;
520 501
521 p = (Elf32_Sym *) symtab_section->data;502 p = (Elf32_Sym*)symtab_section->data;
522 503
523 504 for (i = 0; i < nb_syms; i++) {
524 for (i = 0; i < nb_syms; i++) {505
525 506 name = symtab_section->link->data + p->st_name;
526 name = symtab_section->link->data + p->st_name;507
527 508 for (k = 0; k < 8; k++)
528 for (k = 0; k < 8; k++)509 csym._n._n_name[k] = 0;
529 csym._n._n_name[k] = 0;510
530 511 if (strlen(name) <= 8) {
531 if (strlen(name) <= 8) {512 strcpy(csym._n._n_name, name);
532 strcpy(csym._n._n_name, name);513 } else {
533 } else {514 if (pCoff_str_table - Coff_str_table + strlen(name) >
534 if (pCoff_str_table - Coff_str_table + strlen(name) >515 MAX_STR_TABLE - 1)
535 MAX_STR_TABLE - 1)516 tcc_error("String table too large");
536 tcc_error("String table too large");517
537 518 csym._n._n_n._n_zeroes = 0;
538 csym._n._n_n._n_zeroes = 0;519 csym._n._n_n._n_offset = pCoff_str_table - Coff_str_table + 4;
539 csym._n._n_n._n_offset =520
540 pCoff_str_table - Coff_str_table + 4;521 strcpy(pCoff_str_table, name);
541 522 pCoff_str_table += strlen(name) + 1; // skip over null
542 strcpy(pCoff_str_table, name);523 nstr++;
543 pCoff_str_table += strlen(name) + 1; // skip over null524 }
544 nstr++;525
545 }526 if (p->st_info == 4) {
546 527 // put a filename symbol
547 if (p->st_info == 4) {528 csym.n_value = 33; // ?????
548 // put a filename symbol529 csym.n_scnum = N_DEBUG;
549 csym.n_value = 33; // ?????530 csym.n_type = 0;
550 csym.n_scnum = N_DEBUG;531 csym.n_sclass = C_FILE;
551 csym.n_type = 0;532 csym.n_numaux = 0;
552 csym.n_sclass = C_FILE;533 fwrite(&csym, 18, 1, f);
553 csym.n_numaux = 0;534 n++;
554 fwrite(&csym, 18, 1, f);535
555 n++;536 } else if (p->st_info == 0x12) {
556 537 // find the function data
557 } else if (p->st_info == 0x12) {538
558 // find the function data539 for (k = 0; k < nFuncs; k++) {
559 540 if (strcmp(name, Func[k]) == 0)
560 for (k = 0; k < nFuncs; k++) {541 break;
561 if (strcmp(name, Func[k]) == 0)542 }
562 break;543
563 }544 if (k >= nFuncs) {
564 545 tcc_error("debug info can't find function: %s", name);
565 if (k >= nFuncs) {546 }
566 tcc_error("debug info can't find function: %s", name);547 // put a Function Name
567 }548
568 // put a Function Name549 csym.n_value = p->st_value; // physical address
569 550 csym.n_scnum = CoffTextSectionNo;
570 csym.n_value = p->st_value; // physical address551 csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
571 csym.n_scnum = CoffTextSectionNo;552 csym.n_sclass = C_EXT;
572 csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);553 csym.n_numaux = 1;
573 csym.n_sclass = C_EXT;554 fwrite(&csym, 18, 1, f);
574 csym.n_numaux = 1;555
575 fwrite(&csym, 18, 1, f);556 // now put aux info
576 557
577 // now put aux info558 auxfunc.tag = 0;
578 559 auxfunc.size = EndAddress[k] - p->st_value;
579 auxfunc.tag = 0;560 auxfunc.fileptr = LineNoFilePtr[k];
580 auxfunc.size = EndAddress[k] - p->st_value;561 auxfunc.nextsym = n + 6; // tktk
581 auxfunc.fileptr = LineNoFilePtr[k];562 auxfunc.dummy = 0;
582 auxfunc.nextsym = n + 6; // tktk563 fwrite(&auxfunc, 18, 1, f);
583 auxfunc.dummy = 0;564
584 fwrite(&auxfunc, 18, 1, f);565 // put a .bf
585 566
586 // put a .bf567 strcpy(csym._n._n_name, ".bf");
587 568 csym.n_value = p->st_value; // physical address
588 strcpy(csym._n._n_name, ".bf");569 csym.n_scnum = CoffTextSectionNo;
589 csym.n_value = p->st_value; // physical address570 csym.n_type = 0;
590 csym.n_scnum = CoffTextSectionNo;571 csym.n_sclass = C_FCN;
591 csym.n_type = 0;572 csym.n_numaux = 1;
592 csym.n_sclass = C_FCN;573 fwrite(&csym, 18, 1, f);
593 csym.n_numaux = 1;574
594 fwrite(&csym, 18, 1, f);575 // now put aux info
595 576
596 // now put aux info577 auxbf.regmask = 0;
597 578 auxbf.lineno = 0;
598 auxbf.regmask = 0;579 auxbf.nentries = FuncEntries[k];
599 auxbf.lineno = 0;580 auxbf.localframe = 0;
600 auxbf.nentries = FuncEntries[k];581 auxbf.nextentry = n + 6;
601 auxbf.localframe = 0;582 auxbf.dummy = 0;
602 auxbf.nextentry = n + 6;583 fwrite(&auxbf, 18, 1, f);
603 auxbf.dummy = 0;584
604 fwrite(&auxbf, 18, 1, f);585 // put a .ef
605 586
606 // put a .ef587 strcpy(csym._n._n_name, ".ef");
607 588 csym.n_value = EndAddress[k]; // physical address
608 strcpy(csym._n._n_name, ".ef");589 csym.n_scnum = CoffTextSectionNo;
609 csym.n_value = EndAddress[k]; // physical address590 csym.n_type = 0;
610 csym.n_scnum = CoffTextSectionNo;591 csym.n_sclass = C_FCN;
611 csym.n_type = 0;592 csym.n_numaux = 1;
612 csym.n_sclass = C_FCN;593 fwrite(&csym, 18, 1, f);
613 csym.n_numaux = 1;594
614 fwrite(&csym, 18, 1, f);595 // now put aux info
615 596
616 // now put aux info597 auxef.dummy = 0;
617 598 auxef.lineno = LastLineNo[k];
618 auxef.dummy = 0;599 auxef.dummy1 = 0;
619 auxef.lineno = LastLineNo[k];600 auxef.dummy2 = 0;
620 auxef.dummy1 = 0;601 auxef.dummy3 = 0;
621 auxef.dummy2 = 0;602 auxef.dummy4 = 0;
622 auxef.dummy3 = 0;603 fwrite(&auxef, 18, 1, f);
623 auxef.dummy4 = 0;604
624 fwrite(&auxef, 18, 1, f);605 n += 6;
625 606
626 n += 6;607 } else {
627 608 // try an put some type info
628 } else {609
629 // try an put some type info610 if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
630 611 csym.n_type = T_DOUBLE; // int
631 if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {612 csym.n_sclass = C_EXT;
632 csym.n_type = T_DOUBLE; // int613 } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
633 csym.n_sclass = C_EXT;614 csym.n_type = T_FLOAT;
634 } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {615 csym.n_sclass = C_EXT;
635 csym.n_type = T_FLOAT;616 } else if ((p->st_other & VT_BTYPE) == VT_INT) {
636 csym.n_sclass = C_EXT;617 csym.n_type = T_INT; // int
637 } else if ((p->st_other & VT_BTYPE) == VT_INT) {618 csym.n_sclass = C_EXT;
638 csym.n_type = T_INT; // int619 } else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
639 csym.n_sclass = C_EXT;620 csym.n_type = T_SHORT;
640 } else if ((p->st_other & VT_BTYPE) == VT_SHORT) {621 csym.n_sclass = C_EXT;
641 csym.n_type = T_SHORT;622 } else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
642 csym.n_sclass = C_EXT;623 csym.n_type = T_CHAR;
643 } else if ((p->st_other & VT_BTYPE) == VT_BYTE) {624 csym.n_sclass = C_EXT;
644 csym.n_type = T_CHAR;625 } else {
645 csym.n_sclass = C_EXT;626 csym.n_type = T_INT; // just mark as a label
646 } else {627 csym.n_sclass = C_LABEL;
647 csym.n_type = T_INT; // just mark as a label628 }
648 csym.n_sclass = C_LABEL;629
649 }630 csym.n_value = p->st_value;
650 631 csym.n_scnum = 2;
651 632 csym.n_numaux = 1;
652 csym.n_value = p->st_value;633 fwrite(&csym, 18, 1, f);
653 csym.n_scnum = 2;634
654 csym.n_numaux = 1;635 auxfunc.tag = 0;
655 fwrite(&csym, 18, 1, f);636 auxfunc.size = 0x20;
656 637 auxfunc.fileptr = 0;
657 auxfunc.tag = 0;638 auxfunc.nextsym = 0;
658 auxfunc.size = 0x20;639 auxfunc.dummy = 0;
659 auxfunc.fileptr = 0;640 fwrite(&auxfunc, 18, 1, f);
660 auxfunc.nextsym = 0;641 n++;
661 auxfunc.dummy = 0;642 n++;
662 fwrite(&auxfunc, 18, 1, f);643 }
663 n++;644
664 n++;645 p++;
665 646 }
666 }
667
668 p++;
669 }
670 }647 }
671 648
672 if (s1->do_debug) {649 if (s1->do_debug) {
673 // write string table650 // write string table
674 651
675 // first write the size652 // first write the size
676 i = pCoff_str_table - Coff_str_table;653 i = pCoff_str_table - Coff_str_table;
677 fwrite(&i, 4, 1, f);654 fwrite(&i, 4, 1, f);
678 655
679 // then write the strings656 // then write the strings
680 fwrite(Coff_str_table, i, 1, f);657 fwrite(Coff_str_table, i, 1, f);
681 658
682 tcc_free(Coff_str_table);659 tcc_free(Coff_str_table);
683 }660 }
684 661
685 return 0;662 return 0;
686}663}
687 664
688
689
690// group the symbols in order of filename, func1, func2, etc665// group the symbols in order of filename, func1, func2, etc
691// finally global symbols666// finally global symbols
692 667
693void SortSymbolTable(void)668void SortSymbolTable(void)
694{669{
695 int i, j, k, n = 0;670 int i, j, k, n = 0;
696 Elf32_Sym *p, *p2, *NewTable;671 Elf32_Sym* p, *p2, *NewTable;
697 char *name, *name2;672 char* name, *name2;
698
699 NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
700 673
701 p = (Elf32_Sym *) symtab_section->data;674 NewTable = (Elf32_Sym*)tcc_malloc(nb_syms * sizeof(Elf32_Sym));
702 675
676 p = (Elf32_Sym*)symtab_section->data;
703 677
704 // find a file symbol, copy it over678 // find a file symbol, copy it over
705 // then scan the whole symbol list and copy any function679 // then scan the whole symbol list and copy any function
706 // symbols that match the file association680 // symbols that match the file association
707 681
708 for (i = 0; i < nb_syms; i++) {682 for (i = 0; i < nb_syms; i++) {
709 if (p->st_info == 4) {683 if (p->st_info == 4) {
710 name = (char *) symtab_section->link->data + p->st_name;684 name = (char*)symtab_section->link->data + p->st_name;
711 685
712 // this is a file symbol, copy it over686 // this is a file symbol, copy it over
713 687
714 NewTable[n++] = *p;688 NewTable[n++] = *p;
715 689
716 p2 = (Elf32_Sym *) symtab_section->data;690 p2 = (Elf32_Sym*)symtab_section->data;
717 691
718 for (j = 0; j < nb_syms; j++) {692 for (j = 0; j < nb_syms; j++) {
719 if (p2->st_info == 0x12) {693 if (p2->st_info == 0x12) {
720 // this is a func symbol694 // this is a func symbol
721 695
722 name2 =696 name2 = (char*)symtab_section->link->data + p2->st_name;
723 (char *) symtab_section->link->data + p2->st_name;
724 697
725 // find the function data index698 // find the function data index
726 699
727 for (k = 0; k < nFuncs; k++) {700 for (k = 0; k < nFuncs; k++) {
728 if (strcmp(name2, Func[k]) == 0)701 if (strcmp(name2, Func[k]) == 0)
729 break;702 break;
730 }703 }
731 704
732 if (k >= nFuncs) {705 if (k >= nFuncs) {
733 tcc_error("debug (sort) info can't find function: %s", name2);706 tcc_error("debug (sort) info can't find function: %s",
734 }707 name2);
708 }
735 709
736 if (strcmp(AssociatedFile[k], name) == 0) {710 if (strcmp(AssociatedFile[k], name) == 0) {
737 // yes they match copy it over711 // yes they match copy it over
738 712
739 NewTable[n++] = *p2;713 NewTable[n++] = *p2;
740 }714 }
741 }715 }
742 p2++;716 p2++;
743 }717 }
744 }718 }
745 p++;719 p++;
746 }720 }
747 721
748 // now all the filename and func symbols should have been copied over722 // now all the filename and func symbols should have been copied over
749 // copy all the rest over (all except file and funcs)723 // copy all the rest over (all except file and funcs)
750 724
751 p = (Elf32_Sym *) symtab_section->data;725 p = (Elf32_Sym*)symtab_section->data;
752 for (i = 0; i < nb_syms; i++) {726 for (i = 0; i < nb_syms; i++) {
753 if (p->st_info != 4 && p->st_info != 0x12) {727 if (p->st_info != 4 && p->st_info != 0x12) {
754 NewTable[n++] = *p;728 NewTable[n++] = *p;
755 }729 }
756 p++;730 p++;
757 }731 }
758 732
759 if (n != nb_syms)733 if (n != nb_syms)
760 tcc_error("Internal Compiler error, debug info");734 tcc_error("Internal Compiler error, debug info");
761 735
762 // copy it all back736 // copy it all back
763 737
764 p = (Elf32_Sym *) symtab_section->data;738 p = (Elf32_Sym*)symtab_section->data;
765 for (i = 0; i < nb_syms; i++) {739 for (i = 0; i < nb_syms; i++) {
766 *p++ = NewTable[i];740 *p++ = NewTable[i];
767 }741 }
768 742
769 tcc_free(NewTable);743 tcc_free(NewTable);
770}744}
771 745
772 746int FindCoffSymbolIndex(const char* func_name)
773int FindCoffSymbolIndex(const char *func_name)
774{747{
775 int i, n = 0;748 int i, n = 0;
776 Elf32_Sym *p;749 Elf32_Sym* p;
777 char *name;750 char* name;
778 751
779 p = (Elf32_Sym *) symtab_section->data;752 p = (Elf32_Sym*)symtab_section->data;
780 753
781 for (i = 0; i < nb_syms; i++) {754 for (i = 0; i < nb_syms; i++) {
782 755
783 name = (char *) symtab_section->link->data + p->st_name;756 name = (char*)symtab_section->link->data + p->st_name;
784 757
785 if (p->st_info == 4) {758 if (p->st_info == 4) {
786 // put a filename symbol759 // put a filename symbol
787 n++;760 n++;
788 } else if (p->st_info == 0x12) {761 } else if (p->st_info == 0x12) {
789 762
790 if (strcmp(func_name, name) == 0)763 if (strcmp(func_name, name) == 0)
791 return n;764 return n;
792 765
793 n += 6;766 n += 6;
794 767
795 // put a Function Name768 // put a Function Name
796 769
797 // now put aux info770 // now put aux info
798 771
799 // put a .bf772 // put a .bf
800 773
801 // now put aux info774 // now put aux info
802 775
803 // put a .ef776 // put a .ef
804 777
805 // now put aux info778 // now put aux info
806 779
807 } else {780 } else {
808 n += 2;781 n += 2;
809 }782 }
810 783
811 p++;784 p++;
812 }785 }
813 786
814 return n; // total number of symbols787 return n; // total number of symbols
815}788}
816 789
817int OutputTheSection(Section * sect)790int OutputTheSection(Section* sect)
818{791{
819 const char *s = sect->name;792 const char* s = sect->name;
820 793
821 if (!strcmp(s, ".text"))794 if (!strcmp(s, ".text"))
822 return 1;795 return 1;
823 else if (!strcmp(s, ".data"))796 else if (!strcmp(s, ".data"))
824 return 1;797 return 1;
825 else798 else
826 return 0;799 return 0;
827}800}
828 801
829short int GetCoffFlags(const char *s)802short int GetCoffFlags(const char* s)
830{803{
831 if (!strcmp(s, ".text"))804 if (!strcmp(s, ".text"))
832 return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;805 return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
833 else if (!strcmp(s, ".data"))806 else if (!strcmp(s, ".data"))
834 return STYP_DATA;807 return STYP_DATA;
835 else if (!strcmp(s, ".bss"))808 else if (!strcmp(s, ".bss"))
836 return STYP_BSS;809 return STYP_BSS;
837 else if (!strcmp(s, ".stack"))810 else if (!strcmp(s, ".stack"))
838 return STYP_BSS | STYP_ALIGN | 0x200;811 return STYP_BSS | STYP_ALIGN | 0x200;
839 else if (!strcmp(s, ".cinit"))812 else if (!strcmp(s, ".cinit"))
840 return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;813 return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
841 else814 else
842 return 0;815 return 0;
843}816}
844 817
845Section *FindSection(TCCState * s1, const char *sname)818Section* FindSection(TCCState* s1, const char* sname)
846{819{
847 Section *s;820 Section* s;
848 int i;821 int i;
849 822
850 for (i = 1; i < s1->nb_sections; i++) {823 for (i = 1; i < s1->nb_sections; i++) {
851 s = s1->sections[i];824 s = s1->sections[i];
852 825
853 if (!strcmp(sname, s->name))826 if (!strcmp(sname, s->name))
854 return s;827 return s;
855 }828 }
856 829
857 tcc_error("could not find section %s", sname);830 tcc_error("could not find section %s", sname);
858 return 0;831 return 0;
859}832}
860 833
861ST_FUNC int tcc_load_coff(TCCState * s1, int fd)834ST_FUNC int tcc_load_coff(TCCState* s1, int fd)
862{835{
863// tktk TokenSym *ts;836 // tktk TokenSym *ts;
864 837
865 FILE *f;838 FILE* f;
866 unsigned int str_size;839 unsigned int str_size;
867 char *Coff_str_table, *name;840 char* Coff_str_table, *name;
868 int i, k;841 int i, k;
869 struct syment csym;842 struct syment csym;
870 char name2[9];843 char name2[9];
871 FILHDR file_hdr; /* FILE HEADER STRUCTURE */844 FILHDR file_hdr; /* FILE HEADER STRUCTURE */
872 845
873 f = fdopen(fd, "rb");846 f = fdopen(fd, "rb");
874 if (!f) {847 if (!f) {
875 tcc_error("Unable to open .out file for input");848 tcc_error("Unable to open .out file for input");
876 }849 }
877 850
878 if (fread(&file_hdr, FILHSZ, 1, f) != 1)851 if (fread(&file_hdr, FILHSZ, 1, f) != 1)
879 tcc_error("error reading .out file for input");852 tcc_error("error reading .out file for input");
880 853
881 if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)854 if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
882 tcc_error("error reading .out file for input");855 tcc_error("error reading .out file for input");
883 856
884 // first read the string table857 // first read the string table
885 858
886 if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))859 if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
887 tcc_error("error reading .out file for input");860 tcc_error("error reading .out file for input");
888 861
889 if (fread(&str_size, sizeof(int), 1, f) != 1)862 if (fread(&str_size, sizeof(int), 1, f) != 1)
890 tcc_error("error reading .out file for input");863 tcc_error("error reading .out file for input");
891
892 864
893 Coff_str_table = (char *) tcc_malloc(str_size);865 Coff_str_table = (char*)tcc_malloc(str_size);
894 866
895 if (fread(Coff_str_table, str_size - 4, 1, f) != 1)867 if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
896 tcc_error("error reading .out file for input");868 tcc_error("error reading .out file for input");
897 869
898 // read/process all the symbols870 // read/process all the symbols
899 871
900 // seek back to symbols872 // seek back to symbols
901 873
902 if (fseek(f, file_hdr.f_symptr, SEEK_SET))874 if (fseek(f, file_hdr.f_symptr, SEEK_SET))
903 tcc_error("error reading .out file for input");875 tcc_error("error reading .out file for input");
904 876
905 for (i = 0; i < file_hdr.f_nsyms; i++) {877 for (i = 0; i < file_hdr.f_nsyms; i++) {
906 if (fread(&csym, SYMESZ, 1, f) != 1)878 if (fread(&csym, SYMESZ, 1, f) != 1)
907 tcc_error("error reading .out file for input");879 tcc_error("error reading .out file for input");
908 880
909 if (csym._n._n_n._n_zeroes == 0) {881 if (csym._n._n_n._n_zeroes == 0) {
910 name = Coff_str_table + csym._n._n_n._n_offset - 4;882 name = Coff_str_table + csym._n._n_n._n_offset - 4;
911 } else {883 } else {
912 name = csym._n._n_name;884 name = csym._n._n_name;
913 885
914 if (name[7] != 0) {886 if (name[7] != 0) {
915 for (k = 0; k < 8; k++)887 for (k = 0; k < 8; k++)
916 name2[k] = name[k];888 name2[k] = name[k];
917 889
918 name2[8] = 0;890 name2[8] = 0;
919 891
920 name = name2;892 name = name2;
921 }893 }
922 }894 }
923// if (strcmp("_DAC_Buffer",name)==0) // tktk895 // if (strcmp("_DAC_Buffer",name)==0) // tktk
924// name[0]=0;896 // name[0]=0;
925 897
926 if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures898 if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) ||
927 (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure899 ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) ||
928 (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles900 (csym.n_type == 0x4 && csym.n_sclass == 0x2) ||
929 (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats901 (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
930 {902 (csym.n_type == 0x18 &&
931 // strip off any leading underscore (except for other main routine)903 csym.n_sclass == 0x2) || // pointer to structure
932 904 (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
933 if (name[0] == '_' && strcmp(name, "_main") != 0)905 (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
934 name++;906 {
935 907 // strip off any leading underscore (except for other main routine)
936 tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);908
937 }909 if (name[0] == '_' && strcmp(name, "_main") != 0)
938 // skip any aux records910 name++;
939 911
940 if (csym.n_numaux == 1) {912 tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
941 if (fread(&csym, SYMESZ, 1, f) != 1)913 }
942 tcc_error("error reading .out file for input");914 // skip any aux records
943 i++;915
944 }916 if (csym.n_numaux == 1) {
917 if (fread(&csym, SYMESZ, 1, f) != 1)
918 tcc_error("error reading .out file for input");
919 i++;
920 }
945 }921 }
946 922
947 return 0;923 return 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t