| @@ -58,6 +58,16 @@ static int ireg(int r) · 57 unmodified lines |
| 58 | return r + 10; // tccrX --> aX == x(10+X) | 58 | return r + 10; // tccrX --> aX == x(10+X) |
| 59 | } | 59 | } |
| 60 | | 60 | |
| | 61 | static int is_ireg(int r) |
| | 62 | { |
| | 63 | return r < 8; |
| | 64 | } |
| | 65 | |
| | 66 | static int is_freg(int r) |
| | 67 | { |
| | 68 | return r >= 8 && r < 16; |
| | 69 | } |
| | 70 | |
| 61 | ST_FUNC void o(unsigned int c) | 71 | ST_FUNC void o(unsigned int c) |
| 62 | { | 72 | { |
| 63 | int ind1 = ind + 4; | 73 | int ind1 = ind + 4; |
| @@ -92,11 +102,14 @@ ST_FUNC void gsym_addr(int t_, int a_) · 28 unmodified lines |
| 92 | while (t) { | 102 | while (t) { |
| 93 | unsigned char *ptr = cur_text_section->data + t; | 103 | unsigned char *ptr = cur_text_section->data + t; |
| 94 | uint32_t next = read32le(ptr); | 104 | uint32_t next = read32le(ptr); |
| 95 | tcc_error("implement me: %s", __FUNCTION__); | 105 | uint32_t r = a - t, imm; |
| 96 | if (a - t + 0x8000000 >= 0x10000000) | 106 | if ((r + (1 << 21)) & ~((1U << 22) - 2)) |
| 97 | tcc_error("branch out of range"); | 107 | tcc_error("out-of-range branch chain"); |
| 98 | write32le(ptr, (a - t == 4 ? 0xd503201f : // nop | 108 | imm = (((r >> 12) & 0xff) << 12) |
| 99 | 0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b | 109 | | (((r >> 11) & 1) << 20) |
| | 110 | | (((r >> 1) & 0x3ff) << 21) |
| | 111 | | (((r >> 20) & 1) << 31); |
| | 112 | write32le(ptr, r == 4 ? 0x33 : 0x6f | imm); // nop || j imm |
| 100 | t = next; | 113 | t = next; |
| 101 | } | 114 | } |
| 102 | } | 115 | } |
| @@ -109,9 +122,19 @@ ST_FUNC void load(int r, SValue *sv) · 6 unmodified lines |
| 109 | int fc = sv->c.i; | 122 | int fc = sv->c.i; |
| 110 | if (fr & VT_LVAL) { | 123 | if (fr & VT_LVAL) { |
| 111 | if (v == VT_LOCAL) { | 124 | if (v == VT_LOCAL) { |
| | 125 | int bt = sv->type.t & VT_BTYPE; |
| | 126 | int align, size = type_size(&sv->type, &align); |
| | 127 | int func3; |
| 112 | if (((unsigned)fc + (1 << 11)) >> 12) | 128 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 113 | tcc_error("unimp: load(large local ofs) (0x%x)", fc); | 129 | tcc_error("unimp: load(large local ofs) (0x%x)", fc); |
| 114 | EI(0x03, 3, rr, 8, fc); // ld RR, fc(s0) | 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 | EI(0x03, func3, rr, 8, fc); // l[bhwd][u] RR, fc(s0) |
| 115 | } else { | 138 | } else { |
| 116 | tcc_error("unimp: load(non-local lval)"); | 139 | tcc_error("unimp: load(non-local lval)"); |
| 117 | } | 140 | } |
| @@ -139,13 +162,41 @@ ST_FUNC void load(int r, SValue *sv) · 21 unmodified lines |
| 139 | if (is_float(sv->type.t)) | 162 | if (is_float(sv->type.t)) |
| 140 | tcc_error("unimp: load(float)"); | 163 | tcc_error("unimp: load(float)"); |
| 141 | EI(0x13, 0, rr, rb, fc); // addi R, x0|R, FC | 164 | EI(0x13, 0, rr, rb, fc); // addi R, x0|R, FC |
| | 165 | } else if (v < VT_CONST) { |
| | 166 | /* reg-reg */ |
| | 167 | if (is_freg(r) && is_freg(v)) |
| | 168 | tcc_error("unimp load: float reg-reg move"); |
| | 169 | else if (is_ireg(r) && is_ireg(v)) |
| | 170 | EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V |
| | 171 | else |
| | 172 | tcc_error("ICE: inter-unit reg-reg move"); |
| | 173 | } else if (v == VT_CMP) { // we rely on cmp_r to be the correct result |
| | 174 | EI(0x13, 0, rr, vtop->cmp_r, 0); // mv RR, CMP_R |
| 142 | } else | 175 | } else |
| 143 | tcc_error("unimp: load(non-const)"); | 176 | tcc_error("unimp: load(non-const)"); |
| 144 | } | 177 | } |
| 145 | | 178 | |
| 146 | ST_FUNC void store(int r, SValue *sv) | 179 | ST_FUNC void store(int r, SValue *sv) |
| 147 | { | 180 | { |
| 148 | tcc_error("implement me: %s", __FUNCTION__); | 181 | int fr = sv->r & VT_VALMASK; |
| | 182 | int rr = ireg(r); |
| | 183 | int fc = sv->c.i; |
| | 184 | int ft = sv->type.t; |
| | 185 | int bt = ft & VT_BTYPE; |
| | 186 | int align, size = type_size(&sv->type, &align); |
| | 187 | if (fr == VT_LOCAL) { |
| | 188 | if (((unsigned)fc + (1 << 11)) >> 12) |
| | 189 | tcc_error("unimp: store(large local off) (0x%x)", fc); |
| | 190 | if (is_float(bt)) |
| | 191 | tcc_error("unimp: store(float)"); |
| | 192 | if (bt == VT_STRUCT) |
| | 193 | tcc_error("unimp: store(struct)"); |
| | 194 | if (size > 8) |
| | 195 | tcc_error("unimp: large sized store"); |
| | 196 | ES(0x23, size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, |
| | 197 | 8, rr, fc); // s[bhwd] RR, fc(s0) |
| | 198 | } else |
| | 199 | tcc_error("implement me: %s(!local)", __FUNCTION__); |
| 149 | } | 200 | } |
| 150 | | 201 | |
| 151 | static void gcall(void) | 202 | static void gcall(void) |
| @@ -174,7 +225,7 @@ ST_FUNC void gfunc_call(int nb_args) · 22 unmodified lines |
| 174 | if (aireg >= 8) | 225 | if (aireg >= 8) |
| 175 | tcc_error("unimp: too many register args"); | 226 | tcc_error("unimp: too many register args"); |
| 176 | vrotb(i+1); | 227 | vrotb(i+1); |
| 177 | gv(RC_R(aireg)); | 228 | gv(RC_R(nb_args - 1 - aireg)); |
| 178 | vrott(i+1); | 229 | vrott(i+1); |
| 179 | aireg++; | 230 | aireg++; |
| 180 | } | 231 | } |
| @@ -233,6 +284,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 52 unmodified lines |
| 233 | tcc_error("unimp: float args"); | 284 | tcc_error("unimp: float args"); |
| 234 | } else { | 285 | } else { |
| 235 | ES(0x23, 3, 8, 10 + aireg, loc + i*8); // sd aX, loc(s0) // XXX | 286 | ES(0x23, 3, 8, 10 + aireg, loc + i*8); // sd aX, loc(s0) // XXX |
| | 287 | aireg++; |
| 236 | } | 288 | } |
| 237 | } | 289 | } |
| 238 | } | 290 | } |
| @@ -303,38 +355,125 @@ ST_FUNC void gen_fill_nops(int bytes) · 64 unmodified lines |
| 303 | // Generate forward branch to label: | 355 | // Generate forward branch to label: |
| 304 | ST_FUNC int gjmp(int t) | 356 | ST_FUNC int gjmp(int t) |
| 305 | { | 357 | { |
| 306 | tcc_error("implement me: %s", __FUNCTION__); | 358 | if (nocode_wanted) |
| | 359 | return t; |
| | 360 | o(t); |
| | 361 | return ind - 4; |
| 307 | } | 362 | } |
| 308 | | 363 | |
| 309 | // Generate branch to known address: | 364 | // Generate branch to known address: |
| 310 | ST_FUNC void gjmp_addr(int a) | 365 | ST_FUNC void gjmp_addr(int a) |
| 311 | { | 366 | { |
| 312 | tcc_error("implement me: %s", __FUNCTION__); | 367 | uint32_t r = a - ind, imm; |
| | 368 | if ((r + (1 << 21)) & ~((1U << 22) - 2)) |
| | 369 | tcc_error("out-of-range jump"); |
| | 370 | imm = (((r >> 12) & 0xff) << 12) |
| | 371 | | (((r >> 11) & 1) << 20) |
| | 372 | | (((r >> 1) & 0x3ff) << 21) |
| | 373 | | (((r >> 20) & 1) << 31); |
| | 374 | o(0x6f | imm); // jal x0, imm == j imm |
| 313 | } | 375 | } |
| 314 | | 376 | |
| 315 | ST_FUNC int gjmp_cond(int op, int t) | 377 | ST_FUNC int gjmp_cond(int op, int t) |
| 316 | { | 378 | { |
| 317 | tcc_error("implement me: %s", __FUNCTION__); | 379 | int inv = op & 1; |
| | 380 | assert(op == TOK_EQ || op == TOK_NE); |
| | 381 | assert(vtop->cmp_r >= 10 && vtop->cmp_r < 18); |
| | 382 | o(0x63 | (!inv << 12) | (vtop->cmp_r << 15) | (8 << 7)); // bne/beq x0,r,+4 |
| | 383 | return gjmp(t); |
| 318 | } | 384 | } |
| 319 | | 385 | |
| 320 | ST_FUNC int gjmp_append(int n, int t) | 386 | ST_FUNC int gjmp_append(int n, int t) |
| 321 | { | 387 | { |
| 322 | tcc_error("implement me: %s", __FUNCTION__); | 388 | void *p; |
| 323 | } | 389 | /* insert jump list n into t */ |
| 324 | | 390 | if (n) { |
| 325 | ST_FUNC int gtst(int inv, int t) | 391 | uint32_t n1 = n, n2; |
| 326 | { | 392 | while ((n2 = read32le(p = cur_text_section->data + n1))) |
| 327 | tcc_error("implement me: %s", __FUNCTION__); | 393 | n1 = n2; |
| | 394 | write32le(p, t); |
| | 395 | t = n; |
| | 396 | } |
| | 397 | return t; |
| | 398 | } |
| | 399 | |
| | 400 | static void gen_opil(int op, int ll) |
| | 401 | { |
| | 402 | int a, b, d; |
| | 403 | int inv = 0; |
| | 404 | /* XXX We could special-case some constant args. */ |
| | 405 | gv2(RC_INT, RC_INT); |
| | 406 | a = ireg(vtop[-1].r); |
| | 407 | b = ireg(vtop[0].r); |
| | 408 | vtop -= 2; |
| | 409 | d = get_reg(RC_INT); |
| | 410 | vtop++; |
| | 411 | vtop[0].r = d; |
| | 412 | d = ireg(d); |
| | 413 | switch (op) { |
| | 414 | case '%': |
| | 415 | case '&': |
| | 416 | case '*': |
| | 417 | case '-': |
| | 418 | case '/': |
| | 419 | case '^': |
| | 420 | case '|': |
| | 421 | case TOK_SAR: |
| | 422 | case TOK_SHL: |
| | 423 | case TOK_SHR: |
| | 424 | case TOK_UDIV: |
| | 425 | case TOK_PDIV: |
| | 426 | case TOK_UMOD: |
| | 427 | default: |
| | 428 | tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL)); |
| | 429 | |
| | 430 | case '+': |
| | 431 | o(0x33 | (d << 7) | (a << 15) | (b << 20)); // add d, a, b |
| | 432 | break; |
| | 433 | |
| | 434 | case TOK_ULT: |
| | 435 | case TOK_UGE: |
| | 436 | case TOK_ULE: |
| | 437 | case TOK_UGT: |
| | 438 | case TOK_LT: |
| | 439 | case TOK_GE: |
| | 440 | case TOK_LE: |
| | 441 | case TOK_GT: |
| | 442 | if (op & 1) { // remove [U]GE,GT |
| | 443 | inv = 1; |
| | 444 | op--; |
| | 445 | } |
| | 446 | if ((op & 7) == 6) { // [U]LE |
| | 447 | int t = a; a = b; b = t; |
| | 448 | inv ^= 1; |
| | 449 | } |
| | 450 | o(0x33 | (d << 7) | (a << 15) | (b << 20) | (((op > TOK_UGT) ? 2 : 3) << 12)); // slt[u] d, a, b |
| | 451 | if (inv) |
| | 452 | EI(0x13, 4, d, d, 1); // xori d, d, 1 |
| | 453 | vset_VT_CMP(TOK_NE); |
| | 454 | vtop->cmp_r = d; |
| | 455 | break; |
| | 456 | case TOK_NE: |
| | 457 | case TOK_EQ: |
| | 458 | o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x20 << 25)); // sub d, a, b |
| | 459 | if (op == TOK_NE) |
| | 460 | o(0x33 | (3 << 12) | (d << 7) | (0 << 15) | (d << 20)); // sltu d, x0, d == snez d,d |
| | 461 | else |
| | 462 | EI(0x13, 3, d, d, 1); // sltiu d, d, 1 == seqz d,d |
| | 463 | vset_VT_CMP(TOK_NE); |
| | 464 | vtop->cmp_r = d; |
| | 465 | break; |
| | 466 | } |
| 328 | } | 467 | } |
| 329 | | 468 | |
| 330 | ST_FUNC void gen_opi(int op) | 469 | ST_FUNC void gen_opi(int op) |
| 331 | { | 470 | { |
| 332 | tcc_error("implement me: %s", __FUNCTION__); | 471 | gen_opil(op, 0); |
| 333 | } | 472 | } |
| 334 | | 473 | |
| 335 | ST_FUNC void gen_opl(int op) | 474 | ST_FUNC void gen_opl(int op) |
| 336 | { | 475 | { |
| 337 | tcc_error("implement me: %s", __FUNCTION__); | 476 | gen_opil(op, 1); |
| 338 | } | 477 | } |
| 339 | | 478 | |
| 340 | ST_FUNC void gen_opf(int op) | 479 | ST_FUNC void gen_opf(int op) |