riscv: Make 32_leds work

* more ops: umod and udiv
* large immediates: suboptimal code, e.g. when loading
  0xffffffffU (which is what a cast from long to int does).

tests2 work up to 67_macro_concat.
This commit is contained in:
Michael Matz 2019-07-14 03:26:38 +02:00
parent 02c8e69a07
commit 9c1b17407f
2 changed files with 26 additions and 5 deletions

View file

@ -191,12 +191,10 @@ ST_FUNC void load(int r, SValue *sv)
} else if (v == VT_CONST) { } else if (v == VT_CONST) {
int rb = 0; int rb = 0;
assert(!is_float(sv->type.t) && is_ireg(r)); assert(!is_float(sv->type.t) && is_ireg(r));
if (fc != sv->c.i)
tcc_error("unimp: load(very large const)");
if (fr & VT_SYM) { if (fr & VT_SYM) {
static Sym label; static Sym label;
greloca(cur_text_section, sv->sym, ind, greloca(cur_text_section, sv->sym, ind,
R_RISCV_PCREL_HI20, fc); R_RISCV_PCREL_HI20, sv->c.i);
if (!label.v) { if (!label.v) {
label.v = tok_alloc(".L0 ", 4)->tok; label.v = tok_alloc(".L0 ", 4)->tok;
label.type.t = VT_VOID | VT_STATIC; label.type.t = VT_VOID | VT_STATIC;
@ -208,9 +206,25 @@ ST_FUNC void load(int r, SValue *sv)
R_RISCV_PCREL_LO12_I, 0); R_RISCV_PCREL_LO12_I, 0);
rb = rr; rb = rr;
fc = 0; fc = 0;
sv->c.i = 0;
} }
if (is_float(sv->type.t)) if (is_float(sv->type.t))
tcc_error("unimp: load(float)"); tcc_error("unimp: load(float)");
if (fc != sv->c.i) {
int64_t si = sv->c.i;
uint32_t pi;
si >>= 32;
if (si != 0)
tcc_error("unimp: load(very large const)");
/* A 32bit unsigned constant. lui always sign extends, so we need
tricks. */
pi = (uint32_t)sv->c.i;
o(0x37 | (rr << 7) | (((pi + 0x80000) & 0xfff00000) >> 8)); // lui RR, up(fc)>>8
EI(0x13, 0, rr, rr, (((pi + 0x200) & 0x000ffc00) >> 8) | (-((int)(pi + 0x200) & 0x80000) >> 8)); // addi RR, RR, mid(fc)
EI(0x13, 1, rr, rr, 8); // slli RR, RR, 8
fc = (pi & 0x3ff) | (-((int)(pi & 0x200)));
rb = rr;
}
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, 0, rr, rb, fc << 20 >> 20); // addi R, x0|R, FC EI(0x13, 0, rr, rb, fc << 20 >> 20); // addi R, x0|R, FC
@ -575,9 +589,7 @@ static void gen_opil(int op, int ll)
case '%': case '%':
case TOK_SAR: case TOK_SAR:
case TOK_SHR: case TOK_SHR:
case TOK_UDIV:
case TOK_PDIV: case TOK_PDIV:
case TOK_UMOD:
default: default:
tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL)); tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL));
@ -605,6 +617,12 @@ static void gen_opil(int op, int ll)
case '|': case '|':
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b
break; break;
case TOK_UMOD:
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (7 << 12)); //remu d, a, b
break;
case TOK_UDIV:
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (5 << 12)); //divu d, a, b
break;
case TOK_ULT: case TOK_ULT:
case TOK_UGE: case TOK_UGE:

View file

@ -2840,6 +2840,9 @@ static void gen_cast(CType *type)
lexpand(); lexpand();
vpop(); vpop();
#else #else
/* XXX some architectures (e.g. risc-v) would like it
better for this merely being a 32-to-64 sign or zero-
extension. */
vpushi(0xffffffff); vpushi(0xffffffff);
vtop->type.t |= VT_UNSIGNED; vtop->type.t |= VT_UNSIGNED;
gen_op('&'); gen_op('&');