* register indirect loads and stores * load of local addresses * indirect calls (uses ra as temporary reg if necessary) * operations *, -, << * gen_cvt_sxtw: is not needed in most cases, let's see tests2 runs until (incl) 09_do_while.
Unified · Split
| @@ -33,6 +33,8 @@ · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | #define XLEN 8 |
| 35 | 35 | |
| 36 | +#define TREG_RA 17 | |
| 37 | + | |
| 36 | 38 | ST_DATA const int reg_classes[NB_REGS] = { |
| 37 | 39 | RC_INT | RC_R(0), |
| 38 | 40 | RC_INT | RC_R(1), |
| @@ -54,13 +56,15 @@ ST_DATA const int reg_classes[NB_REGS] = { · 15 unmodified lines | ||
| 54 | 56 | |
| 55 | 57 | static int ireg(int r) |
| 56 | 58 | { |
| 59 | + if (r == TREG_RA) | |
| 60 | + return 1; // ra | |
| 57 | 61 | assert(r >= 0 && r < 8); |
| 58 | 62 | return r + 10; // tccrX --> aX == x(10+X) |
| 59 | 63 | } |
| 60 | 64 | |
| 61 | 65 | static int is_ireg(int r) |
| 62 | 66 | { |
| 63 | − return r < 8; | |
| 67 | + return r < 8 || r == TREG_RA; | |
| 64 | 68 | } |
| 65 | 69 | |
| 66 | 70 | static int is_freg(int r) |
| @@ -121,20 +125,22 @@ ST_FUNC void load(int r, SValue *sv) · 54 unmodified lines | ||
| 121 | 125 | int rr = ireg(r); |
| 122 | 126 | int fc = sv->c.i; |
| 123 | 127 | if (fr & VT_LVAL) { |
| 128 | + int bt = sv->type.t & VT_BTYPE; | |
| 129 | + int align, size = type_size(&sv->type, &align); | |
| 130 | + int func3; | |
| 131 | + if (is_float(bt)) | |
| 132 | + tcc_error("unimp: load-local(float)"); | |
| 133 | + else if (bt == VT_FUNC) | |
| 134 | + size = PTR_SIZE; | |
| 135 | + func3 = size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3; | |
| 136 | + if (size < 8 && (sv->type.t & VT_UNSIGNED)) | |
| 137 | + func3 |= 4; | |
| 124 | 138 | if (v == VT_LOCAL) { |
| 125 | − int bt = sv->type.t & VT_BTYPE; | |
| 126 | − int align, size = type_size(&sv->type, &align); | |
| 127 | − int func3; | |
| 128 | 139 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 129 | 140 | tcc_error("unimp: load(large local ofs) (0x%x)", fc); |
| 130 | − if (is_float(bt)) | |
| 131 | − tcc_error("unimp: load-local(float)"); | |
| 132 | − else if (bt == VT_FUNC) | |
| 133 | − size = PTR_SIZE; | |
| 134 | − func3 = size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3; | |
| 135 | − if (size < 8 && (sv->type.t & VT_UNSIGNED)) | |
| 136 | − func3 |= 4; | |
| 137 | 141 | EI(0x03, func3, rr, 8, fc); // l[bhwd][u] RR, fc(s0) |
| 142 | + } else if (v < VT_CONST) { | |
| 143 | + EI(0x03, func3, rr, ireg(v), 0); // l[bhwd][u] RR, 0(V) | |
| 138 | 144 | } else { |
| 139 | 145 | tcc_error("unimp: load(non-local lval)"); |
| 140 | 146 | } |
| @@ -162,6 +168,10 @@ ST_FUNC void load(int r, SValue *sv) · 21 unmodified lines | ||
| 162 | 168 | if (is_float(sv->type.t)) |
| 163 | 169 | tcc_error("unimp: load(float)"); |
| 164 | 170 | EI(0x13, 0, rr, rb, fc); // addi R, x0|R, FC |
| 171 | + } else if (v == VT_LOCAL) { | |
| 172 | + if (((unsigned)fc + (1 << 11)) >> 12) | |
| 173 | + tcc_error("unimp: load(addr large local ofs) (0x%x)", fc); | |
| 174 | + EI(0x13, 0, rr, 8, fc); // addi R, s0, FC | |
| 165 | 175 | } else if (v < VT_CONST) { |
| 166 | 176 | /* reg-reg */ |
| 167 | 177 | if (is_freg(r) && is_freg(v)) |
| @@ -195,6 +205,10 @@ ST_FUNC void store(int r, SValue *sv) · 27 unmodified lines | ||
| 195 | 205 | tcc_error("unimp: large sized store"); |
| 196 | 206 | ES(0x23, size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, |
| 197 | 207 | 8, rr, fc); // s[bhwd] RR, fc(s0) |
| 208 | + } else if (fr < VT_CONST) { | |
| 209 | + int ptrreg = ireg(fr); | |
| 210 | + ES(0x23, size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, | |
| 211 | + ptrreg, rr, 0); // s[bhwd] RR, 0(PTRREG) | |
| 198 | 212 | } else |
| 199 | 213 | tcc_error("implement me: %s(!local)", __FUNCTION__); |
| 200 | 214 | } |
| @@ -208,8 +222,14 @@ static void gcall(void) · 7 unmodified lines | ||
| 208 | 222 | R_RISCV_CALL_PLT, (int)vtop->c.i); |
| 209 | 223 | o(0x17 | (1 << 7)); // auipc ra, 0 %call(func) |
| 210 | 224 | o(0x80e7); // jalr ra, 0 %call(func) |
| 225 | + } else if ((vtop->r & VT_VALMASK) < VT_CONST) { | |
| 226 | + int r = ireg(vtop->r & VT_VALMASK); | |
| 227 | + EI(0x67, 0, 1, r, 0); // jalr ra, 0(R) | |
| 211 | 228 | } else { |
| 212 | − tcc_error("unimp: indirect call"); | |
| 229 | + int r = TREG_RA; | |
| 230 | + load(r, vtop); | |
| 231 | + r = ireg(r); | |
| 232 | + EI(0x67, 0, 1, r, 0); // jalr ra, 0(R) | |
| 213 | 233 | } |
| 214 | 234 | } |
| 215 | 235 | |
| @@ -401,6 +421,7 @@ static void gen_opil(int op, int ll) · 185 unmodified lines | ||
| 401 | 421 | { |
| 402 | 422 | int a, b, d; |
| 403 | 423 | int inv = 0; |
| 424 | + int func3 = 0, func7 = 0; | |
| 404 | 425 | /* XXX We could special-case some constant args. */ |
| 405 | 426 | gv2(RC_INT, RC_INT); |
| 406 | 427 | a = ireg(vtop[-1].r); |
| @@ -413,13 +434,10 @@ static void gen_opil(int op, int ll) · 6 unmodified lines | ||
| 413 | 434 | switch (op) { |
| 414 | 435 | case '%': |
| 415 | 436 | case '&': |
| 416 | − case '*': | |
| 417 | − case '-': | |
| 418 | 437 | case '/': |
| 419 | 438 | case '^': |
| 420 | 439 | case '|': |
| 421 | 440 | case TOK_SAR: |
| 422 | − case TOK_SHL: | |
| 423 | 441 | case TOK_SHR: |
| 424 | 442 | case TOK_UDIV: |
| 425 | 443 | case TOK_PDIV: |
| @@ -430,6 +448,15 @@ static void gen_opil(int op, int ll) · 4 unmodified lines | ||
| 430 | 448 | case '+': |
| 431 | 449 | o(0x33 | (d << 7) | (a << 15) | (b << 20)); // add d, a, b |
| 432 | 450 | break; |
| 451 | + case '-': | |
| 452 | + o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x20 << 25)); //sub d, a, b | |
| 453 | + break; | |
| 454 | + case TOK_SHL: | |
| 455 | + o(0x33 | (d << 7) | (a << 15) | (b << 20) | (1 << 12)); //sll d, a, b | |
| 456 | + break; | |
| 457 | + case '*': | |
| 458 | + o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25)); //mul d, a, b | |
| 459 | + break; | |
| 433 | 460 | |
| 434 | 461 | case TOK_ULT: |
| 435 | 462 | case TOK_UGE: |
| @@ -483,7 +510,8 @@ ST_FUNC void gen_opf(int op) · 47 unmodified lines | ||
| 483 | 510 | |
| 484 | 511 | ST_FUNC void gen_cvt_sxtw(void) |
| 485 | 512 | { |
| 486 | − tcc_error("implement me: %s", __FUNCTION__); | |
| 513 | + /* XXX on risc-v the registers are usually sign-extended already. | |
| 514 | + Let's try to not do anything here. */ | |
| 487 | 515 | } |
| 488 | 516 | |
| 489 | 517 | ST_FUNC void gen_cvt_itof(int t) |