The apple targets are not done yet.
Unified · Split
| @@ -324,8 +324,11 @@ struct Con { · 323 unmodified lines | |||
| 324 | double d; | 324 | double d; |
| 325 | float s; | 325 | float s; |
| 326 | } bits; | 326 | } bits; |
| 327 | enum { | ||
| 328 | RelDef, | ||
| 329 | RelThr, | ||
| 330 | } rel; | ||
| 327 | char flt; /* 1 to print as s, 2 to print as d */ | 331 | char flt; /* 1 to print as s, 2 to print as d */ |
| 328 | char local; | ||
| 329 | }; | 332 | }; |
| 330 | 333 | ||
| 331 | typedef struct Addr Addr; | 334 | typedef struct Addr Addr; |
| @@ -339,6 +342,7 @@ struct Addr { /* amd64 addressing */ · 7 unmodified lines | |||
| 339 | 342 | ||
| 340 | struct Lnk { | 343 | struct Lnk { |
| 341 | char export; | 344 | char export; |
| 345 | char thread; | ||
| 342 | char align; | 346 | char align; |
| 343 | char *sec; | 347 | char *sec; |
| 344 | char *secf; | 348 | char *secf; |
| @@ -536,7 +540,7 @@ void spill(Fn *); · 191 unmodified lines | |||
| 536 | void rega(Fn *); | 540 | void rega(Fn *); |
| 537 | 541 | ||
| 538 | /* emit.c */ | 542 | /* emit.c */ |
| 539 | void emitlnk(char *, Lnk *, char *, FILE *); | 543 | void emitfnlnk(char *, Lnk *, FILE *); |
| 540 | void emitdat(Dat *, FILE *); | 544 | void emitdat(Dat *, FILE *); |
| 541 | int stashbits(void *, int); | 545 | int stashbits(void *, int); |
| 542 | void elf_emitfnfin(char *, FILE *); | 546 | void elf_emitfnfin(char *, FILE *); |
| @@ -166,8 +166,11 @@ emitcon(Con *con, FILE *f) · 165 unmodified lines | |||
| 166 | switch (con->type) { | 166 | switch (con->type) { |
| 167 | case CAddr: | 167 | case CAddr: |
| 168 | l = str(con->label); | 168 | l = str(con->label); |
| 169 | p = con->local ? T.asloc : l[0] == '"' ? "" : T.assym; | 169 | p = l[0] == '"' ? "" : T.assym; |
| 170 | fprintf(f, "%s%s", p, l); | 170 | if (con->rel == RelThr) |
| 171 | fprintf(f, "%%fs:%s%s@tpoff", p, l); | ||
| 172 | else | ||
| 173 | fprintf(f, "%s%s", p, l); | ||
| 171 | if (con->bits.i) | 174 | if (con->bits.i) |
| 172 | fprintf(f, "%+"PRId64, con->bits.i); | 175 | fprintf(f, "%+"PRId64, con->bits.i); |
| 173 | break; | 176 | break; |
| @@ -337,7 +340,7 @@ Next: · 163 unmodified lines | |||
| 337 | case RCon: | 340 | case RCon: |
| 338 | off = fn->con[ref.val]; | 341 | off = fn->con[ref.val]; |
| 339 | emitcon(&off, f); | 342 | emitcon(&off, f); |
| 340 | if (off.type == CAddr) | 343 | if (off.type == CAddr && off.rel != RelThr) |
| 341 | fprintf(f, "(%%rip)"); | 344 | fprintf(f, "(%%rip)"); |
| 342 | break; | 345 | break; |
| 343 | case RTmp: | 346 | case RTmp: |
| @@ -549,7 +552,7 @@ emitfn(Fn *fn, FILE *f) · 205 unmodified lines | |||
| 549 | int *r, c, o, n, lbl; | 552 | int *r, c, o, n, lbl; |
| 550 | uint64_t fs; | 553 | uint64_t fs; |
| 551 | 554 | ||
| 552 | emitlnk(fn->name, &fn->lnk, ".text", f); | 555 | emitfnlnk(fn->name, &fn->lnk, f); |
| 553 | fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f); | 556 | fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f); |
| 554 | fs = framesz(fn); | 557 | fs = framesz(fn); |
| 555 | if (fs) | 558 | if (fs) |
| @@ -78,9 +78,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) · 77 unmodified lines | |||
| 78 | vgrow(&fn->mem, ++fn->nmem); | 78 | vgrow(&fn->mem, ++fn->nmem); |
| 79 | memset(&a, 0, sizeof a); | 79 | memset(&a, 0, sizeof a); |
| 80 | a.offset.type = CAddr; | 80 | a.offset.type = CAddr; |
| 81 | a.offset.local = 1; | ||
| 82 | n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4); | 81 | n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4); |
| 83 | sprintf(buf, "fp%d", n); | 82 | sprintf(buf, "\"%sfp%d\"", T.asloc, n); |
| 84 | a.offset.label = intern(buf); | 83 | a.offset.label = intern(buf); |
| 85 | fn->mem[fn->nmem-1] = a; | 84 | fn->mem[fn->nmem-1] = a; |
| 86 | } | 85 | } |
| @@ -244,7 +244,7 @@ emitf(char *s, Ins *i, E *e) · 243 unmodified lines | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static void | 246 | static void |
| 247 | loadcon(Con *c, int r, int k, E *e) | 247 | loadaddr(Con *c, char *rn, E *e) |
| 248 | { | 248 | { |
| 249 | static char *ldsym[][2] = { | 249 | static char *ldsym[][2] = { |
| 250 | /* arm64 */ | 250 | /* arm64 */ |
| @@ -254,7 +254,31 @@ loadcon(Con *c, int r, int k, E *e) · 3 unmodified lines | |||
| 254 | [1][0] = "\tadrp\t%s, %s%s@page%s\n", | 254 | [1][0] = "\tadrp\t%s, %s%s@page%s\n", |
| 255 | [1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n", | 255 | [1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n", |
| 256 | }; | 256 | }; |
| 257 | char *rn, *l, *p, off[32]; | 257 | char *p, *l, off[32]; |
| 258 | |||
| 259 | if (c->bits.i) | ||
| 260 | /* todo, handle large offsets */ | ||
| 261 | sprintf(off, "+%"PRIi64, c->bits.i); | ||
| 262 | else | ||
| 263 | off[0] = 0; | ||
| 264 | l = str(c->label); | ||
| 265 | p = l[0] == '"' ? "" : T.assym; | ||
| 266 | if (c->rel == RelThr) { | ||
| 267 | fprintf(e->f, "\tmrs\t%s, tpidr_el0\n", rn); | ||
| 268 | fprintf(e->f, "\tadd\t%s, %s, #:tprel_hi12:%s%s%s, lsl #12\n", | ||
| 269 | rn, rn, p, l, off); | ||
| 270 | fprintf(e->f, "\tadd\t%s, %s, #:tprel_lo12_nc:%s%s%s\n", | ||
| 271 | rn, rn, p, l, off); | ||
| 272 | } else { | ||
| 273 | fprintf(e->f, ldsym[e->apple][0], rn, p, l, off); | ||
| 274 | fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off); | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | static void | ||
| 279 | loadcon(Con *c, int r, int k, E *e) | ||
| 280 | { | ||
| 281 | char *rn; | ||
| 258 | int64_t n; | 282 | int64_t n; |
| 259 | int w, sh; | 283 | int w, sh; |
| 260 | 284 | ||
| @@ -262,16 +286,7 @@ loadcon(Con *c, int r, int k, E *e) · 1 unmodified line | |||
| 262 | rn = rname(r, k); | 286 | rn = rname(r, k); |
| 263 | n = c->bits.i; | 287 | n = c->bits.i; |
| 264 | if (c->type == CAddr) { | 288 | if (c->type == CAddr) { |
| 265 | rn = rname(r, Kl); | 289 | loadaddr(c, rn, e); |
| 266 | if (n) | ||
| 267 | /* todo, handle large offsets */ | ||
| 268 | sprintf(off, "+%"PRIi64, n); | ||
| 269 | else | ||
| 270 | off[0] = 0; | ||
| 271 | l = str(c->label); | ||
| 272 | p = c->local ? T.asloc : l[0] == '"' ? "" : T.assym; | ||
| 273 | fprintf(e->f, ldsym[e->apple][0], rn, p, l, off); | ||
| 274 | fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off); | ||
| 275 | return; | 290 | return; |
| 276 | } | 291 | } |
| 277 | assert(c->type == CBits); | 292 | assert(c->type == CBits); |
| @@ -471,7 +486,7 @@ emitfn(E *e) · 193 unmodified lines | |||
| 471 | Blk *b, *t; | 486 | Blk *b, *t; |
| 472 | Ins *i; | 487 | Ins *i; |
| 473 | 488 | ||
| 474 | emitlnk(e->fn->name, &e->fn->lnk, ".text", e->f); | 489 | emitfnlnk(e->fn->name, &e->fn->lnk, e->f); |
| 475 | framelayout(e); | 490 | framelayout(e); |
| 476 | 491 | ||
| 477 | if (e->fn->vararg && !e->apple) { | 492 | if (e->fn->vararg && !e->apple) { |
| @@ -87,8 +87,8 @@ fixarg(Ref *pr, int k, int phi, Fn *fn) · 86 unmodified lines | |||
| 87 | n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); | 87 | n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); |
| 88 | vgrow(&fn->con, ++fn->ncon); | 88 | vgrow(&fn->con, ++fn->ncon); |
| 89 | c = &fn->con[fn->ncon-1]; | 89 | c = &fn->con[fn->ncon-1]; |
| 90 | sprintf(buf, "fp%d", n); | 90 | sprintf(buf, "\"%sfp%d\"", T.asloc, n); |
| 91 | *c = (Con){.type = CAddr, .local = 1}; | 91 | *c = (Con){.type = CAddr}; |
| 92 | c->label = intern(buf); | 92 | c->label = intern(buf); |
| 93 | r2 = newtmp("isel", Kl, fn); | 93 | r2 = newtmp("isel", Kl, fn); |
| 94 | emit(Oload, k, r1, r2, R); | 94 | emit(Oload, k, r1, r2, R); |
| @@ -1,17 +1,30 @@ | |||
| 1 | #include "all.h" | 1 | #include "all.h" |
| 2 | 2 | ||
| 3 | enum { | ||
| 4 | SecText, | ||
| 5 | SecData, | ||
| 6 | SecBss, | ||
| 7 | }; | ||
| 8 | |||
| 3 | void | 9 | void |
| 4 | emitlnk(char *n, Lnk *l, char *s, FILE *f) | 10 | emitlnk(char *n, Lnk *l, int s, FILE *f) |
| 5 | { | 11 | { |
| 12 | static char *sec[2][3] = { | ||
| 13 | [0][SecText] = ".text", | ||
| 14 | [0][SecData] = ".data", | ||
| 15 | [0][SecBss] = ".bss", | ||
| 16 | [1][SecText] = ".abort \"unreachable\"", | ||
| 17 | [1][SecData] = ".section .tdata,\"awT\"", | ||
| 18 | [1][SecBss] = ".section .tbss,\"awT\"", | ||
| 19 | }; | ||
| 6 | char *p; | 20 | char *p; |
| 7 | 21 | ||
| 8 | if (l->sec) { | 22 | if (l->sec) { |
| 9 | fprintf(f, ".section %s", l->sec); | 23 | fprintf(f, ".section %s", l->sec); |
| 10 | if (l->secf) | 24 | if (l->secf) |
| 11 | fprintf(f, ", %s", l->secf); | 25 | fprintf(f, ",%s", l->secf); |
| 12 | } else { | 26 | } else |
| 13 | fputs(s, f); | 27 | fputs(sec[l->thread != 0][s], f); |
| 14 | } | ||
| 15 | fputc('\n', f); | 28 | fputc('\n', f); |
| 16 | if (l->align) | 29 | if (l->align) |
| 17 | fprintf(f, ".balign %d\n", l->align); | 30 | fprintf(f, ".balign %d\n", l->align); |
| @@ -21,6 +34,12 @@ emitlnk(char *n, Lnk *l, char *s, FILE *f) · 3 unmodified lines | |||
| 21 | fprintf(f, "%s%s:\n", p, n); | 34 | fprintf(f, "%s%s:\n", p, n); |
| 22 | } | 35 | } |
| 23 | 36 | ||
| 37 | void | ||
| 38 | emitfnlnk(char *n, Lnk *l, FILE *f) | ||
| 39 | { | ||
| 40 | emitlnk(n, l, SecText, f); | ||
| 41 | } | ||
| 42 | |||
| 24 | void | 43 | void |
| 25 | emitdat(Dat *d, FILE *f) | 44 | emitdat(Dat *d, FILE *f) |
| 26 | { | 45 | { |
| @@ -39,7 +58,7 @@ emitdat(Dat *d, FILE *f) · 12 unmodified lines | |||
| 39 | break; | 58 | break; |
| 40 | case DEnd: | 59 | case DEnd: |
| 41 | if (zero != -1) { | 60 | if (zero != -1) { |
| 42 | emitlnk(d->name, d->lnk, ".bss", f); | 61 | emitlnk(d->name, d->lnk, SecBss, f); |
| 43 | fprintf(f, "\t.fill %"PRId64",1,0\n", zero); | 62 | fprintf(f, "\t.fill %"PRId64",1,0\n", zero); |
| 44 | } | 63 | } |
| 45 | break; | 64 | break; |
| @@ -51,7 +70,7 @@ emitdat(Dat *d, FILE *f) · 5 unmodified lines | |||
| 51 | break; | 70 | break; |
| 52 | default: | 71 | default: |
| 53 | if (zero != -1) { | 72 | if (zero != -1) { |
| 54 | emitlnk(d->name, d->lnk, ".data", f); | 73 | emitlnk(d->name, d->lnk, SecData, f); |
| 55 | if (zero > 0) | 74 | if (zero > 0) |
| 56 | fprintf(f, "\t.fill %"PRId64",1,0\n", zero); | 75 | fprintf(f, "\t.fill %"PRId64",1,0\n", zero); |
| 57 | zero = -1; | 76 | zero = -1; |
| @@ -165,7 +184,7 @@ macho_emitfin(FILE *f) · 107 unmodified lines | |||
| 165 | static char *sec[3] = { | 184 | static char *sec[3] = { |
| 166 | "__TEXT,__literal4,4byte_literals", | 185 | "__TEXT,__literal4,4byte_literals", |
| 167 | "__TEXT,__literal8,8byte_literals", | 186 | "__TEXT,__literal8,8byte_literals", |
| 168 | ".rodata", /* should not happen */ | 187 | ".abort \"unreachable\"", |
| 169 | }; | 188 | }; |
| 170 | 189 | ||
| 171 | emitfin(f, sec); | 190 | emitfin(f, sec); |
| @@ -334,9 +334,10 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 333 unmodified lines | |||
| 334 | } l, r; | 334 | } l, r; |
| 335 | uint64_t x; | 335 | uint64_t x; |
| 336 | uint32_t lab; | 336 | uint32_t lab; |
| 337 | int typ; | 337 | int typ, rel; |
| 338 | 338 | ||
| 339 | typ = CBits; | 339 | typ = CBits; |
| 340 | rel = RelDef; | ||
| 340 | lab = 0; | 341 | lab = 0; |
| 341 | l.s = cl->bits.i; | 342 | l.s = cl->bits.i; |
| 342 | r.s = cr->bits.i; | 343 | r.s = cr->bits.i; |
| @@ -345,10 +346,12 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 2 unmodified lines | |||
| 345 | if (cr->type == CAddr) | 346 | if (cr->type == CAddr) |
| 346 | return 1; | 347 | return 1; |
| 347 | lab = cl->label; | 348 | lab = cl->label; |
| 349 | rel = cl->rel; | ||
| 348 | typ = CAddr; | 350 | typ = CAddr; |
| 349 | } | 351 | } |
| 350 | else if (cr->type == CAddr) { | 352 | else if (cr->type == CAddr) { |
| 351 | lab = cr->label; | 353 | lab = cr->label; |
| 354 | rel = cr->rel; | ||
| 352 | typ = CAddr; | 355 | typ = CAddr; |
| 353 | } | 356 | } |
| 354 | } | 357 | } |
| @@ -356,6 +359,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 1 unmodified line | |||
| 356 | if (cl->type == CAddr) { | 359 | if (cl->type == CAddr) { |
| 357 | if (cr->type != CAddr) { | 360 | if (cr->type != CAddr) { |
| 358 | lab = cl->label; | 361 | lab = cl->label; |
| 362 | rel = cl->rel; | ||
| 359 | typ = CAddr; | 363 | typ = CAddr; |
| 360 | } else if (cl->label != cr->label) | 364 | } else if (cl->label != cr->label) |
| 361 | return 1; | 365 | return 1; |
| @@ -404,6 +408,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 42 unmodified lines | |||
| 404 | x = l.u; | 408 | x = l.u; |
| 405 | if (cl->type == CAddr) { | 409 | if (cl->type == CAddr) { |
| 406 | lab = cl->label; | 410 | lab = cl->label; |
| 411 | rel = cl->rel; | ||
| 407 | typ = CAddr; | 412 | typ = CAddr; |
| 408 | } | 413 | } |
| 409 | break; | 414 | break; |
| @@ -457,7 +462,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 47 unmodified lines | |||
| 457 | else | 462 | else |
| 458 | die("unreachable"); | 463 | die("unreachable"); |
| 459 | } | 464 | } |
| 460 | *res = (Con){.type=typ, .label=lab, .bits={.i=x}}; | 465 | *res = (Con){.type=typ, .label=lab, .rel=rel, .bits={.i=x}}; |
| 461 | return 0; | 466 | return 0; |
| 462 | } | 467 | } |
| 463 | 468 | ||
| @@ -155,7 +155,7 @@ load(Slice sl, bits msk, Loc *l) · 154 unmodified lines | |||
| 155 | c.type = CAddr; | 155 | c.type = CAddr; |
| 156 | c.label = a->label; | 156 | c.label = a->label; |
| 157 | c.bits.i = a->offset; | 157 | c.bits.i = a->offset; |
| 158 | c.local = 0; | 158 | c.rel = RelDef; |
| 159 | r = newcon(&c, curf); | 159 | r = newcon(&c, curf); |
| 160 | break; | 160 | break; |
| 161 | } | 161 | } |
| @@ -45,6 +45,7 @@ enum { · 44 unmodified lines | |||
| 45 | Tjnz, | 45 | Tjnz, |
| 46 | Tret, | 46 | Tret, |
| 47 | Texport, | 47 | Texport, |
| 48 | Tthread, | ||
| 48 | Tfunc, | 49 | Tfunc, |
| 49 | Ttype, | 50 | Ttype, |
| 50 | Tdata, | 51 | Tdata, |
| @@ -99,6 +100,7 @@ static char *kwmap[Ntok] = { · 48 unmodified lines | |||
| 99 | [Tjnz] = "jnz", | 100 | [Tjnz] = "jnz", |
| 100 | [Tret] = "ret", | 101 | [Tret] = "ret", |
| 101 | [Texport] = "export", | 102 | [Texport] = "export", |
| 103 | [Tthread] = "thread", | ||
| 102 | [Tfunc] = "function", | 104 | [Tfunc] = "function", |
| 103 | [Ttype] = "type", | 105 | [Ttype] = "type", |
| 104 | [Tdata] = "data", | 106 | [Tdata] = "data", |
| @@ -399,30 +401,34 @@ parseref() · 294 unmodified lines | |||
| 399 | 401 | ||
| 400 | memset(&c, 0, sizeof c); | 402 | memset(&c, 0, sizeof c); |
| 401 | switch (next()) { | 403 | switch (next()) { |
| 404 | default: | ||
| 405 | return R; | ||
| 402 | case Ttmp: | 406 | case Ttmp: |
| 403 | return tmpref(tokval.str); | 407 | return tmpref(tokval.str); |
| 404 | case Tint: | 408 | case Tint: |
| 405 | c.type = CBits; | 409 | c.type = CBits; |
| 406 | c.bits.i = tokval.num; | 410 | c.bits.i = tokval.num; |
| 407 | goto Look; | 411 | break; |
| 408 | case Tflts: | 412 | case Tflts: |
| 409 | c.type = CBits; | 413 | c.type = CBits; |
| 410 | c.bits.s = tokval.flts; | 414 | c.bits.s = tokval.flts; |
| 411 | c.flt = 1; | 415 | c.flt = 1; |
| 412 | goto Look; | 416 | break; |
| 413 | case Tfltd: | 417 | case Tfltd: |
| 414 | c.type = CBits; | 418 | c.type = CBits; |
| 415 | c.bits.d = tokval.fltd; | 419 | c.bits.d = tokval.fltd; |
| 416 | c.flt = 2; | 420 | c.flt = 2; |
| 417 | goto Look; | 421 | break; |
| 422 | case Tthread: | ||
| 423 | c.rel = RelThr; | ||
| 424 | expect(Tglo); | ||
| 425 | /* fall through */ | ||
| 418 | case Tglo: | 426 | case Tglo: |
| 419 | c.type = CAddr; | 427 | c.type = CAddr; |
| 420 | c.label = intern(tokval.str); | 428 | c.label = intern(tokval.str); |
| 421 | Look: | 429 | break; |
| 422 | return newcon(&c, curf); | ||
| 423 | default: | ||
| 424 | return R; | ||
| 425 | } | 430 | } |
| 431 | return newcon(&c, curf); | ||
| 426 | } | 432 | } |
| 427 | 433 | ||
| 428 | static int | 434 | static int |
| @@ -1101,6 +1107,9 @@ parselnk(Lnk *lnk) · 672 unmodified lines | |||
| 1101 | case Texport: | 1107 | case Texport: |
| 1102 | lnk->export = 1; | 1108 | lnk->export = 1; |
| 1103 | break; | 1109 | break; |
| 1110 | case Tthread: | ||
| 1111 | lnk->thread = 1; | ||
| 1112 | break; | ||
| 1104 | case Tsection: | 1113 | case Tsection: |
| 1105 | if (lnk->sec) | 1114 | if (lnk->sec) |
| 1106 | err("only one section allowed"); | 1115 | err("only one section allowed"); |
| @@ -1113,9 +1122,9 @@ parselnk(Lnk *lnk) · 6 unmodified lines | |||
| 1113 | } | 1122 | } |
| 1114 | break; | 1123 | break; |
| 1115 | default: | 1124 | default: |
| 1116 | if (haslnk) | 1125 | if (t == Tfunc && lnk->thread) |
| 1117 | if (t != Tdata) | 1126 | err("only data may have thread linkage"); |
| 1118 | if (t != Tfunc) | 1127 | if (haslnk && t != Tdata && t != Tfunc) |
| 1119 | err("only data and function have linkage"); | 1128 | err("only data and function have linkage"); |
| 1120 | return t; | 1129 | return t; |
| 1121 | } | 1130 | } |
| @@ -1244,8 +1253,6 @@ printfn(Fn *fn, FILE *f) · 122 unmodified lines | |||
| 1244 | Ins *i; | 1253 | Ins *i; |
| 1245 | uint n; | 1254 | uint n; |
| 1246 | 1255 | ||
| 1247 | if (fn->lnk.export) | ||
| 1248 | fprintf(f, "export "); | ||
| 1249 | fprintf(f, "function $%s() {\n", fn->name); | 1256 | fprintf(f, "function $%s() {\n", fn->name); |
| 1250 | for (b=fn->start; b; b=b->link) { | 1257 | for (b=fn->start; b; b=b->link) { |
| 1251 | fprintf(f, "@%s\n", b->name); | 1258 | fprintf(f, "@%s\n", b->name); |
| @@ -129,14 +129,10 @@ slot(int s, Fn *fn) · 128 unmodified lines | |||
| 129 | static void | 129 | static void |
| 130 | emitaddr(Con *c, FILE *f) | 130 | emitaddr(Con *c, FILE *f) |
| 131 | { | 131 | { |
| 132 | char off[32], *p; | 132 | assert(c->rel == RelDef); |
| 133 | 133 | fputs(str(c->label), f); | |
| 134 | if (c->bits.i) | 134 | if (c->bits.i) |
| 135 | sprintf(off, "+%"PRIi64, c->bits.i); | 135 | fprintf(f, "+%"PRIi64, c->bits.i); |
| 136 | else | ||
| 137 | off[0] = 0; | ||
| 138 | p = c->local ? ".L" : ""; | ||
| 139 | fprintf(f, "%s%s%s", p, str(c->label), off); | ||
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | static void | 138 | static void |
| @@ -228,26 +224,45 @@ emitf(char *s, Ins *i, Fn *fn, FILE *f) · 85 unmodified lines | |||
| 228 | } | 224 | } |
| 229 | } | 225 | } |
| 230 | 226 | ||
| 227 | static void | ||
| 228 | loadaddr(Con *c, char *rn, FILE *f) | ||
| 229 | { | ||
| 230 | char off[32]; | ||
| 231 | |||
| 232 | if (c->rel == RelThr) { | ||
| 233 | if (c->bits.i) | ||
| 234 | sprintf(off, "+%"PRIi64, c->bits.i); | ||
| 235 | else | ||
| 236 | off[0] = 0; | ||
| 237 | fprintf(f, "\tlui %s, %%tprel_hi(%s)%s\n", | ||
| 238 | rn, str(c->label), off); | ||
| 239 | fprintf(f, "\tadd %s, %s, tp, %%tprel_add(%s)%s\n", | ||
| 240 | rn, rn, str(c->label), off); | ||
| 241 | fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n", | ||
| 242 | rn, rn, str(c->label), off); | ||
| 243 | } else { | ||
| 244 | fprintf(f, "\tla %s, ", rn); | ||
| 245 | emitaddr(c, f); | ||
| 246 | fputc('\n', f); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 231 | static void | 250 | static void |
| 232 | loadcon(Con *c, int r, int k, FILE *f) | 251 | loadcon(Con *c, int r, int k, FILE *f) |
| 233 | { | 252 | { |
| 234 | char *rn; | 253 | char *rn; |
| 235 | int64_t n; | 254 | int64_t n; |
| 236 | int w; | ||
| 237 | 255 | ||
| 238 | w = KWIDE(k); | ||
| 239 | rn = rname[r]; | 256 | rn = rname[r]; |
| 240 | switch (c->type) { | 257 | switch (c->type) { |
| 241 | case CAddr: | 258 | case CAddr: |
| 242 | fprintf(f, "\tla %s, ", rn); | 259 | loadaddr(c, rn, f); |
| 243 | emitaddr(c, f); | ||
| 244 | fputc('\n', f); | ||
| 245 | break; | 260 | break; |
| 246 | case CBits: | 261 | case CBits: |
| 247 | n = c->bits.i; | 262 | n = c->bits.i; |
| 248 | if (!w) | 263 | if (!KWIDE(k)) |
| 249 | n = (int32_t)n; | 264 | n = (int32_t)n; |
| 250 | fprintf(f, "\tli %s, %"PRIu64"\n", rn, n); | 265 | fprintf(f, "\tli %s, %"PRIi64"\n", rn, n); |
| 251 | break; | 266 | break; |
| 252 | default: | 267 | default: |
| 253 | die("invalid constant"); | 268 | die("invalid constant"); |
| @@ -255,12 +270,20 @@ loadcon(Con *c, int r, int k, FILE *f) · 1 unmodified line | |||
| 255 | } | 270 | } |
| 256 | 271 | ||
| 257 | static void | 272 | static void |
| 258 | fixslot(Ref *pr, Fn *fn, FILE *f) | 273 | fixmem(Ref *pr, Fn *fn, FILE *f) |
| 259 | { | 274 | { |
| 260 | Ref r; | 275 | Ref r; |
| 261 | int64_t s; | 276 | int64_t s; |
| 277 | Con *c; | ||
| 262 | 278 | ||
| 263 | r = *pr; | 279 | r = *pr; |
| 280 | if (rtype(r) == RCon) { | ||
| 281 | c = &fn->con[r.val]; | ||
| 282 | if (c->type == CAddr && c->rel == RelThr) { | ||
| 283 | loadcon(c, T6, Kl, f); | ||
| 284 | *pr = TMP(T6); | ||
| 285 | } | ||
| 286 | } | ||
| 264 | if (rtype(r) == RSlot) { | 287 | if (rtype(r) == RSlot) { |
| 265 | s = slot(r.val, fn); | 288 | s = slot(r.val, fn); |
| 266 | if (s < -2048 || s > 2047) { | 289 | if (s < -2048 || s > 2047) { |
| @@ -282,9 +305,9 @@ emitins(Ins *i, Fn *fn, FILE *f) · 15 unmodified lines | |||
| 282 | switch (i->op) { | 305 | switch (i->op) { |
| 283 | default: | 306 | default: |
| 284 | if (isload(i->op)) | 307 | if (isload(i->op)) |
| 285 | fixslot(&i->arg[0], fn, f); | 308 | fixmem(&i->arg[0], fn, f); |
| 286 | else if (isstore(i->op)) | 309 | else if (isstore(i->op)) |
| 287 | fixslot(&i->arg[1], fn, f); | 310 | fixmem(&i->arg[1], fn, f); |
| 288 | Table: | 311 | Table: |
| 289 | /* most instructions are just pulled out of | 312 | /* most instructions are just pulled out of |
| 290 | * the table omap[], some special cases are | 313 | * the table omap[], some special cases are |
| @@ -321,7 +344,7 @@ emitins(Ins *i, Fn *fn, FILE *f) · 30 unmodified lines | |||
| 321 | case Ks: i->op = Ostores; break; | 344 | case Ks: i->op = Ostores; break; |
| 322 | case Kd: i->op = Ostored; break; | 345 | case Kd: i->op = Ostored; break; |
| 323 | } | 346 | } |
| 324 | fixslot(&i->arg[1], fn, f); | 347 | fixmem(&i->arg[1], fn, f); |
| 325 | goto Table; | 348 | goto Table; |
| 326 | } | 349 | } |
| 327 | break; | 350 | break; |
| @@ -333,7 +356,7 @@ emitins(Ins *i, Fn *fn, FILE *f) · 5 unmodified lines | |||
| 333 | break; | 356 | break; |
| 334 | case RSlot: | 357 | case RSlot: |
| 335 | i->op = Oload; | 358 | i->op = Oload; |
| 336 | fixslot(&i->arg[0], fn, f); | 359 | fixmem(&i->arg[0], fn, f); |
| 337 | goto Table; | 360 | goto Table; |
| 338 | default: | 361 | default: |
| 339 | assert(isreg(i->arg[0])); | 362 | assert(isreg(i->arg[0])); |
| @@ -415,7 +438,7 @@ rv64_emitfn(Fn *fn, FILE *f) · 75 unmodified lines | |||
| 415 | Blk *b, *s; | 438 | Blk *b, *s; |
| 416 | Ins *i; | 439 | Ins *i; |
| 417 | 440 | ||
| 418 | emitlnk(fn->name, &fn->lnk, ".text", f); | 441 | emitfnlnk(fn->name, &fn->lnk, f); |
| 419 | 442 | ||
| 420 | if (fn->vararg) { | 443 | if (fn->vararg) { |
| 421 | /* TODO: only need space for registers | 444 | /* TODO: only need space for registers |
| @@ -44,8 +44,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) · 43 unmodified lines | |||
| 44 | n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); | 44 | n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); |
| 45 | vgrow(&fn->con, ++fn->ncon); | 45 | vgrow(&fn->con, ++fn->ncon); |
| 46 | c = &fn->con[fn->ncon-1]; | 46 | c = &fn->con[fn->ncon-1]; |
| 47 | sprintf(buf, "fp%d", n); | 47 | sprintf(buf, "\"%sfp%d\"", T.asloc, n); |
| 48 | *c = (Con){.type = CAddr, .local = 1}; | 48 | *c = (Con){.type = CAddr}; |
| 49 | c->label = intern(buf); | 49 | c->label = intern(buf); |
| 50 | emit(Oload, k, r1, CON(c-fn->con), R); | 50 | emit(Oload, k, r1, CON(c-fn->con), R); |
| 51 | break; | 51 | break; |
| @@ -358,9 +358,9 @@ newcon(Con *c0, Fn *fn) · 357 unmodified lines | |||
| 358 | for (i=0; i<fn->ncon; i++) { | 358 | for (i=0; i<fn->ncon; i++) { |
| 359 | c1 = &fn->con[i]; | 359 | c1 = &fn->con[i]; |
| 360 | if (c0->type == c1->type | 360 | if (c0->type == c1->type |
| 361 | && c0->bits.i == c1->bits.i | ||
| 362 | && c0->label == c1->label | 361 | && c0->label == c1->label |
| 363 | && c0->local == c1->local) | 362 | && c0->bits.i == c1->bits.i |
| 363 | && c0->rel == c1->rel) | ||
| 364 | return CON(i); | 364 | return CON(i); |
| 365 | } | 365 | } |
| 366 | vgrow(&fn->con, ++fn->ncon); | 366 | vgrow(&fn->con, ++fn->ncon); |