History

riscv: some long double support

long double on risc-v is 128bit, but there are no registers for that type (without the Q ISA extension). They are passed like two 64bit integers values (with an exception for varargs, where it's an aligned register pair). This all requires some hacks in generic code as otherwise RC_FLOAT regs are tried for holding values of long double type, but we need a RC_INT register pair. This really could all use some cleanup for all archs. This doesn't implement any conversions of operations for long double, but it's enough to get 70_floating_point_literals working.

Michael Matz committed 7 years ago

Commit 93095851 parent 9c1b1742 files · +75 −11Browse files

Unified · Split

2 files
  1. riscv64-gen.c +40 −8
  2. tccgen.c +35 −3
riscv64-gen.c+40−8
@@ -345,24 +345,45 @@ ST_FUNC void gfunc_call(int nb_args) · 344 unmodified lines
345345 int i, align, size, aireg, afreg;
346346 int info[nb_args ? nb_args : 1];
347347 int stack_adj = 0, ofs;
348+ int force_stack = 0;
348349 SValue *sv;
349350 Sym *sa;
350351 aireg = afreg = 0;
351352 sa = vtop[-nb_args].type.ref->next;
352353 for (i = 0; i < nb_args; i++) {
353− int *pareg;
354+ int *pareg, nregs, infreg = 0;
354355 sv = &vtop[1 + i - nb_args];
355356 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
356357 size = type_size(&sv->type, &align);
357− if (size > 8 || ((sv->type.t & VT_BTYPE) == VT_STRUCT))
358+ if ((size > 8 && ((sv->type.t & VT_BTYPE) != VT_LDOUBLE))
359+ || ((sv->type.t & VT_BTYPE) == VT_STRUCT))
358360 tcc_error("unimp: call arg %d wrong type", nb_args - i);
359− pareg = sa && is_float(sv->type.t) ? &afreg : &aireg;
360− if (*pareg < 8) {
361− info[i] = *pareg + (sa && is_float(sv->type.t) ? 8 : 0);
361+ nregs = 1;
362+ if ((sv->type.t & VT_BTYPE) == VT_LDOUBLE) {
363+ infreg = 0, nregs = 2;
364+ if (!sa) {
365+ aireg = (aireg + 1) & ~1;
366+ }
367+ } else
368+ infreg = sa && is_float(sv->type.t);
369+ pareg = infreg ? &afreg : &aireg;
370+ if ((*pareg < 8) && !force_stack) {
371+ info[i] = *pareg + (infreg ? 8 : 0);
362372 (*pareg)++;
373+ if (nregs == 1)
374+ ;
375+ else if (*pareg < 8)
376+ (*pareg)++;
377+ else {
378+ info[i] |= 16;
379+ stack_adj += 8;
380+ tcc_error("unimp: param passing half in reg, half on stack");
381+ }
363382 } else {
364− info[i] = 16;
383+ info[i] = 32;
365384 stack_adj += (size + align - 1) & -align;
385+ if (!sa)
386+ force_stack = 1;
366387 }
367388 if (sa)
368389 sa = sa->next;
@@ -371,7 +392,7 @@ ST_FUNC void gfunc_call(int nb_args) · 2 unmodified lines
371392 if (stack_adj) {
372393 EI(0x13, 0, 2, 2, -stack_adj); // addi sp, sp, -adj
373394 for (i = ofs = 0; i < nb_args; i++) {
374− if (1 && info[i] >= 16) {
395+ if (1 && info[i] >= 32) {
375396 vrotb(nb_args - i);
376397 size = type_size(&vtop->type, &align);
377398 /* Once we support offseted regs we can do this:
@@ -393,9 +414,20 @@ ST_FUNC void gfunc_call(int nb_args) · 15 unmodified lines
393414 }
394415 for (i = 0; i < nb_args; i++) {
395416 int r = info[nb_args - 1 - i];
396− if (r < 16) {
417+ if (r < 32) {
418+ r &= 15;
397419 vrotb(i+1);
398420 gv(r < 8 ? RC_R(r) : RC_F(r - 8));
421+ if (vtop->r2 < VT_CONST) {
422+ assert((vtop->type.t & VT_BTYPE) == VT_LDOUBLE);
423+ assert(vtop->r < 7);
424+ if (vtop->r2 != 1 + vtop->r) {
425+ /* XXX we'd like to have 'gv' move directly into
426+ the right class instead of us fixing it up. */
427+ EI(0x13, 0, ireg(vtop->r) + 1, ireg(vtop->r2), 0); // mv Ra+1, RR2
428+ vtop->r2 = 1 + vtop->r;
429+ }
430+ }
399431 vrott(i+1);
400432 }
401433 }
tccgen.c+35−3
@@ -1548,6 +1548,11 @@ ST_FUNC int gv(int rc) · 1547 unmodified lines
15481548 if (vtop->r & VT_MUSTBOUND)
15491549 gbound();
15501550 #endif
1551+#ifdef TCC_TARGET_RISCV64
1552+ /* XXX mega hack */
1553+ if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE && rc == RC_FLOAT)
1554+ rc = RC_INT;
1555+#endif
15511556
15521557 r = vtop->r & VT_VALMASK;
15531558 rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
@@ -1568,7 +1573,10 @@ ST_FUNC int gv(int rc) · 14 unmodified lines
15681573 if (r >= VT_CONST
15691574 || (vtop->r & VT_LVAL)
15701575 || !(reg_classes[r] & rc)
1571−#if PTR_SIZE == 8
1576+#ifdef TCC_TARGET_RISCV64
1577+ || ((vtop->type.t & VT_BTYPE) == VT_QLONG && (vtop->r2 >= NB_REGS || !(reg_classes[vtop->r2] & rc2)))
1578+ || ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE && (vtop->r2 >= NB_REGS || !(reg_classes[vtop->r2] & rc2)))
1579+#elif PTR_SIZE == 8
15721580 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
15731581 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
15741582 #else
@@ -1577,7 +1585,10 @@ ST_FUNC int gv(int rc) · 2 unmodified lines
15771585 )
15781586 {
15791587 r = get_reg(rc);
1580−#if PTR_SIZE == 8
1588+#ifdef TCC_TARGET_RISCV64
1589+ if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)) {
1590+ int addr_type = VT_LLONG, load_size = 8, load_type = VT_LLONG;
1591+#elif PTR_SIZE == 8
15811592 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
15821593 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
15831594 #else
@@ -1708,6 +1719,9 @@ static int rc_fret(int t) · 124 unmodified lines
17081719 if (t == VT_LDOUBLE) {
17091720 return RC_ST0;
17101721 }
1722+#elif defined TCC_TARGET_RISCV64
1723+ if (t == VT_LDOUBLE)
1724+ return RC_IRET;
17111725 #endif
17121726 return RC_FRET;
17131727 }
@@ -1720,6 +1734,9 @@ static int reg_fret(int t) · 6 unmodified lines
17201734 if (t == VT_LDOUBLE) {
17211735 return TREG_ST0;
17221736 }
1737+#elif defined TCC_TARGET_RISCV64
1738+ if (t == VT_LDOUBLE)
1739+ return REG_IRET;
17231740 #endif
17241741 return REG_FRET;
17251742 }
@@ -1797,6 +1814,9 @@ static void gv_dup(void) · 71 unmodified lines
17971814 if ((t & VT_BTYPE) == VT_LDOUBLE) {
17981815 rc = RC_ST0;
17991816 }
1817+#elif defined TCC_TARGET_RISCV64
1818+ if ((t & VT_BTYPE) == VT_LDOUBLE)
1819+ rc = RC_INT;
18001820 #endif
18011821 sv.type.t = t;
18021822 }
@@ -3403,6 +3423,9 @@ ST_FUNC void vstore(void) · 1600 unmodified lines
34033423 } else if ((ft & VT_BTYPE) == VT_QFLOAT) {
34043424 rc = RC_FRET;
34053425 }
3426+#elif defined TCC_TARGET_RISCV64
3427+ if (dbt == VT_LDOUBLE)
3428+ rc = RC_INT;
34063429 #endif
34073430 }
34083431 r = gv(rc); /* generate value */
@@ -3421,7 +3444,10 @@ ST_FUNC void vstore(void) · 12 unmodified lines
34213444 vtop[-1].r = t | VT_LVAL;
34223445 }
34233446 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */
3424−#if PTR_SIZE == 8
3447+#ifdef TCC_TARGET_RISCV64
3448+ if (dbt == VT_QLONG || dbt == VT_LDOUBLE) {
3449+ int addr_type = VT_LLONG, load_size = 8, load_type = VT_LLONG;
3450+#elif PTR_SIZE == 8
34253451 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {
34263452 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
34273453 #else
@@ -5743,6 +5769,9 @@ static void expr_cond(void) · 2315 unmodified lines
57435769 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
57445770 rc = RC_ST0;
57455771 }
5772+#elif defined TCC_TARGET_RISCV64
5773+ if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
5774+ rc = RC_INT;
57465775 #endif
57475776 }
57485777 gv(rc);
@@ -5914,6 +5943,9 @@ static void expr_cond(void) · 165 unmodified lines
59145943 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
59155944 rc = RC_ST0;
59165945 }
5946+#elif defined TCC_TARGET_RISCV64
5947+ if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
5948+ rc = RC_INT;
59175949 #endif
59185950 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
59195951 /* for long longs, we use fixed registers to avoid having

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