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
345 int i, align, size, aireg, afreg;345 int i, align, size, aireg, afreg;
346 int info[nb_args ? nb_args : 1];346 int info[nb_args ? nb_args : 1];
347 int stack_adj = 0, ofs;347 int stack_adj = 0, ofs;
348 int force_stack = 0;
348 SValue *sv;349 SValue *sv;
349 Sym *sa;350 Sym *sa;
350 aireg = afreg = 0;351 aireg = afreg = 0;
351 sa = vtop[-nb_args].type.ref->next;352 sa = vtop[-nb_args].type.ref->next;
352 for (i = 0; i < nb_args; i++) {353 for (i = 0; i < nb_args; i++) {
353 int *pareg;354 int *pareg, nregs, infreg = 0;
354 sv = &vtop[1 + i - nb_args];355 sv = &vtop[1 + i - nb_args];
355 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c356 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
356 size = type_size(&sv->type, &align);357 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))
358 tcc_error("unimp: call arg %d wrong type", nb_args - i);360 tcc_error("unimp: call arg %d wrong type", nb_args - i);
359 pareg = sa && is_float(sv->type.t) ? &afreg : &aireg;361 nregs = 1;
360 if (*pareg < 8) {362 if ((sv->type.t & VT_BTYPE) == VT_LDOUBLE) {
361 info[i] = *pareg + (sa && is_float(sv->type.t) ? 8 : 0);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);
362 (*pareg)++;372 (*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 }
363 } else {382 } else {
364 info[i] = 16;383 info[i] = 32;
365 stack_adj += (size + align - 1) & -align;384 stack_adj += (size + align - 1) & -align;
385 if (!sa)
386 force_stack = 1;
366 }387 }
367 if (sa)388 if (sa)
368 sa = sa->next;389 sa = sa->next;
@@ -371,7 +392,7 @@ ST_FUNC void gfunc_call(int nb_args) · 2 unmodified lines
371 if (stack_adj) {392 if (stack_adj) {
372 EI(0x13, 0, 2, 2, -stack_adj); // addi sp, sp, -adj393 EI(0x13, 0, 2, 2, -stack_adj); // addi sp, sp, -adj
373 for (i = ofs = 0; i < nb_args; i++) {394 for (i = ofs = 0; i < nb_args; i++) {
374 if (1 && info[i] >= 16) {395 if (1 && info[i] >= 32) {
375 vrotb(nb_args - i);396 vrotb(nb_args - i);
376 size = type_size(&vtop->type, &align);397 size = type_size(&vtop->type, &align);
377 /* Once we support offseted regs we can do this:398 /* Once we support offseted regs we can do this:
@@ -393,9 +414,20 @@ ST_FUNC void gfunc_call(int nb_args) · 15 unmodified lines
393 }414 }
394 for (i = 0; i < nb_args; i++) {415 for (i = 0; i < nb_args; i++) {
395 int r = info[nb_args - 1 - i];416 int r = info[nb_args - 1 - i];
396 if (r < 16) {417 if (r < 32) {
418 r &= 15;
397 vrotb(i+1);419 vrotb(i+1);
398 gv(r < 8 ? RC_R(r) : RC_F(r - 8));420 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 }
399 vrott(i+1);431 vrott(i+1);
400 }432 }
401 }433 }
tccgen.c+35−3
@@ -1548,6 +1548,11 @@ ST_FUNC int gv(int rc) · 1547 unmodified lines
1548 if (vtop->r & VT_MUSTBOUND) 1548 if (vtop->r & VT_MUSTBOUND)
1549 gbound();1549 gbound();
1550#endif1550#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
1551 1556
1552 r = vtop->r & VT_VALMASK;1557 r = vtop->r & VT_VALMASK;
1553 rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;1558 rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
@@ -1568,7 +1573,10 @@ ST_FUNC int gv(int rc) · 14 unmodified lines
1568 if (r >= VT_CONST1573 if (r >= VT_CONST
1569 || (vtop->r & VT_LVAL)1574 || (vtop->r & VT_LVAL)
1570 || !(reg_classes[r] & rc)1575 || !(reg_classes[r] & rc)
1571#if PTR_SIZE == 81576#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
1572 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))1580 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
1573 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))1581 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
1574#else1582#else
@@ -1577,7 +1585,10 @@ ST_FUNC int gv(int rc) · 2 unmodified lines
1577 )1585 )
1578 {1586 {
1579 r = get_reg(rc);1587 r = get_reg(rc);
1580#if PTR_SIZE == 81588#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
1581 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {1592 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
1582 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;1593 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
1583#else1594#else
@@ -1708,6 +1719,9 @@ static int rc_fret(int t) · 124 unmodified lines
1708 if (t == VT_LDOUBLE) {1719 if (t == VT_LDOUBLE) {
1709 return RC_ST0;1720 return RC_ST0;
1710 }1721 }
1722#elif defined TCC_TARGET_RISCV64
1723 if (t == VT_LDOUBLE)
1724 return RC_IRET;
1711#endif1725#endif
1712 return RC_FRET;1726 return RC_FRET;
1713}1727}
@@ -1720,6 +1734,9 @@ static int reg_fret(int t) · 6 unmodified lines
1720 if (t == VT_LDOUBLE) {1734 if (t == VT_LDOUBLE) {
1721 return TREG_ST0;1735 return TREG_ST0;
1722 }1736 }
1737#elif defined TCC_TARGET_RISCV64
1738 if (t == VT_LDOUBLE)
1739 return REG_IRET;
1723#endif1740#endif
1724 return REG_FRET;1741 return REG_FRET;
1725}1742}
@@ -1797,6 +1814,9 @@ static void gv_dup(void) · 71 unmodified lines
1797 if ((t & VT_BTYPE) == VT_LDOUBLE) {1814 if ((t & VT_BTYPE) == VT_LDOUBLE) {
1798 rc = RC_ST0;1815 rc = RC_ST0;
1799 }1816 }
1817#elif defined TCC_TARGET_RISCV64
1818 if ((t & VT_BTYPE) == VT_LDOUBLE)
1819 rc = RC_INT;
1800#endif1820#endif
1801 sv.type.t = t;1821 sv.type.t = t;
1802 }1822 }
@@ -3403,6 +3423,9 @@ ST_FUNC void vstore(void) · 1600 unmodified lines
3403 } else if ((ft & VT_BTYPE) == VT_QFLOAT) {3423 } else if ((ft & VT_BTYPE) == VT_QFLOAT) {
3404 rc = RC_FRET;3424 rc = RC_FRET;
3405 }3425 }
3426#elif defined TCC_TARGET_RISCV64
3427 if (dbt == VT_LDOUBLE)
3428 rc = RC_INT;
3406#endif3429#endif
3407 }3430 }
3408 r = gv(rc); /* generate value */3431 r = gv(rc); /* generate value */
@@ -3421,7 +3444,10 @@ ST_FUNC void vstore(void) · 12 unmodified lines
3421 vtop[-1].r = t | VT_LVAL;3444 vtop[-1].r = t | VT_LVAL;
3422 }3445 }
3423 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */3446 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */
3424#if PTR_SIZE == 83447#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
3425 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {3451 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {
3426 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;3452 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
3427#else3453#else
@@ -5743,6 +5769,9 @@ static void expr_cond(void) · 2315 unmodified lines
5743 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {5769 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
5744 rc = RC_ST0;5770 rc = RC_ST0;
5745 }5771 }
5772#elif defined TCC_TARGET_RISCV64
5773 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
5774 rc = RC_INT;
5746#endif5775#endif
5747 }5776 }
5748 gv(rc);5777 gv(rc);
@@ -5914,6 +5943,9 @@ static void expr_cond(void) · 165 unmodified lines
5914 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {5943 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
5915 rc = RC_ST0;5944 rc = RC_ST0;
5916 }5945 }
5946#elif defined TCC_TARGET_RISCV64
5947 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
5948 rc = RC_INT;
5917#endif5949#endif
5918 } else if ((type.t & VT_BTYPE) == VT_LLONG) {5950 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
5919 /* for long longs, we use fixed registers to avoid having5951 /* 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