riscv: load 64bit constants, and 32bit shifts

fixes 95_bitfields.  loading 64bit constants is suboptimal
right now.  int32_t shifts really need to use the W form,
otherwise 'x << 24 >> 24' doesn't extract the low 8 bits.
This commit is contained in:
Michael Matz 2019-07-15 20:59:28 +02:00
parent 215bc1aab4
commit 9164594d1f

View file

@ -215,8 +215,22 @@ ST_FUNC void load(int r, SValue *sv)
int64_t si = sv->c.i; int64_t si = sv->c.i;
uint32_t pi; uint32_t pi;
si >>= 32; si >>= 32;
if (si != 0) if (si != 0) {
tcc_error("unimp: load(very large const)"); pi = si;
if (fc < 0)
pi++;
o(0x37 | (rr << 7) | (((pi + 0x800) & 0xfffff000))); // lui RR, up(up(fc))
EI(0x13, 0, rr, rr, (int)pi << 20 >> 20); // addi RR, RR, lo(up(fc))
EI(0x13, 1, rr, rr, 12); // slli RR, RR, 12
EI(0x13, 0, rr, rr, (fc + (1 << 19)) >> 20); // addi RR, RR, up(lo(fc))
EI(0x13, 1, rr, rr, 12); // slli RR, RR, 12
fc = fc << 12 >> 12;
EI(0x13, 0, rr, rr, fc >> 8); // addi RR, RR, lo1(lo(fc))
EI(0x13, 1, rr, rr, 8); // slli RR, RR, 8
fc &= 0xff;
rb = rr;
do32bit = 0;
} else {
/* A 32bit unsigned constant. lui always sign extends, so we need /* A 32bit unsigned constant. lui always sign extends, so we need
tricks. */ tricks. */
pi = (uint32_t)sv->c.i; pi = (uint32_t)sv->c.i;
@ -227,6 +241,7 @@ ST_FUNC void load(int r, SValue *sv)
rb = rr; rb = rr;
do32bit = 0; do32bit = 0;
} }
}
if (((unsigned)fc + (1 << 11)) >> 12) if (((unsigned)fc + (1 << 11)) >> 12)
o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc) o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc)
EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC
@ -619,6 +634,7 @@ static void gen_opil(int op, int ll)
vtop++; vtop++;
vtop[0].r = d; vtop[0].r = d;
d = ireg(d); d = ireg(d);
ll = ll ? 0 : 8;
switch (op) { switch (op) {
case '%': case '%':
case TOK_PDIV: case TOK_PDIV:
@ -632,10 +648,10 @@ static void gen_opil(int op, int ll)
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x20 << 25)); //sub d, a, b o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x20 << 25)); //sub d, a, b
break; break;
case TOK_SAR: case TOK_SAR:
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (5 << 12) | (1 << 30)); //sra d, a, b o(0x33 | ll | (d << 7) | (a << 15) | (b << 20) | (5 << 12) | (1 << 30)); //sra d, a, b
break; break;
case TOK_SHR: case TOK_SHR:
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (5 << 12)); //srl d, a, b o(0x33 | ll | (d << 7) | (a << 15) | (b << 20) | (5 << 12)); //srl d, a, b
break; break;
case TOK_SHL: case TOK_SHL:
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (1 << 12)); //sll d, a, b o(0x33 | (d << 7) | (a << 15) | (b << 20) | (1 << 12)); //sll d, a, b