~ubuntu-branches/ubuntu/oneiric/tcc/oneiric

« back to all changes in this revision

Viewing changes to arm-gen.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Preud'homme, Aurélien GÉRÔME, Thomas Preud'homme
  • Date: 2008-06-16 03:31:38 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 lenny)
  • Revision ID: james.westby@ubuntu.com-20080616033138-hqo92o7adc6nn9fa
Tags: 0.9.24-1
[ Aurélien GÉRÔME ]
* Change my email address in the Maintainer field.
* Bump Standards-Version to 3.8.0.
* Remove no longer used XS-Vcs-Git and XS-Vcs-Browser fields.
* Add the DM-Upload-Allowed field for Arthur.

[ Thomas Preud'homme ]
* New Upstream Version
  - tcc now supports typename as structure field name (closes: #278698)
  - A long long value used as a test expression ignores the
    upper 32 bits at runtime (closes: #304082)
* Remove unecessary patches:
  - 352202_fix_int_overflow.diff
  - 283066_add_va_copy_define.diff (already disabled)
  - 430209_fix_bound_check_error.diff
* Clean all patches (no fuzz or offset problem anymore)
* Add patch from Bradley Smith to allow compilation with gcc 4.3
  (closes: #474883)
* Add tcc-doc_texi_formatting.diff to correct formatting of tcc-doc.texi

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
21
 */
22
22
 
 
23
#ifdef TCC_ARM_EABI
 
24
#define TCC_ARM_VFP
 
25
#endif
 
26
 
 
27
 
23
28
/* number of available registers */
 
29
#ifdef TCC_ARM_VFP
 
30
#define NB_REGS            13
 
31
#else
24
32
#define NB_REGS             9
 
33
#endif
25
34
 
26
35
/* a register can belong to several classes. The classes must be
27
36
   sorted from more general to more precise (see gv2() code which does
37
46
#define RC_F1      0x0100
38
47
#define RC_F2      0x0200
39
48
#define RC_F3      0x0400
 
49
#ifdef TCC_ARM_VFP
 
50
#define RC_F4      0x0800
 
51
#define RC_F5      0x1000
 
52
#define RC_F6      0x2000
 
53
#define RC_F7      0x4000
 
54
#endif
40
55
#define RC_IRET    RC_R0  /* function return: integer register */
41
56
#define RC_LRET    RC_R1  /* function return: second integer register */
42
57
#define RC_FRET    RC_F0  /* function return: float register */
52
67
    TREG_F1,
53
68
    TREG_F2,
54
69
    TREG_F3,
 
70
#ifdef TCC_ARM_VFP
 
71
    TREG_F4,
 
72
    TREG_F5,
 
73
    TREG_F6,
 
74
    TREG_F7,
 
75
#endif
55
76
};
56
77
 
57
78
int reg_classes[NB_REGS] = {
64
85
    /* f1 */ RC_FLOAT | RC_F1,
65
86
    /* f2 */ RC_FLOAT | RC_F2,
66
87
    /* f3 */ RC_FLOAT | RC_F3,
 
88
#ifdef TCC_ARM_VFP
 
89
 /* d4/s8 */ RC_FLOAT | RC_F4,
 
90
/* d5/s10 */ RC_FLOAT | RC_F5,
 
91
/* d6/s12 */ RC_FLOAT | RC_F6,
 
92
/* d7/s14 */ RC_FLOAT | RC_F7,
 
93
#endif
67
94
};
68
95
 
69
96
static int two2mask(int a,int b) {
74
101
  return reg_classes[r]&~(RC_INT|RC_FLOAT);
75
102
}
76
103
 
 
104
#ifdef TCC_ARM_VFP
 
105
#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0)
 
106
#endif
 
107
 
77
108
/* return registers for function */
78
109
#define REG_IRET TREG_R0 /* single word int return register */
79
110
#define REG_LRET TREG_R1 /* second word return register (for long long) */
86
117
   are directly pushed on stack. */
87
118
//#define FUNC_STRUCT_PARAM_AS_PTR
88
119
 
 
120
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
 
121
static CType float_type, double_type, func_float_type, func_double_type;
 
122
#endif
 
123
 
89
124
/* pointer size, in bytes */
90
125
#define PTR_SIZE 4
91
126
 
92
127
/* long double size and alignment, in bytes */
93
 
#define LDOUBLE_SIZE  8
 
128
#ifdef TCC_ARM_VFP
 
129
#define LDOUBLE_SIZE  8
 
130
#endif
 
131
 
 
132
#ifndef LDOUBLE_SIZE
 
133
#define LDOUBLE_SIZE  8
 
134
#endif
 
135
 
 
136
#ifdef TCC_ARM_EABI
 
137
#define LDOUBLE_ALIGN 8
 
138
#else
94
139
#define LDOUBLE_ALIGN 4
 
140
#endif
 
141
 
95
142
/* maximum alignment (for aligned attribute support) */
96
143
#define MAX_ALIGN     8
97
144
 
112
159
 
113
160
/******************************************************/
114
161
static unsigned long func_sub_sp_offset,last_itod_magic;
 
162
static int leaffunc;
115
163
 
116
164
void o(unsigned long i)
117
165
{
287
335
  gsym_addr(t, ind);
288
336
}
289
337
 
 
338
#ifdef TCC_ARM_VFP
 
339
static unsigned long vfpr(int r)
 
340
{
 
341
  if(r<TREG_F0 || r>TREG_F7)
 
342
    error("compiler error! register %i is no vfp register",r);
 
343
  return r-5;
 
344
}
 
345
#else
290
346
static unsigned long fpr(int r)
291
347
{
292
348
  if(r<TREG_F0 || r>TREG_F3)
293
 
    error("compiler error! register %i is no fp register\n",r);
 
349
    error("compiler error! register %i is no fpa register",r);
294
350
  return r-5;
295
351
}
 
352
#endif
296
353
 
297
354
static unsigned long intr(int r)
298
355
{
299
356
  if(r==4)
300
357
    return 12;
301
358
  if((r<0 || r>4) && r!=14)
302
 
    error("compiler error! register %i is no int register\n",r);
 
359
    error("compiler error! register %i is no int register",r);
303
360
  return r;
304
361
}
305
362
 
335
392
  switch(cc)
336
393
  {
337
394
    case TOK_ULT:
338
 
      return 0x30000000;
 
395
      return 0x30000000; /* CC/LO */
339
396
    case TOK_UGE:
340
 
      return 0x20000000;
 
397
      return 0x20000000; /* CS/HS */
341
398
    case TOK_EQ:
342
 
      return 0x00000000;
 
399
      return 0x00000000; /* EQ */
343
400
    case TOK_NE:
344
 
      return 0x10000000;
 
401
      return 0x10000000; /* NE */
345
402
    case TOK_ULE:
346
 
      return 0x90000000;
 
403
      return 0x90000000; /* LS */
347
404
    case TOK_UGT:
348
 
      return 0x80000000;
 
405
      return 0x80000000; /* HI */
 
406
    case TOK_Nset:
 
407
      return 0x40000000; /* MI */
 
408
    case TOK_Nclear:
 
409
      return 0x50000000; /* PL */
349
410
    case TOK_LT:
350
 
      return 0xB0000000;
 
411
      return 0xB0000000; /* LT */
351
412
    case TOK_GE:
352
 
      return 0xA0000000;
 
413
      return 0xA0000000; /* GE */
353
414
    case TOK_LE:
354
 
      return 0xD0000000;
 
415
      return 0xD0000000; /* LE */
355
416
    case TOK_GT:
356
 
      return 0xC0000000;
 
417
      return 0xC0000000; /* GT */
357
418
  }
358
419
  error("unexpected condition code");
359
 
  return 0xE0000000;
 
420
  return 0xE0000000; /* AL */
360
421
}
361
422
 
362
423
static int negcc(int cc)
375
436
      return TOK_UGT;
376
437
    case TOK_UGT:
377
438
      return TOK_ULE;
 
439
    case TOK_Nset:
 
440
      return TOK_Nclear;
 
441
    case TOK_Nclear:
 
442
      return TOK_Nset;
378
443
    case TOK_LT:
379
444
      return TOK_GE;
380
445
    case TOK_GE:
432
497
    if(v == VT_LOCAL) {
433
498
      if(is_float(ft)) {
434
499
        calcaddr(&base,&fc,&sign,1020,2);
 
500
#ifdef TCC_ARM_VFP
 
501
        op=0xED100A00; /* flds */
 
502
        if(!sign)
 
503
          op|=0x800000;
 
504
        if ((ft & VT_BTYPE) != VT_FLOAT)
 
505
          op|=0x100;   /* flds -> fldd */
 
506
        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
 
507
#else
435
508
        op=0xED100100;
436
509
        if(!sign)
437
510
          op|=0x800000;
445
518
          op|=0x400000;
446
519
#endif
447
520
        o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
448
 
      } else if((ft & VT_TYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_SHORT) {
 
521
#endif
 
522
      } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE
 
523
                || (ft & VT_BTYPE) == VT_SHORT) {
449
524
        calcaddr(&base,&fc,&sign,255,0);
450
525
        op=0xE1500090;
451
526
        if ((ft & VT_BTYPE) == VT_SHORT)
504
579
      return;
505
580
    } else if (v < VT_CONST) {
506
581
      if(is_float(ft))
 
582
#ifdef TCC_ARM_VFP
 
583
        o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
 
584
#else
507
585
        o(0xEE008180|(fpr(r)<<12)|fpr(v));
 
586
#endif
508
587
      else
509
588
        o(0xE1A00000|(intr(r)<<12)|intr(v));
510
589
      return;
550
629
    if(v == VT_LOCAL) {
551
630
       if(is_float(ft)) {
552
631
        calcaddr(&base,&fc,&sign,1020,2);
 
632
#ifdef TCC_ARM_VFP
 
633
        op=0xED000A00; /* fsts */
 
634
        if(!sign) 
 
635
          op|=0x800000; 
 
636
        if ((ft & VT_BTYPE) != VT_FLOAT) 
 
637
          op|=0x100;   /* fsts -> fstd */
 
638
        o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16));
 
639
#else
553
640
        op=0xED000100;
554
641
        if(!sign)
555
642
          op|=0x800000;
563
650
          op|=0x400000;
564
651
#endif
565
652
        o(op|(fpr(r)<<12)|(fc>>2)|(base<<16));
 
653
#endif
566
654
        return;
567
655
      } else if((ft & VT_BTYPE) == VT_SHORT) {
568
656
        calcaddr(&base,&fc,&sign,255,0);
635
723
  r = vtop->r & VT_VALMASK;
636
724
  if (r == VT_CMP || (r & ~1) == VT_JMP)
637
725
    gv(RC_INT);
 
726
#ifdef TCC_ARM_EABI
 
727
  if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT
 
728
     && type_size(&vtop[-nb_args].type, &align) <= 4) {
 
729
    SValue tmp;
 
730
    tmp=vtop[-nb_args];
 
731
    vtop[-nb_args]=vtop[-nb_args+1];
 
732
    vtop[-nb_args+1]=tmp;
 
733
    --nb_args;
 
734
  }
 
735
  
 
736
  vpushi(0);
 
737
  vtop->type.t = VT_LLONG;
 
738
  args_size = 0;
 
739
  for(i = nb_args + 1 ; i-- ;) {
 
740
    size = type_size(&vtop[-i].type, &align);
 
741
    if(args_size & (align-1)) {
 
742
      vpushi(0);
 
743
      vtop->type.t = VT_VOID; /* padding */
 
744
      vrott(i+2);
 
745
      args_size += 4;
 
746
      ++nb_args;
 
747
    }
 
748
    args_size += (size + 3) & -4;
 
749
  }
 
750
  vtop--;
 
751
#endif
638
752
  args_size = 0;
639
753
  for(i = nb_args ; i-- && args_size < 16 ;) {
640
 
    if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) {
 
754
    switch(vtop[-i].type.t & VT_BTYPE) {
 
755
      case VT_STRUCT:
 
756
      case VT_FLOAT:
 
757
      case VT_DOUBLE:
 
758
      case VT_LDOUBLE:
641
759
      size = type_size(&vtop[-i].type, &align);
642
 
      size = (size + 3) & ~3;
 
760
        size = (size + 3) & -4;
643
761
      args_size += size;
644
 
    } else if ((vtop[-i].type.t & VT_BTYPE) == VT_FLOAT)
645
 
      args_size += 4;
646
 
    else if ((vtop[-i].type.t & VT_BTYPE) == VT_DOUBLE)
647
 
      args_size += 8;
648
 
    else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE)
649
 
      args_size += LDOUBLE_SIZE;
650
 
    else {
 
762
        break;
 
763
      default:
651
764
      plan[nb_args-1-i][0]=args_size/4;
652
765
      args_size += 4;
653
766
      if ((vtop[-i].type.t & VT_BTYPE) == VT_LLONG && args_size < 16) {
662
775
    if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
663
776
      size = type_size(&vtop->type, &align);
664
777
      /* align to stack align size */
665
 
      size = (size + 3) & ~3;
 
778
      size = (size + 3) & -4;
666
779
      /* allocate the necessary size on stack */
667
780
      gadd_sp(-size);
668
781
      /* generate structure store */
674
787
      vtop--;
675
788
      args_size += size;
676
789
    } else if (is_float(vtop->type.t)) {
 
790
#ifdef TCC_ARM_VFP
 
791
      r=vfpr(gv(RC_FLOAT))<<12;
 
792
      size=4;
 
793
      if ((vtop->type.t & VT_BTYPE) != VT_FLOAT)
 
794
      {
 
795
        size=8;
 
796
        r|=0x101; /* fstms -> fstmd */
 
797
      }
 
798
      o(0xED2D0A01+r);
 
799
#else
677
800
      r=fpr(gv(RC_FLOAT))<<12;
678
801
      if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
679
802
        size = 4;
688
811
        r|=0x8000;
689
812
 
690
813
      o(0xED2D0100|r|(size>>2));
 
814
#endif
691
815
      vtop--;
692
816
      args_size += size;
693
817
    } else {
718
842
        s=regmask(plan[nb_args-i-1][0]);
719
843
        todo&=~(1<<plan[nb_args-i-1][0]);
720
844
      }
721
 
      if(s==RC_INT) {
 
845
#ifdef TCC_ARM_EABI
 
846
      if(vtop->type.t == VT_VOID) {
 
847
        if(s == RC_INT)
 
848
          o(0xE24DD004); /* sub sp,sp,#4 */
 
849
        vtop--;
 
850
      } else
 
851
#endif      
 
852
      if(s == RC_INT) {
722
853
        r = gv(s);
723
854
        o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */
724
855
        vtop--;
733
864
    gv(plan2[i]);
734
865
    vrott(keep);
735
866
  }
736
 
  save_regs(keep); /* save used temporary registers */
 
867
save_regs(keep); /* save used temporary registers */
737
868
  keep++;
738
869
  if(args_size) {
739
870
    int n;
758
889
  gcall_or_jmp(0);
759
890
  if (args_size)
760
891
      gadd_sp(args_size);
 
892
#ifdef TCC_ARM_EABI
 
893
  if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT
 
894
     && type_size(&vtop->type.ref->type, &align) <= 4)
 
895
  {
 
896
    store(REG_IRET,vtop-keep);
 
897
    ++keep;
 
898
  }
 
899
#ifdef TCC_ARM_VFP
 
900
  else if(is_float(vtop->type.ref->type.t)) {
 
901
    if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) {
 
902
      o(0xEE000A10); /* fmsr s0,r0 */
 
903
    } else {
 
904
      o(0xEE000B10); /* fmdlr d0,r0 */
 
905
      o(0xEE201B10); /* fmdhr d0,r1 */
 
906
    }
 
907
  }
 
908
#endif
 
909
#endif
761
910
  vtop-=keep;
 
911
  leaffunc = 0;
762
912
}
763
913
 
764
914
/* generate function prolog of type 't' */
770
920
  sym = func_type->ref;
771
921
  func_vt = sym->type;
772
922
  
773
 
  n=0;
774
 
  addr=12;
775
 
  if((func_vt.t & VT_BTYPE) == VT_STRUCT) {
 
923
  n = 0;
 
924
  addr = 0;
 
925
  if((func_vt.t & VT_BTYPE) == VT_STRUCT
 
926
     && type_size(&func_vt,&align) > 4)
 
927
  {
776
928
    func_vc = addr;
777
929
    addr += 4;
778
930
    n++;
779
931
  }
780
932
  for(sym2=sym->next;sym2 && n<4;sym2=sym2->next) {
781
933
    size = type_size(&sym2->type, &align);
782
 
    size = (size + 3) & ~3;
783
 
    n+=size/4;
 
934
    n += (size + 3) / 4;
784
935
  }
785
936
  o(0xE1A0C00D); /* mov ip,sp */
786
937
  if(func_type->ref->c == FUNC_ELLIPSIS)
788
939
  if(n) {
789
940
    if(n>4)
790
941
      n=4;
 
942
#ifdef TCC_ARM_EABI
 
943
    n=(n+1)&-2;
 
944
#endif
791
945
    o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */
792
946
  }
793
 
  o(0xE92D5800); /* save fp, ip, lr*/
794
 
  o(0xE1A0B00D); /* mov fp,sp */
 
947
  o(0xE92D5800); /* save fp, ip, lr */
 
948
  o(0xE28DB00C); /* add fp, sp, #12 */
795
949
  func_sub_sp_offset = ind;
796
950
  o(0xE1A00000); /* nop, leave space for stack adjustment */
797
951
  while ((sym = sym->next)) {
798
952
    CType *type;
799
953
    type = &sym->type;
 
954
    size = type_size(type, &align);
 
955
    size = (size + 3) & -4;
 
956
#ifdef TCC_ARM_EABI
 
957
    addr = (addr + align - 1) & -align;
 
958
#endif
800
959
    sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
801
 
    size = type_size(type, &align);
802
 
    size = (size + 3) & ~3;
803
960
    addr += size;
804
961
  }
805
962
  last_itod_magic=0;
806
 
  loc = 0;
 
963
  leaffunc = 1;
 
964
  loc = -12;
807
965
}
808
966
 
809
967
/* generate function epilog */
810
968
void gfunc_epilog(void)
811
969
{
812
970
  unsigned long x;
813
 
  o(0xE89BA800); /* restore fp, sp, pc */
814
 
  if(loc) {
815
 
    x=stuff_const(0xE24DD000, (-loc + 3) & -4); /* sub sp,sp,# */
 
971
  int diff;
 
972
#ifdef TCC_ARM_EABI
 
973
  if(is_float(func_vt.t)) {
 
974
    if((func_vt.t & VT_BTYPE) == VT_FLOAT)
 
975
      o(0xEE100A10); /* fmrs r0, s0 */
 
976
    else {
 
977
      o(0xEE100B10); /* fmrdl r0, d0 */
 
978
      o(0xEE301B10); /* fmrdh r1, d0 */
 
979
    }
 
980
  }
 
981
#endif
 
982
  o(0xE91BA800); /* restore fp, sp, pc */
 
983
  diff = (-loc + 3) & -4;
 
984
#ifdef TCC_ARM_EABI
 
985
  if(!leaffunc)
 
986
    diff = (diff + 7) & -8;
 
987
#endif
 
988
  if(diff > 12) {
 
989
    x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
816
990
    if(x)
817
991
      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = x;
818
992
    else {
819
993
      unsigned long addr;
820
994
      addr=ind;
821
995
      o(0xE59FC004); /* ldr ip,[pc+4] */
822
 
      o(0xE04DD00C); /* sub sp,sp,ip  */
 
996
      o(0xE04BD00C); /* sub sp,fp,ip  */
823
997
      o(0xE1A0F00E); /* mov pc,lr */
824
 
      o((-loc + 3) & -4);
 
998
      o(diff);
825
999
      *(unsigned long *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1);
826
1000
    }
827
1001
  }
879
1053
  } else {
880
1054
    if (is_float(vtop->type.t)) {
881
1055
      r=gv(RC_FLOAT);
882
 
      o(0xEE90F118|fpr(r)<<16);
 
1056
#ifdef TCC_ARM_VFP
 
1057
      o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */
 
1058
      o(0xEEF1FA10); /* fmstat */
 
1059
#else
 
1060
      o(0xEE90F118|(fpr(r)<<16));
 
1061
#endif
883
1062
      vtop->r = VT_CMP;
884
1063
      vtop->c.i = TOK_NE;
885
1064
      return gtst(inv, t);
1058
1237
  }
1059
1238
}
1060
1239
 
 
1240
#ifdef TCC_ARM_VFP
 
1241
static int is_zero(int i)
 
1242
{
 
1243
  if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
 
1244
    return 0;
 
1245
  if (vtop[i].type.t == VT_FLOAT)
 
1246
    return (vtop[i].c.f == 0.f);
 
1247
  else if (vtop[i].type.t == VT_DOUBLE)
 
1248
    return (vtop[i].c.d == 0.0);
 
1249
  return (vtop[i].c.ld == 0.l);
 
1250
}
 
1251
 
 
1252
/* generate a floating point operation 'v = t1 op t2' instruction. The
 
1253
 *    two operands are guaranted to have the same floating point type */
 
1254
void gen_opf(int op)
 
1255
{
 
1256
  unsigned long x;
 
1257
  int fneg=0,r;
 
1258
  x=0xEE000A00|T2CPR(vtop->type.t);
 
1259
  switch(op) {
 
1260
    case '+':
 
1261
      if(is_zero(-1))
 
1262
        vswap();
 
1263
      if(is_zero(0)) {
 
1264
        vtop--;
 
1265
        return;
 
1266
      }
 
1267
      x|=0x300000;
 
1268
      break;
 
1269
    case '-':
 
1270
      x|=0x300040;
 
1271
      if(is_zero(0)) {
 
1272
        vtop--;
 
1273
        return;
 
1274
      }
 
1275
      if(is_zero(-1)) {
 
1276
        x|=0x810000; /* fsubX -> fnegX */
 
1277
        vswap();
 
1278
        vtop--;
 
1279
        fneg=1;
 
1280
      }
 
1281
      break;
 
1282
    case '*':
 
1283
      x|=0x200000;
 
1284
      break;
 
1285
    case '/':
 
1286
      x|=0x800000;
 
1287
      break;
 
1288
    default:
 
1289
      if(op < TOK_ULT && op > TOK_GT) {
 
1290
        error("unknown fp op %x!",op);
 
1291
        return;
 
1292
      }
 
1293
      if(is_zero(-1)) {
 
1294
        vswap();
 
1295
        switch(op) {
 
1296
          case TOK_LT: op=TOK_GT; break;
 
1297
          case TOK_GE: op=TOK_ULE; break;
 
1298
          case TOK_LE: op=TOK_GE; break;
 
1299
          case TOK_GT: op=TOK_ULT; break;
 
1300
        }
 
1301
      }
 
1302
      x|=0xB40040; /* fcmpX */
 
1303
      if(op!=TOK_EQ && op!=TOK_NE)
 
1304
        x|=0x80; /* fcmpX -> fcmpeX */
 
1305
      if(is_zero(0)) {
 
1306
        vtop--;
 
1307
        o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
 
1308
      } else {
 
1309
        x|=vfpr(gv(RC_FLOAT));
 
1310
        vswap();
 
1311
        o(x|(vfpr(gv(RC_FLOAT))<<12));
 
1312
        vtop--;
 
1313
      }
 
1314
      o(0xEEF1FA10); /* fmstat */
 
1315
 
 
1316
      switch(op) {
 
1317
        case TOK_LE: op=TOK_ULE; break;
 
1318
        case TOK_LT: op=TOK_ULT; break;
 
1319
        case TOK_UGE: op=TOK_GE; break;
 
1320
        case TOK_UGT: op=TOK_GT; break;
 
1321
      }
 
1322
      
 
1323
      vtop->r = VT_CMP;
 
1324
      vtop->c.i = op;
 
1325
      return;
 
1326
  }
 
1327
  r=gv(RC_FLOAT);
 
1328
  x|=vfpr(r);
 
1329
  r=regmask(r);
 
1330
  if(!fneg) {
 
1331
    int r2;
 
1332
    vswap();
 
1333
    r2=gv(RC_FLOAT);
 
1334
    x|=vfpr(r2)<<16;
 
1335
    r|=regmask(r2);
 
1336
  }
 
1337
  vtop->r=get_reg_ex(RC_FLOAT,r);
 
1338
  if(!fneg)
 
1339
    vtop--;
 
1340
  o(x|(vfpr(vtop->r)<<12));
 
1341
}
 
1342
 
 
1343
#else
1061
1344
static int is_fconst()
1062
1345
{
1063
1346
  long double f;
1193
1476
    default:
1194
1477
      if(op >= TOK_ULT && op <= TOK_GT) {
1195
1478
        x|=0xd0f110; // cmfe
 
1479
/* bug (intention?) in Linux FPU emulator
 
1480
   doesn't set carry if equal */
1196
1481
        switch(op) {
1197
1482
          case TOK_ULT:
1198
1483
          case TOK_UGE:
1199
1484
          case TOK_ULE:
1200
1485
          case TOK_UGT:
1201
 
            fputs("unsigned comparision on floats?\n",stderr);
 
1486
            error("unsigned comparision on floats?");
1202
1487
            break;
1203
1488
          case TOK_LT:
1204
 
            op=TOK_ULT;
1205
 
            break;
1206
 
          case TOK_GE:
1207
 
            op=TOK_UGE;
 
1489
            op=TOK_Nset;
1208
1490
            break;
1209
1491
          case TOK_LE:
1210
 
            op=TOK_ULE;
1211
 
            break;
1212
 
          case TOK_GT:
1213
 
            op=TOK_UGT;
 
1492
            op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */
1214
1493
            break;
1215
1494
          case TOK_EQ:
1216
1495
          case TOK_NE:
1221
1500
          c2=c1;
1222
1501
          vswap();
1223
1502
          switch(op) {
1224
 
            case TOK_ULT:
1225
 
              op=TOK_UGT;
 
1503
            case TOK_Nset:
 
1504
              op=TOK_GT;
1226
1505
              break;
1227
 
            case TOK_UGE:
 
1506
            case TOK_GE:
1228
1507
              op=TOK_ULE;
1229
1508
              break;
1230
1509
            case TOK_ULE:
1231
 
              op=TOK_UGE;
 
1510
              op=TOK_GE;
1232
1511
              break;
1233
 
            case TOK_UGT:
1234
 
              op=TOK_ULT;
 
1512
            case TOK_GT:
 
1513
              op=TOK_Nset;
1235
1514
              break;
1236
1515
          }
1237
1516
        }
1238
 
// bug (intention?) in Linux FPU emulator
1239
 
// doesn't set carry if equal
1240
 
        if(op==TOK_ULT)
1241
 
          op=TOK_LT;
1242
 
        else if(op==TOK_UGE)
1243
 
          op=TOK_GE;
1244
1517
        vswap();
1245
1518
        r=fpr(gv(RC_FLOAT));
1246
1519
        vswap();
1254
1527
        vtop[-1].r = VT_CMP;
1255
1528
        vtop[-1].c.i = op;
1256
1529
      } else {
1257
 
        error("unknown fp op %x!\n",op);
 
1530
        error("unknown fp op %x!",op);
1258
1531
        return;
1259
1532
      }
1260
1533
  }
1270
1543
  vtop--;
1271
1544
  o(x|(r<<16)|(c1<<12)|r2);
1272
1545
}
 
1546
#endif
1273
1547
 
1274
1548
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
1275
1549
   and 'long long' cases. */
1279
1553
  bt=vtop->type.t & VT_BTYPE;
1280
1554
  if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) {
1281
1555
    r=intr(gv(RC_INT));
 
1556
#ifdef TCC_ARM_VFP
 
1557
    r2=vfpr(vtop->r=get_reg(RC_FLOAT));
 
1558
    o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
 
1559
    r2<<=12;
 
1560
    if(!(vtop->type.t & VT_UNSIGNED))
 
1561
      r2|=0x80;                /* fuitoX -> fsituX */
 
1562
    o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
 
1563
#else
1282
1564
    r2=fpr(vtop->r=get_reg(RC_FLOAT));
1283
1565
    o(0xEE000190|(r2<<16)|(r<<12));
1284
1566
    if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) {
1300
1582
      }
1301
1583
      o(0xBE000180|(r2<<16)|(r2<<12)|r);
1302
1584
    }
 
1585
#endif
1303
1586
    return;
1304
1587
  } else if(bt == VT_LLONG) {
1305
1588
    int func;
 
1589
    CType *func_type = &func_old_type;
 
1590
#ifdef TCC_ARM_VFP
 
1591
#ifdef TCC_ARM_EABI
 
1592
    func_type = &func_double_type;
 
1593
#endif
 
1594
    if((t & VT_BTYPE) == VT_FLOAT) {
 
1595
#ifdef TCC_ARM_EABI
 
1596
      func_type = &func_float_type;
 
1597
#endif
 
1598
      if(vtop->type.t & VT_UNSIGNED)
 
1599
        func=TOK___ulltof;
 
1600
      else
 
1601
        func=TOK___slltof;
 
1602
    } else
 
1603
#endif
1306
1604
    if(vtop->type.t & VT_UNSIGNED)
1307
1605
      func=TOK___ulltold;
1308
1606
    else
1309
1607
      func=TOK___slltold;
1310
 
    vpush_global_sym(&func_old_type, func);
 
1608
    vpush_global_sym(func_type, func);
1311
1609
    vswap();
1312
1610
    gfunc_call(1);
1313
1611
    vpushi(0);
1325
1623
  t&=VT_BTYPE;
1326
1624
  r2=vtop->type.t & VT_BTYPE;
1327
1625
  if(t==VT_INT) {
 
1626
#ifdef TCC_ARM_VFP
 
1627
    r=vfpr(gv(RC_FLOAT));
 
1628
    u=u?0:0x10000;
 
1629
    o(0xEEBC0A40|(r<<12)|r|T2CPR(r2)); /* ftoXiY */
 
1630
    r2=intr(vtop->r=get_reg(RC_INT));
 
1631
    o(0xEE100A10|(r<<16)|(r2<<12));
 
1632
    return;
 
1633
#else
1328
1634
    if(u) {
1329
1635
      if(r2 == VT_FLOAT)
1330
1636
        func=TOK___fixunssfsi;
1342
1648
      o(0xEE100170|(r2<<12)|r);
1343
1649
    return;
1344
1650
    }
 
1651
#endif
1345
1652
  } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1
1346
1653
    if(r2 == VT_FLOAT)
1347
1654
      func=TOK___fixsfdi;
1370
1677
/* convert from one floating point type to another */
1371
1678
void gen_cvt_ftof(int t)
1372
1679
{
1373
 
  /* all we have to do on i386 and ARM is to put the float in a register */
 
1680
#ifdef TCC_ARM_VFP
 
1681
  if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
 
1682
    int r=vfpr(gv(RC_FLOAT));
 
1683
    o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
 
1684
  }
 
1685
#else
 
1686
  /* all we have to do on i386 and FPA ARM is to put the float in a register */
1374
1687
  gv(RC_FLOAT);
 
1688
#endif
1375
1689
}
1376
1690
 
1377
1691
/* computed goto support */