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) {
int rb = 0;
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) {
static Sym label;
greloca(cur_text_section, sv->sym, ind,
R_RISCV_PCREL_HI20, fc);
R_RISCV_PCREL_HI20, sv->c.i);
if (!label.v) {
label.v = tok_alloc(".L0 ", 4)->tok;
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);
rb = rr;
fc = 0;
sv->c.i = 0;
}
if (is_float(sv->type.t))
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)
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
@ -575,9 +589,7 @@ static void gen_opil(int op, int ll)
case '%':
case TOK_SAR:
case TOK_SHR:
case TOK_UDIV:
case TOK_PDIV:
case TOK_UMOD:
default:
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 '|':
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b
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_UGE:

View File

@ -2840,6 +2840,9 @@ static void gen_cast(CType *type)
lexpand();
vpop();
#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);
vtop->type.t |= VT_UNSIGNED;
gen_op('&');