cgen: extract the narrow-tail aggregate-register materialise into a shared helper (#14)
This commit is contained in:
160
cmd/w6c/cgen.c
160
cmd/w6c/cgen.c
@@ -2341,6 +2341,62 @@ cg_aggcopy(Cg *c, int sz)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cg_agg_reg_store — the ONE register-cursor aggregate materialise: an
|
||||||
|
* in-cap (<=24B, GP-class) struct/array/tuple already held in the
|
||||||
|
* {AX,DX,CX} return cursor is stored into the place base_reg+disp.
|
||||||
|
* full = sz/8 exact-8B MOVQ words land straight in (safe into any dest);
|
||||||
|
* the sz%8 tail is one sized MOVB/MOVW/MOVL for {1,2,4} (BOTH branches).
|
||||||
|
* Extracted from site E (the #10 template) so every narrow-tail
|
||||||
|
* materialise funnels through one place — close-by-construction (#14).
|
||||||
|
*
|
||||||
|
* dest_padded forks ONLY the {3,5,6,7} tail (no GP sub-register exists
|
||||||
|
* for those widths and w6a has no shift):
|
||||||
|
* dest_padded == "the dest is a ceil-8/round8 slot (a scratch, or a
|
||||||
|
* #75 let/local aggregate slot) so an 8B tail over-store stays
|
||||||
|
* in-bounds." Post-#9: packed struct fields + array elements => 0;
|
||||||
|
* let/local/scratch slots => 1. It CANNOT be derived — paddedness is
|
||||||
|
* routing knowledge the caller owns.
|
||||||
|
* 1 -> a single full MOVQ of the cursor tail eightbyte (= E's #10
|
||||||
|
* template; the over-store lands in the slot's pad).
|
||||||
|
* 0 -> MOVQ the cursor tail eightbyte into the helper's own ceil-8
|
||||||
|
* @tagscr pad, then a sized aggcopy of the tail bytes into the
|
||||||
|
* dest so a packed field / array element is never overrun.
|
||||||
|
* PRECONDITION (caller-owned, stays per-site): the value is already in
|
||||||
|
* AX/DX/CX, the dest base is resolved into base_reg+disp, and the
|
||||||
|
* float-class (#165) / over-cap-sret (#234) loud-stops have already
|
||||||
|
* fired. Clobbers SI/BX/AX only on the dest_padded==0 detour (the value
|
||||||
|
* words are in memory by then). */
|
||||||
|
static void
|
||||||
|
cg_agg_reg_store(Cg *c, Local **locals, int base_reg, int disp, int sz,
|
||||||
|
int dest_padded)
|
||||||
|
{
|
||||||
|
int regs[3] = { D_AX, D_DX, D_CX };
|
||||||
|
int full = sz / 8;
|
||||||
|
int tail = sz % 8;
|
||||||
|
for (int i = 0; i < full; i++)
|
||||||
|
ins2(c, A_MOVQ, areg(regs[i]),
|
||||||
|
amem(base_reg, disp + i * 8));
|
||||||
|
if (tail == 0)
|
||||||
|
return;
|
||||||
|
if (tail == 1 || tail == 2 || tail == 4) {
|
||||||
|
int op = (tail == 1) ? A_MOVB
|
||||||
|
: (tail == 2) ? A_MOVW : A_MOVL;
|
||||||
|
ins2(c, op, areg(regs[full]),
|
||||||
|
amem(base_reg, disp + full * 8));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dest_padded) {
|
||||||
|
ins2(c, A_MOVQ, areg(regs[full]),
|
||||||
|
amem(base_reg, disp + full * 8));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int pad = cg_tagscr_slot(c, locals, 8);
|
||||||
|
ins2(c, A_MOVQ, areg(regs[full]), amem(D_BP, pad));
|
||||||
|
ins2(c, A_LEAQ, amem(D_BP, pad), areg(D_SI));
|
||||||
|
ins2(c, A_LEAQ, amem(base_reg, disp + full * 8), areg(D_BX));
|
||||||
|
cg_aggcopy(c, tail);
|
||||||
|
}
|
||||||
|
|
||||||
/* cgplaceaddr — compute the ADDRESS of an arbitrary place (lvalue)
|
/* cgplaceaddr — compute the ADDRESS of an arbitrary place (lvalue)
|
||||||
* expression into dst_reg; returns 1 when the shape is wired, 0
|
* expression into dst_reg; returns 1 when the shape is wired, 0
|
||||||
* otherwise (the caller loud-stops — rule 7, never a silent drop).
|
* otherwise (the caller loud-stops — rule 7, never a silent drop).
|
||||||
@@ -3480,20 +3536,8 @@ cg_structlit_fill(Cg *c, Local **locals_p, Type *lu, Node *lit,
|
|||||||
ins2(c, A_LEAQ, masym(c, name), areg(D_BX));
|
ins2(c, A_LEAQ, masym(c, name), areg(D_BX));
|
||||||
else if (mode == DST_PTR_SP)
|
else if (mode == DST_PTR_SP)
|
||||||
ins2(c, A_MOVQ, amem(D_SP, 0), areg(D_BX));
|
ins2(c, A_MOVQ, amem(D_SP, 0), areg(D_BX));
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
cg_agg_reg_store(c, locals_p, base_reg,
|
||||||
int full = fsz / 8;
|
disp + (int)foff, fsz, 0);
|
||||||
int tail = fsz % 8;
|
|
||||||
for (int i = 0; i < full; i++)
|
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
|
||||||
amem(base_reg,
|
|
||||||
disp + (int)foff + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW : A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(base_reg,
|
|
||||||
disp + (int)foff + full * 8));
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* str IS []u8: 3-word field (ptr,len,cap). cgexpr leaves
|
/* str IS []u8: 3-word field (ptr,len,cap). cgexpr leaves
|
||||||
@@ -5252,18 +5296,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
ins1(c, A_PUSHQ, areg(D_BX));
|
ins1(c, A_PUSHQ, areg(D_BX));
|
||||||
cgexpr(c, n->rhs, locals);
|
cgexpr(c, n->rhs, locals);
|
||||||
ins1(c, A_POPQ, areg(D_BX));
|
ins1(c, A_POPQ, areg(D_BX));
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
cg_agg_reg_store(c, &locals, D_BX, 0, ssz, 0);
|
||||||
int full = ssz / 8;
|
|
||||||
int tail = ssz % 8;
|
|
||||||
for (int i = 0; i < full; i++)
|
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
|
||||||
amem(D_BX, i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW : A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(D_BX, full * 8));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5495,9 +5528,6 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
|| str_fu->size % 8 == 4)) {
|
|| str_fu->size % 8 == 4)) {
|
||||||
int ssz = (int)str_fu->size;
|
int ssz = (int)str_fu->size;
|
||||||
cgexpr(c, n->rhs, locals);
|
cgexpr(c, n->rhs, locals);
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
|
||||||
int full = ssz / 8;
|
|
||||||
int tail = ssz % 8;
|
|
||||||
int base_reg, base_disp;
|
int base_reg, base_disp;
|
||||||
if (via_ptr || is_global) {
|
if (via_ptr || is_global) {
|
||||||
if (via_ptr)
|
if (via_ptr)
|
||||||
@@ -5514,18 +5544,8 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
base_reg = D_BP;
|
base_reg = D_BP;
|
||||||
base_disp = boff + foff;
|
base_disp = boff + foff;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < full; i++)
|
cg_agg_reg_store(c, &locals, base_reg,
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
base_disp, ssz, 0);
|
||||||
amem(base_reg,
|
|
||||||
base_disp + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW
|
|
||||||
: A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(base_reg,
|
|
||||||
base_disp + full * 8));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (n->op == TK_ASSIGN && str_fu
|
if (n->op == TK_ASSIGN && str_fu
|
||||||
@@ -6723,9 +6743,6 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
&& (fsz % 8 == 0 || fsz % 8 == 1
|
&& (fsz % 8 == 0 || fsz % 8 == 1
|
||||||
|| fsz % 8 == 2 || fsz % 8 == 4)) {
|
|| fsz % 8 == 2 || fsz % 8 == 4)) {
|
||||||
cgexpr(c, n->rhs, locals);
|
cgexpr(c, n->rhs, locals);
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
|
||||||
int full = fsz / 8;
|
|
||||||
int tail = fsz % 8;
|
|
||||||
int base_reg, base_off;
|
int base_reg, base_off;
|
||||||
if (via_cx) {
|
if (via_cx) {
|
||||||
if (ptr_root)
|
if (ptr_root)
|
||||||
@@ -6742,18 +6759,8 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
base_reg = D_BP;
|
base_reg = D_BP;
|
||||||
base_off = base_disp + total_off;
|
base_off = base_disp + total_off;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < full; i++)
|
cg_agg_reg_store(c, &locals,
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
base_reg, base_off, fsz, 0);
|
||||||
amem(base_reg,
|
|
||||||
base_off + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW
|
|
||||||
: A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(base_reg,
|
|
||||||
base_off + full * 8));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fu && fu->kind == TY_STRUCT
|
if (fu && fu->kind == TY_STRUCT
|
||||||
@@ -7119,19 +7126,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
int scr = cg_tagscr_slot(c, &locals, esz);
|
int scr = cg_tagscr_slot(c, &locals, esz);
|
||||||
cgexpr(c, n->rhs, locals); /* call → AX/DX/CX */
|
cgexpr(c, n->rhs, locals); /* call → AX/DX/CX */
|
||||||
/* AX/DX/CX → scratch (mirror cgen.c:3434 receive). */
|
/* AX/DX/CX → scratch (mirror cgen.c:3434 receive). */
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
cg_agg_reg_store(c, &locals, D_BP, scr, esz, 1);
|
||||||
int full = esz / 8;
|
|
||||||
int tail = esz % 8;
|
|
||||||
for (int i = 0; i < full; i++)
|
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
|
||||||
amem(D_BP, scr + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 1) ? A_MOVB
|
|
||||||
: (tail == 2) ? A_MOVW
|
|
||||||
: (tail == 4) ? A_MOVL : A_MOVQ;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(D_BP, scr + full * 8));
|
|
||||||
}
|
|
||||||
/* dest &a[i] → BX (mirror #121 / #270-1b resolve) */
|
/* dest &a[i] → BX (mirror #121 / #270-1b resolve) */
|
||||||
cgexpr(c, n->lhs->rhs, locals); /* idx → AX */
|
cgexpr(c, n->lhs->rhs, locals); /* idx → AX */
|
||||||
if (esz > 1) {
|
if (esz > 1) {
|
||||||
@@ -7954,19 +7949,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
|| sz % 8 == 2
|
|| sz % 8 == 2
|
||||||
|| sz % 8 == 4)) {
|
|| sz % 8 == 4)) {
|
||||||
cgexpr(c, n->rhs, locals);
|
cgexpr(c, n->rhs, locals);
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
cg_agg_reg_store(c, &locals, D_BP, off, sz, 0);
|
||||||
int full = sz / 8;
|
|
||||||
int tail = sz % 8;
|
|
||||||
for (int i = 0; i < full; i++)
|
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
|
||||||
amem(D_BP, off + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW
|
|
||||||
: A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(D_BP, off + full * 8));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isglob && au->kind == TY_ARRAY
|
if (isglob && au->kind == TY_ARRAY
|
||||||
@@ -13623,18 +13606,7 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
|||||||
&& (sz % 8 == 0 || sz % 8 == 1
|
&& (sz % 8 == 0 || sz % 8 == 1
|
||||||
|| sz % 8 == 2 || sz % 8 == 4)) {
|
|| sz % 8 == 2 || sz % 8 == 4)) {
|
||||||
cgexpr(c, n->rhs, *locals);
|
cgexpr(c, n->rhs, *locals);
|
||||||
int regs[3] = { D_AX, D_DX, D_CX };
|
cg_agg_reg_store(c, locals, D_BP, off, sz, 1);
|
||||||
int full = sz / 8;
|
|
||||||
int tail = sz % 8;
|
|
||||||
for (int i = 0; i < full; i++)
|
|
||||||
ins2(c, A_MOVQ, areg(regs[i]),
|
|
||||||
amem(D_BP, off + i * 8));
|
|
||||||
if (tail > 0) {
|
|
||||||
int op = (tail == 4) ? A_MOVL
|
|
||||||
: (tail == 2) ? A_MOVW : A_MOVB;
|
|
||||||
ins2(c, op, areg(regs[full]),
|
|
||||||
amem(D_BP, off + full * 8));
|
|
||||||
}
|
|
||||||
goto letlink;
|
goto letlink;
|
||||||
}
|
}
|
||||||
/* array literal initialiser: `let xs: [N]T = [a, b, c];`.
|
/* array literal initialiser: `let xs: [N]T = [a, b, c];`.
|
||||||
|
|||||||
@@ -1721,6 +1721,88 @@ fn aggcopy(c: *cgen, sz: i32) void = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// cgaggregstore — ww twin of cstage cgen.c cg_agg_reg_store. The ONE
|
||||||
|
// register-cursor aggregate materialise: an in-cap (<=24B, GP-class)
|
||||||
|
// struct/array/tuple already held in the {AX,DX,CX} return cursor is
|
||||||
|
// stored into basereg+disp. full=sz/8 exact-8B MOVQ words land straight
|
||||||
|
// in; the sz%8 tail is one sized MOVB/MOVW/MOVL for {1,2,4} (BOTH
|
||||||
|
// branches). Extracted from the cstage site-E #10 template so every
|
||||||
|
// narrow-tail materialise funnels through one place — close-by-
|
||||||
|
// construction (task #14).
|
||||||
|
//
|
||||||
|
// dest_padded forks ONLY the {3,5,6,7} tail (no GP sub-register exists
|
||||||
|
// for those widths and w6a has no shift):
|
||||||
|
// dest_padded == "the dest is a ceil-8/round8 slot (a scratch, or a
|
||||||
|
// #75 let/local aggregate slot) so an 8B tail over-store stays
|
||||||
|
// in-bounds." Post-#9: packed struct fields + array elements => false;
|
||||||
|
// let/local/scratch slots => true. It CANNOT be derived — paddedness
|
||||||
|
// is routing knowledge the caller owns.
|
||||||
|
// true -> a single full MOVQ of the cursor tail eightbyte (= the
|
||||||
|
// #10 template; the over-store lands in the slot's pad).
|
||||||
|
// false -> MOVQ the cursor tail eightbyte into the helper's own
|
||||||
|
// ceil-8 @tagscr pad, then a sized aggcopy of the tail bytes
|
||||||
|
// into the dest so a packed field / array element is never
|
||||||
|
// overrun.
|
||||||
|
// PRECONDITION (caller-owned, stays per-site): the value is already in
|
||||||
|
// AX/DX/CX, the dest base is resolved into basereg+disp, and the
|
||||||
|
// float-class (#165) / over-cap-sret (#234) loud-stops have already
|
||||||
|
// fired. Clobbers SI/BX/AX only on the dest_padded==false detour (the
|
||||||
|
// value words are in memory by then).
|
||||||
|
fn cgaggregstore(c: *cgen, basereg: str, disp: i32, sz: i32, dest_padded: bool) void = {
|
||||||
|
let full: i32 = sz / 8;
|
||||||
|
let tail: i32 = sz - full * 8;
|
||||||
|
let i: i32 = 0;
|
||||||
|
for (i < full) {
|
||||||
|
let reg: str = "AX";
|
||||||
|
if (i == 1) { reg = "DX"; };
|
||||||
|
if (i == 2) { reg = "CX"; };
|
||||||
|
emitline("\tMOVQ\t");
|
||||||
|
emitline(reg);
|
||||||
|
emitline(", ");
|
||||||
|
emitdispreg((disp + i * 8): i64, basereg);
|
||||||
|
emitline("\n");
|
||||||
|
i += 1;
|
||||||
|
};
|
||||||
|
if (tail == 0) { return; };
|
||||||
|
let treg: str = "AX";
|
||||||
|
if (full == 1) { treg = "DX"; };
|
||||||
|
if (full == 2) { treg = "CX"; };
|
||||||
|
if (tail == 1 || tail == 2 || tail == 4) {
|
||||||
|
let top: str = "MOVB";
|
||||||
|
if (tail == 4) { top = "MOVL"; };
|
||||||
|
if (tail == 2) { top = "MOVW"; };
|
||||||
|
emitline("\t");
|
||||||
|
emitline(top);
|
||||||
|
emitline("\t");
|
||||||
|
emitline(treg);
|
||||||
|
emitline(", ");
|
||||||
|
emitdispreg((disp + full * 8): i64, basereg);
|
||||||
|
emitline("\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (dest_padded) {
|
||||||
|
emitline("\tMOVQ\t");
|
||||||
|
emitline(treg);
|
||||||
|
emitline(", ");
|
||||||
|
emitdispreg((disp + full * 8): i64, basereg);
|
||||||
|
emitline("\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let pad: i32 = tagscradd(c, 8);
|
||||||
|
emitline("\tMOVQ\t");
|
||||||
|
emitline(treg);
|
||||||
|
emitline(", ");
|
||||||
|
emitdispreg(pad: i64, "BP");
|
||||||
|
emitline("\n");
|
||||||
|
emitline("\tLEAQ\t");
|
||||||
|
emitdispreg(pad: i64, "BP");
|
||||||
|
emitline(", SI\n");
|
||||||
|
emitline("\tLEAQ\t");
|
||||||
|
emitdispreg((disp + full * 8): i64, basereg);
|
||||||
|
emitline(", BX\n");
|
||||||
|
aggcopy(c, tail);
|
||||||
|
};
|
||||||
|
|
||||||
// copysrcnatsize — natural byte width of a whole-struct copy's SOURCE
|
// copysrcnatsize — natural byte width of a whole-struct copy's SOURCE
|
||||||
// operand, read from the source node's stamped tinfo (tichase peels
|
// operand, read from the source node's stamped tinfo (tichase peels
|
||||||
// NAMED). #71: the four whole-struct field-copy sites must move this many
|
// NAMED). #71: the four whole-struct field-copy sites must move this many
|
||||||
@@ -8399,34 +8481,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
emitline("\tPUSHQ\tBX\n");
|
emitline("\tPUSHQ\tBX\n");
|
||||||
cgexpr(c, n.rhs);
|
cgexpr(c, n.rhs);
|
||||||
emitline("\tPOPQ\tBX\n");
|
emitline("\tPOPQ\tBX\n");
|
||||||
let full: i32 = ssz / 8;
|
cgaggregstore(c, "BX", 0, ssz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((i * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((full * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -9217,36 +9272,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
let scrc2: i32 = tagscradd(c, esz);
|
let scrc2: i32 = tagscradd(c, esz);
|
||||||
cgexpr(c, n.rhs); // call -> AX/DX/CX
|
cgexpr(c, n.rhs); // call -> AX/DX/CX
|
||||||
// AX/DX/CX -> scratch (mirror cstage cgen.c:3434).
|
// AX/DX/CX -> scratch (mirror cstage cgen.c:3434).
|
||||||
let full: i32 = esz / 8;
|
cgaggregstore(c, "BP", scrc2, esz, true);
|
||||||
let tail: i32 = esz % 8;
|
|
||||||
let wi: i32 = 0;
|
|
||||||
for (wi < full) {
|
|
||||||
let rn: str = "AX";
|
|
||||||
if (wi == 1) { rn = "DX"; }
|
|
||||||
else { if (wi == 2) { rn = "CX"; }; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(rn);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((scrc2 + wi * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
wi += 1;
|
|
||||||
};
|
|
||||||
if (tail > 0) {
|
|
||||||
let top: str = "MOVQ";
|
|
||||||
if (tail == 1) { top = "MOVB"; }
|
|
||||||
else { if (tail == 2) { top = "MOVW"; }
|
|
||||||
else { if (tail == 4) { top = "MOVL"; }; }; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; }
|
|
||||||
else { if (full == 2) { treg = "CX"; }; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((scrc2 + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
// dest &a[i] -> BX (#121 / #270-1b base resolve)
|
// dest &a[i] -> BX (#121 / #270-1b base resolve)
|
||||||
cgexpr(c, idx);
|
cgexpr(c, idx);
|
||||||
if (esz > 1) {
|
if (esz > 1) {
|
||||||
@@ -10601,34 +10627,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
emitline("\tMOVQ\t");
|
emitline("\tMOVQ\t");
|
||||||
emitoff(lc.off: i64);
|
emitoff(lc.off: i64);
|
||||||
emitline("(BP), BX\n");
|
emitline("(BP), BX\n");
|
||||||
let full: i32 = ssz / 8;
|
cgaggregstore(c, "BX", fi.foff, ssz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((fi.foff + i * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((fi.foff + full * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -10847,34 +10846,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
if (tlm == 0 || tlm == 1
|
if (tlm == 0 || tlm == 1
|
||||||
|| tlm == 2 || tlm == 4) {
|
|| tlm == 2 || tlm == 4) {
|
||||||
cgexpr(c, n.rhs);
|
cgexpr(c, n.rhs);
|
||||||
let full: i32 = ssz / 8;
|
cgaggregstore(c, "BP", lc.off + fi.foff, ssz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((lc.off + fi.foff + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((lc.off + fi.foff + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -11141,34 +11113,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
emitline("\tLEAQ\t");
|
emitline("\tLEAQ\t");
|
||||||
emitsymname(c, bn);
|
emitsymname(c, bn);
|
||||||
emitline("(SB), BX\n");
|
emitline("(SB), BX\n");
|
||||||
let full: i32 = ssz / 8;
|
cgaggregstore(c, "BX", fi.foff, ssz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((fi.foff + i * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((fi.foff + full * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -11848,52 +11793,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
emitline("(SB), BX\n");
|
emitline("(SB), BX\n");
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
let full: i32 = lsz / 8;
|
if (viacx) { cgaggregstore(c, "BX", totaloff, lsz, false); } else { cgaggregstore(c, "BP", rootoff + totaloff, lsz, false); };
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
if (viacx) {
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((totaloff + i * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
} else {
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((rootoff + totaloff + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
if (viacx) {
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitdispreg((totaloff + full * 8): i64, "BX");
|
|
||||||
emitline("\n");
|
|
||||||
} else {
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((rootoff + totaloff + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -12638,34 +12538,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
if (tlm == 0 || tlm == 1
|
if (tlm == 0 || tlm == 1
|
||||||
|| tlm == 2 || tlm == 4) {
|
|| tlm == 2 || tlm == 4) {
|
||||||
cgexpr(c, n.rhs);
|
cgexpr(c, n.rhs);
|
||||||
let full: i32 = lcsz / 8;
|
cgaggregstore(c, "BP", off, lcsz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -12702,34 +12575,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
if (tlm == 0 || tlm == 1
|
if (tlm == 0 || tlm == 1
|
||||||
|| tlm == 2 || tlm == 4) {
|
|| tlm == 2 || tlm == 4) {
|
||||||
cgexpr(c, n.rhs);
|
cgexpr(c, n.rhs);
|
||||||
let full: i32 = lcsz / 8;
|
cgaggregstore(c, "BP", off, lcsz, false);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2603,34 +2603,7 @@ fn cgletbody(c: *cgen, n: *syntax.node, off: i32) void = {
|
|||||||
if (tlm == 0 || tlm == 1
|
if (tlm == 0 || tlm == 1
|
||||||
|| tlm == 2 || tlm == 4) {
|
|| tlm == 2 || tlm == 4) {
|
||||||
cgexpr(c, rhs);
|
cgexpr(c, rhs);
|
||||||
let full: i32 = lsz / 8;
|
cgaggregstore(c, "BP", off, lsz, true);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
c.lastwasreturn = 0;
|
c.lastwasreturn = 0;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -2655,34 +2628,7 @@ fn cgletbody(c: *cgen, n: *syntax.node, off: i32) void = {
|
|||||||
if (tlm == 0 || tlm == 1
|
if (tlm == 0 || tlm == 1
|
||||||
|| tlm == 2 || tlm == 4) {
|
|| tlm == 2 || tlm == 4) {
|
||||||
cgexpr(c, rhs);
|
cgexpr(c, rhs);
|
||||||
let full: i32 = lsz / 8;
|
cgaggregstore(c, "BP", off, lsz, true);
|
||||||
let i: i32 = 0;
|
|
||||||
for (i < full) {
|
|
||||||
let reg: str = "AX";
|
|
||||||
if (i == 1) { reg = "DX"; };
|
|
||||||
if (i == 2) { reg = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(reg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + i * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
i += 1;
|
|
||||||
};
|
|
||||||
if (tlm > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (tlm == 4) { top = "MOVL"; };
|
|
||||||
if (tlm == 2) { top = "MOVW"; };
|
|
||||||
let treg: str = "AX";
|
|
||||||
if (full == 1) { treg = "DX"; };
|
|
||||||
if (full == 2) { treg = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(treg);
|
|
||||||
emitline(", ");
|
|
||||||
emitoff((off + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
};
|
|
||||||
c.lastwasreturn = 0;
|
c.lastwasreturn = 0;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5387,44 +5387,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *syntax.node,
|
|||||||
if (mode == 3) {
|
if (mode == 3) {
|
||||||
emitline("\tMOVQ\t(SP), BX\n");
|
emitline("\tMOVQ\t(SP), BX\n");
|
||||||
};
|
};
|
||||||
let full: i32 = cfsz / 8;
|
cgaggregstore(c, basereg, disp + fi.foff, cfsz, false);
|
||||||
let ci: i32 = 0;
|
|
||||||
for (ci < full) {
|
|
||||||
let r: str = "AX";
|
|
||||||
if (ci == 1) { r = "DX"; };
|
|
||||||
if (ci == 2) { r = "CX"; };
|
|
||||||
emitline("\tMOVQ\t");
|
|
||||||
emitline(r);
|
|
||||||
emitline(", ");
|
|
||||||
if (mode == 0) {
|
|
||||||
emitoff((disp + fi.foff + ci * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
} else {
|
|
||||||
emitdispreg((disp + fi.foff + ci * 8): i64, basereg);
|
|
||||||
emitline("\n");
|
|
||||||
};
|
|
||||||
ci += 1;
|
|
||||||
};
|
|
||||||
if (crem > 0) {
|
|
||||||
let top: str = "MOVB";
|
|
||||||
if (crem == 4) { top = "MOVL"; };
|
|
||||||
if (crem == 2) { top = "MOVW"; };
|
|
||||||
let tr: str = "AX";
|
|
||||||
if (full == 1) { tr = "DX"; };
|
|
||||||
if (full == 2) { tr = "CX"; };
|
|
||||||
emitline("\t");
|
|
||||||
emitline(top);
|
|
||||||
emitline("\t");
|
|
||||||
emitline(tr);
|
|
||||||
emitline(", ");
|
|
||||||
if (mode == 0) {
|
|
||||||
emitoff((disp + fi.foff + full * 8): i64);
|
|
||||||
emitline("(BP)\n");
|
|
||||||
} else {
|
|
||||||
emitdispreg((disp + fi.foff + full * 8): i64, basereg);
|
|
||||||
emitline("\n");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
callwhole = true;
|
callwhole = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user