From 81ef162703ec2075136ceb5aa7601bf3ef8e8ca2 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 29 Dec 2020 22:40:59 -0800 Subject: [PATCH] Create integrated assembler for chibicc All we need now to complete the triforce is an integrated linker. That way Cosmpolitan will let C be a "build anywhere run anywhere" language. --- third_party/chibicc/as.c | 302 +++++++++++++----- third_party/chibicc/as.main.c | 30 ++ third_party/chibicc/chibicc.c | 13 +- third_party/chibicc/chibicc.h | 6 + .../chibicc/{main.c => chibicc.main.c} | 0 third_party/chibicc/chibicc.mk | 4 +- 6 files changed, 267 insertions(+), 88 deletions(-) create mode 100644 third_party/chibicc/as.main.c rename third_party/chibicc/{main.c => chibicc.main.c} (100%) diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index 6a68b0b93..981c92620 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -445,6 +445,7 @@ static unsigned Hash(const void *p, unsigned long n) { static bool IsPunctMergeable(int c) { switch (c) { + case ',': case ';': case '$': return false; @@ -710,7 +711,7 @@ static void Tokenize(struct As *a, int path) { } bol = false; if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || - c == '\v' || c == ',') { + c == '\v') { ++p; continue; } @@ -960,6 +961,12 @@ static bool IsForward(struct As *a, int i) { static bool IsBackward(struct As *a, int i) { return a->things.p[i].t == TT_BACKWARD; } +static bool IsComma(struct As *a) { + return IsPunct(a, a->i, ','); +} +static bool IsSemicolon(struct As *a) { + return IsPunct(a, a->i, ';'); +} static bool IsRegister(struct As *a, int i) { return IsSlice(a, i) && (a->slices.p[a->things.p[i].i].n && @@ -975,6 +982,10 @@ static void ConsumePunct(struct As *a, int c) { } } +static void ConsumeComma(struct As *a) { + ConsumePunct(a, ','); +} + static int NewPrimary(struct As *a, enum ExprKind k, long x) { AppendExpr(a); a->exprs.p[a->exprs.n - 1].kind = k; @@ -1374,7 +1385,7 @@ static void EmitVarword(struct As *a, unsigned long x) { static void OnSleb128(struct As *a, struct Slice s) { int c; long x; - while (!IsPunct(a, a->i, ';')) { + for (;;) { x = GetInt(a); for (;;) { c = x & 0x7f; @@ -1385,6 +1396,8 @@ static void OnSleb128(struct As *a, struct Slice s) { c |= 0x80; } EmitByte(a, c); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } } @@ -1392,7 +1405,7 @@ static void OnSleb128(struct As *a, struct Slice s) { static void OnUleb128(struct As *a, struct Slice s) { int c; unsigned long x; - while (!IsPunct(a, a->i, ';')) { + for (;;) { x = GetInt(a); do { c = x & 0x7f; @@ -1400,25 +1413,36 @@ static void OnUleb128(struct As *a, struct Slice s) { if (x) c |= 0x80; EmitByte(a, c); } while (x); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } static void OnZero(struct As *a, struct Slice s) { long n; char *p; - while (IsInt(a, a->i)) { + for (;;) { n = GetInt(a); p = calloc(n, 1); EmitData(a, p, n); free(p); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } static void OnSpace(struct As *a, struct Slice s) { long n; char *p; + int fill; p = malloc((n = GetInt(a))); - memset(p, IsInt(a, a->i) ? GetInt(a) : 0, n); + if (IsComma(a)) { + ConsumeComma(a); + fill = GetInt(a); + } else { + fill = 0; + } + memset(p, fill, n); EmitData(a, p, n); free(p); } @@ -1455,28 +1479,29 @@ static void EmitExpr(struct As *a, int expr, int kind, } } +static void OpInt(struct As *a, int kind, + void emitter(struct As *, unsigned long)) { + for (;;) { + EmitExpr(a, Parse(a), kind, emitter); + if (IsSemicolon(a)) break; + ConsumeComma(a); + } +} + static void OnByte(struct As *a, struct Slice s) { - do { - EmitExpr(a, Parse(a), R_X86_64_8, EmitByte); - } while (!IsPunct(a, a->i, ';')); + OpInt(a, R_X86_64_8, EmitByte); } static void OnWord(struct As *a, struct Slice s) { - do { - EmitExpr(a, Parse(a), R_X86_64_16, EmitWord); - } while (!IsPunct(a, a->i, ';')); + OpInt(a, R_X86_64_16, EmitWord); } static void OnLong(struct As *a, struct Slice s) { - do { - EmitExpr(a, Parse(a), R_X86_64_32, EmitLong); - } while (!IsPunct(a, a->i, ';')); + OpInt(a, R_X86_64_32, EmitLong); } static void OnQuad(struct As *a, struct Slice s) { - do { - EmitExpr(a, Parse(a), R_X86_64_64, EmitQuad); - } while (!IsPunct(a, a->i, ';')); + OpInt(a, R_X86_64_64, EmitQuad); } static void OnFloat(struct As *a, struct Slice s) { @@ -1485,13 +1510,13 @@ static void OnFloat(struct As *a, struct Slice s) { for (;;) { if (IsFloat(a, a->i)) { f = GetFloat(a); - } else if (IsInt(a, a->i)) { - f = GetInt(a); } else { - break; + f = GetInt(a); } memcpy(b, &f, 4); EmitData(a, b, 4); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1501,13 +1526,13 @@ static void OnDouble(struct As *a, struct Slice s) { for (;;) { if (IsFloat(a, a->i)) { f = GetFloat(a); - } else if (IsInt(a, a->i)) { - f = GetInt(a); } else { - break; + f = GetInt(a); } memcpy(b, &f, 8); EmitData(a, b, 8); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1517,14 +1542,14 @@ static void OnLongDouble(struct As *a, int n) { for (;;) { if (IsFloat(a, a->i)) { f = GetFloat(a); - } else if (IsInt(a, a->i)) { - f = GetInt(a); } else { - break; + f = GetInt(a); } memset(b, 0, 16); memcpy(b, &f, sizeof(f)); EmitData(a, b, n); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1538,18 +1563,22 @@ static void OnLdbl(struct As *a, struct Slice s) { static void OnAscii(struct As *a, struct Slice s) { struct Slice arg; - while (IsSlice(a, a->i)) { + for (;;) { arg = GetSlice(a); EmitData(a, arg.p, arg.n); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } static void OnAsciz(struct As *a, struct Slice s) { struct Slice arg; - while (IsSlice(a, a->i)) { + for (;;) { arg = GetSlice(a); EmitData(a, arg.p, arg.n); EmitByte(a, 0); + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1597,9 +1626,11 @@ static void OnAlign(struct As *a, struct Slice s) { if (__builtin_popcountl(align) != 1) Fail(a, "alignment not power of 2"); fill = (a->sections.p[a->section].flags & SHF_EXECINSTR) ? 0x90 : 0; maxskip = 268435456; - if (IsInt(a, a->i)) { + if (IsComma(a)) { + ++a->i; fill = GetInt(a); - if (IsInt(a, a->i)) { + if (IsComma(a)) { + ++a->i; maxskip = GetInt(a); } } @@ -1700,9 +1731,11 @@ static void OnSection(struct As *a, struct Slice s) { flags = SHF_ALLOC | SHF_EXECINSTR | SHF_WRITE; type = SHT_PROGBITS; } - if (IsSlice(a, a->i)) { + if (IsComma(a)) { + ++a->i; flags = SectionFlags(a, GetSlice(a)); - if (IsSlice(a, a->i)) { + if (IsComma(a)) { + ++a->i; type = SectionType(a, GetSlice(a)); } } @@ -1761,20 +1794,24 @@ static void OnIncbin(struct As *a, struct Slice s) { static void OnType(struct As *a, struct Slice s) { int i; i = GetSymbol(a, a->things.p[a->i++].i); + ConsumeComma(a); a->symbols.p[i].type = SymbolType(a, GetSlice(a)); } static void OnSize(struct As *a, struct Slice s) { int i; i = GetSymbol(a, a->things.p[a->i++].i); + ConsumeComma(a); a->symbols.p[i].size = GetInt(a); } static void OpVisibility(struct As *a, int visibility) { int i; - while (IsSlice(a, a->i)) { + for (;;) { i = GetSymbol(a, a->things.p[a->i++].i); a->symbols.p[i].stv = visibility; + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1792,9 +1829,11 @@ static void OnProtected(struct As *a, struct Slice s) { static void OpBind(struct As *a, int bind) { int i; - while (IsSlice(a, a->i)) { + for (;;) { i = GetSymbol(a, a->things.p[a->i++].i); a->symbols.p[i].stb = bind; + if (IsSemicolon(a)) break; + ConsumeComma(a); } } @@ -1975,6 +2014,7 @@ static int ParseModrm(struct As *a, int *disp) { ││││││ │ ┌index or size ││││││ │ │ ┌base or reg │││││├──────┐├┐├─┐├─┐ + 000100000000000100101 0b00000000000000000000000000000000*/ struct Slice str; int reg, scale, modrm = 0; @@ -1989,7 +2029,8 @@ static int ParseModrm(struct As *a, int *disp) { } if (IsPunct(a, a->i, '(')) { ++a->i; - if ((str = GetSlice(a)).n) { + if (!IsComma(a)) { + str = GetSlice(a); modrm |= HASBASE; if (!strncasecmp(str.p, "%rip", str.n)) { modrm |= ISRIP; @@ -2001,18 +2042,18 @@ static int ParseModrm(struct As *a, int *disp) { if (((reg & 070) >> 3) == 2) modrm |= HASASZ; // asz } } - if (!IsPunct(a, a->i, ')')) { + if (IsComma(a)) { + ++a->i; modrm |= HASINDEX; reg = FindRegIndex(GetSlice(a)); if (reg == -1) InvalidRegister(a); modrm |= (reg & 007) << 3; // index modrm |= reg & 0xff00; // rex if (((reg & 070) >> 3) == 2) modrm |= HASASZ; // asz - if (!IsPunct(a, a->i, ')')) { + if (IsComma(a)) { + ++a->i; modrm |= (bsr(GetInt(a)) & 3) << 6; } - } else { - modrm |= 4 << 3; // puttin' on the riz } ConsumePunct(a, ')'); } @@ -2041,6 +2082,8 @@ static void EmitImm(struct As *a, int reg, int imm) { } static void EmitModrm(struct As *a, int reg, int modrm, int disp) { + int relo, mod, rm; + void (*emitter)(struct As *, unsigned long); reg &= 7; reg <<= 3; if (modrm & ISREG) { @@ -2048,19 +2091,54 @@ static void EmitModrm(struct As *a, int reg, int modrm, int disp) { } else { if (modrm & ISRIP) { EmitByte(a, 005 | reg); + emitter = EmitLong; + relo = a->pcrelative ?: R_X86_64_PC32; } else if (modrm & (HASBASE | HASINDEX)) { - EmitByte(a, 0204 | reg); // suboptimal - EmitByte(a, modrm); + if (disp == -1) { + emitter = NULL; + relo = 0; + mod = 0; + } else if (a->exprs.p[disp].kind == EX_INT) { + if (!a->exprs.p[disp].x) { + emitter = NULL; + relo = 0; + mod = 0; + } else if (-128 <= a->exprs.p[disp].x && a->exprs.p[disp].x <= 127) { + emitter = EmitByte; + relo = R_X86_64_32S; + mod = 0100; + } else { + emitter = EmitLong; + relo = R_X86_64_32S; + mod = 0200; + } + } else { + emitter = EmitLong; + relo = R_X86_64_32S; + mod = 0200; + } + if (!(modrm & HASINDEX) && (modrm & 7) != 4) { + EmitByte(a, mod | reg | modrm); + } else if (!(modrm & HASINDEX) && (modrm & 7) == 4) { + EmitByte(a, mod | reg | 4); // (%rsp) must be (%rsp,%riz) + EmitByte(a, 040 | modrm); + } else if (!mod && (modrm & 7) == 5) { + EmitByte(a, 0100 | reg | 4); // (%rbp,𝑥) is special + EmitByte(a, modrm); + EmitByte(a, 0); + } else { + EmitByte(a, mod | reg | 4); + EmitByte(a, modrm); + } } else { - EmitByte(a, 004 | reg); + EmitByte(a, 004 | reg); // (%rbp,%riz) is disp32 EmitByte(a, 045); + emitter = EmitLong; + relo = R_X86_64_32S; + } + if (emitter) { + EmitExpr(a, disp, relo, emitter); } - EmitExpr( - a, disp, - a->pcrelative && ((modrm & ISRIP) || !(modrm & (HASBASE | HASINDEX))) - ? a->pcrelative - : R_X86_64_32S, - EmitLong); } } @@ -2078,7 +2156,6 @@ static void EmitOpModrm(struct As *a, long op, int reg, int modrm, int disp, EmitModrm(a, reg, modrm, disp); break; case 1: - EmitByte(a, OSZ); EmitVarword(a, op + skew); EmitModrm(a, reg, modrm, disp); break; @@ -2095,6 +2172,7 @@ static void EmitOpModrm(struct As *a, long op, int reg, int modrm, int disp, static void EmitRexOpModrm(struct As *a, long op, int reg, int modrm, int disp, int skew) { + if (((reg & 070) >> 3) == 1) EmitByte(a, OSZ); EmitRex(a, reg | modrm); EmitOpModrm(a, op, reg, modrm, disp, skew); } @@ -2102,6 +2180,7 @@ static void EmitRexOpModrm(struct As *a, long op, int reg, int modrm, int disp, static void OnLea(struct As *a, struct Slice s) { int modrm, reg, disp; modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, 0x8D, reg, modrm, disp, 0); } @@ -2111,6 +2190,7 @@ static void OnMov(struct As *a, struct Slice s) { if (IsPunct(a, a->i, '$')) { ++a->i; imm = Parse(a); + ConsumeComma(a); if (IsSlice(a, a->i)) { // imm -> reg reg = GetRegisterRm(a); switch ((reg & 070) >> 3) { @@ -2120,8 +2200,8 @@ static void OnMov(struct As *a, struct Slice s) { EmitExpr(a, imm, R_X86_64_8, EmitByte); break; case 1: - EmitRex(a, reg); EmitByte(a, OSZ); + EmitRex(a, reg); EmitByte(a, 0xB8 + (reg & 7)); EmitExpr(a, imm, R_X86_64_16, EmitWord); break; @@ -2172,10 +2252,12 @@ static void OnMov(struct As *a, struct Slice s) { } } else if (IsSlice(a, a->i)) { // reg -> reg/modrm reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, 0x88, reg, modrm, disp, 1); } else { // modrm -> reg modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, 0x8A, reg, modrm, disp, 1); } @@ -2184,6 +2266,7 @@ static void OnMov(struct As *a, struct Slice s) { static void EmitMovx(struct As *a, struct Slice opname, int op) { int reg, modrm, disp; modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRex(a, reg); if (((reg & 070) >> 3) == 1) EmitByte(a, OSZ); @@ -2202,6 +2285,7 @@ static void OnMovsbwx(struct As *a, struct Slice s) { static void OnMovslq(struct As *a, struct Slice s) { int reg, modrm, disp; modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitByte(a, REXW); EmitByte(a, 0x63); @@ -2213,16 +2297,19 @@ static noinline void OpAluImpl(struct As *a, struct Slice opname, int op) { if (IsPunct(a, a->i, '$')) { // imm -> reg/modrm ++a->i; imm = Parse(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); reg = GetOpSize(a, opname, modrm, 1) << 3 | op; EmitRexOpModrm(a, 0x80, reg, modrm, disp, 1); // suboptimal EmitImm(a, reg, imm); } else if (IsSlice(a, a->i)) { // reg -> reg/modrm reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, op << 3, reg, modrm, disp, 1); } else { // modrm -> reg modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, op << 3 | 2, reg, modrm, disp, 1); } @@ -2237,14 +2324,16 @@ static noinline void OpBsuImpl(struct As *a, struct Slice opname, int op) { if (IsPunct(a, a->i, '$')) { ++a->i; imm = Parse(a); + ConsumeComma(a); } else if (IsSlice(a, a->i) && (a->slices.p[a->things.p[a->i].i].n == 3 && !strncasecmp(a->slices.p[a->things.p[a->i].i].p, "%cl", 3)) && !IsPunct(a, a->i + 1, ';')) { ++a->i; + ConsumeComma(a); modrm = ParseModrm(a, &disp); reg = GetOpSize(a, opname, modrm, 1) << 3 | op; - EmitRexOpModrm(a, 0xC0, reg, modrm, disp, 1); + EmitRexOpModrm(a, 0xD2, reg, modrm, disp, 1); return; } else { AppendExpr(a); @@ -2256,7 +2345,7 @@ static noinline void OpBsuImpl(struct As *a, struct Slice opname, int op) { modrm = ParseModrm(a, &disp); reg = GetOpSize(a, opname, modrm, 1) << 3 | op; EmitRexOpModrm(a, 0xC0, reg, modrm, disp, 1); // suboptimal - EmitByte(a, imm); + EmitExpr(a, imm, R_X86_64_8, EmitByte); } static noinline void OpBsu(struct As *a, struct Slice opname, int op) { @@ -2280,10 +2369,12 @@ static void OnTest(struct As *a, struct Slice s) { if (IsPunct(a, a->i, '$')) { ++a->i; imm = Parse(a); + ConsumeComma(a); reg = OpF6(a, s, 0); // suboptimal EmitImm(a, reg, imm); } else { reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, 0x84, reg, modrm, disp, 1); } @@ -2294,18 +2385,21 @@ static void OnImul(struct As *a, struct Slice s) { if (IsPunct(a, a->i, '$')) { ++a->i; imm = Parse(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, 0x69, reg, modrm, disp, 0); EmitImm(a, reg, imm); } else { modrm = ParseModrm(a, &disp); - if (IsPunct(a, a->i, ';')) { - reg = GetOpSize(a, s, modrm, 1) << 3 | 5; - EmitRexOpModrm(a, 0xF6, reg, modrm, disp, 1); - } else { + if (IsComma(a)) { + ++a->i; reg = GetRegisterReg(a); EmitRexOpModrm(a, 0x0FAF, reg, modrm, disp, 0); + } else { + reg = GetOpSize(a, s, modrm, 1) << 3 | 5; + EmitRexOpModrm(a, 0xF6, reg, modrm, disp, 1); } } } @@ -2313,6 +2407,7 @@ static void OnImul(struct As *a, struct Slice s) { static void OpBit(struct As *a, int op) { int reg, modrm, disp; modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, op, reg, modrm, disp, 0); } @@ -2320,6 +2415,7 @@ static void OpBit(struct As *a, int op) { static void OnXchg(struct As *a, struct Slice s) { int reg, modrm, disp; reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, 0x86, reg, modrm, disp, 1); } @@ -2335,19 +2431,22 @@ static void OpShrld(struct As *a, struct Slice s, int op) { if (IsSlice(a, a->i) && (a->slices.p[a->things.p[a->i].i].n == 3 && !strncasecmp(a->slices.p[a->things.p[a->i].i].p, "%cl", 3))) { - skew = 1; ++a->i; + ConsumeComma(a); + skew = 1; reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, 0x0F00 | op | skew, reg, modrm, disp, 0); } else { skew = 0; ConsumePunct(a, '$'); imm = GetInt(a); + ConsumeComma(a); reg = GetRegisterReg(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, 0x0F00 | op | skew, reg, modrm, disp, 0); - EmitByte(a, imm); + EmitExpr(a, imm, R_X86_64_8, EmitByte); } } @@ -2363,10 +2462,12 @@ static void OpSseMov(struct As *a, int opWsdVsd, int opVsdWsd) { int reg, modrm, disp; if (IsRegister(a, a->i)) { reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); EmitRexOpModrm(a, opWsdVsd, reg, modrm, disp, 0); } else { modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, opVsdWsd, reg, modrm, disp, 0); } @@ -2404,17 +2505,46 @@ static void OnMovapd(struct As *a, struct Slice s) { OpSseMov(a, 0x0F29, 0x0F28); } -static void OnMovdq(struct As *a, struct Slice s) { - int reg, modrm, boop, disp; +static void OpMovdq(struct As *a, bool is64) { + int reg, modrm, boop, disp, ugh; EmitByte(a, 0x66); // todo mmx if (IsRegister(a, a->i)) { reg = GetRegisterReg(a); + ConsumeComma(a); modrm = ParseModrm(a, &disp); - boop = ((reg & 070) >> 3) == 4 ? 0x10 : 0; + if (!(modrm & ISREG)) { + if (((reg & 070) >> 3) == 4) { + if (is64) reg |= REXW << 8; + boop = 0x10; + } else { + boop = 0; + } + } else { + if (((reg & 070) >> 3) == 4) { + boop = 0x10; + } else { + boop = 0; + ugh = modrm & 7; + modrm &= ~7; + modrm |= reg & 7; + reg &= ~7; + reg |= ugh; + } + } } else { modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); - boop = ((reg & 070) >> 3) == 4 ? 0x10 : 0; + if (!(modrm & ISREG)) { + if (((reg & 070) >> 3) == 4) { + if (is64) reg |= REXW << 8; + boop = 0; + } else { + boop = 0x10; + } + } else { + boop = ((modrm & 070) >> 3) == 4 ? 0 : 0x10; + } } EmitRexOpModrm(a, 0x0F6E + boop, reg, modrm, disp, 0); } @@ -2442,6 +2572,7 @@ static noinline void OpSseImpl(struct As *a, int op) { op &= 0xffff; } modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, op, reg, modrm, disp, 0); } @@ -2454,6 +2585,7 @@ static noinline void OpSseIbImpl(struct As *a, int op) { int imm; ConsumePunct(a, '$'); imm = Parse(a); + ConsumeComma(a); OpSse(a, op); EmitExpr(a, imm, R_X86_64_8, EmitByte); } @@ -2474,9 +2606,13 @@ static bool HasXmmOnLine(struct As *a) { return false; } +static void OnMovd(struct As *a, struct Slice s) { + OpMovdq(a, false); +} + static void OnMovq(struct As *a, struct Slice s) { if (HasXmmOnLine(a)) { - OnMovdq(a, s); + OpMovdq(a, true); } else { OnMov(a, s); } @@ -2502,7 +2638,7 @@ static void OnPop(struct As *a, struct Slice s) { static void OnNop(struct As *a, struct Slice opname) { int modrm, disp; - if (IsPunct(a, a->i, ';')) { + if (IsSemicolon(a)) { EmitByte(a, 0x90); } else { modrm = ParseModrm(a, &disp); @@ -2523,6 +2659,7 @@ static void OnRet(struct As *a, struct Slice s) { static noinline void OpCmovccImpl(struct As *a, int cc) { int reg, modrm, disp; modrm = ParseModrm(a, &disp); + ConsumeComma(a); reg = GetRegisterReg(a); EmitRexOpModrm(a, 0x0F40 | cc, reg, modrm, disp, 0); } @@ -2604,7 +2741,7 @@ static noinline void OpFpu1(struct As *a, int op, int reg) { static void OnFxch(struct As *a, struct Slice s) { int rm; - rm = !IsPunct(a, a->i, ';') ? GetRegisterRm(a) : 1; + rm = !IsSemicolon(a) ? GetRegisterRm(a) : 1; EmitByte(a, 0xD9); EmitByte(a, 0310 | rm & 7); } @@ -2618,10 +2755,18 @@ static void OnBswap(struct As *a, struct Slice s) { } static noinline void OpFcomImpl(struct As *a, int op) { - int reg, rm; - rm = !IsPunct(a, a->i, ';') ? GetRegisterRm(a) : 1; - reg = !IsPunct(a, a->i, ';') ? GetRegisterReg(a) : 0; - if (reg & 7) Fail(a, "bad register"); + int rm; + if (IsSemicolon(a)) { + rm = 1; + } else { + rm = GetRegisterRm(a); + if (IsComma(a)) { + ++a->i; + if (GetRegisterReg(a) & 7) { + Fail(a, "bad register"); + } + } + } EmitVarword(a, op | rm & 7); } @@ -2733,7 +2878,7 @@ static void OnFldlg2(struct As *a, struct Slice s) { EmitVarword(a, 0xd9ec); } static void OnFldln2(struct As *a, struct Slice s) { EmitVarword(a, 0xd9ed); } static void OnFldpi(struct As *a, struct Slice s) { EmitVarword(a, 0xd9eb); } static void OnFlds(struct As *a, struct Slice s) { OpFpu1(a, 0xD9, 0); } -static void OnFldt(struct As *a, struct Slice s) { OpFpu1(a, 0xDB, 0); } +static void OnFldt(struct As *a, struct Slice s) { OpFpu1(a, 0xDB, 5); } static void OnFldz(struct As *a, struct Slice s) { EmitVarword(a, 0xd9ee); } static void OnFmulp(struct As *a, struct Slice s) { EmitVarword(a, 0xdec9); } static void OnFnstcw(struct As *a, struct Slice s) { OpFpu1(a, 0xD9, 7); } @@ -3231,7 +3376,7 @@ static const struct Directive8 { {"movapd", OnMovapd}, // {"movaps", OnMovaps}, // {"movb", OnMov}, // - {"movd", OnMovdq}, // + {"movd", OnMovd}, // {"movdqa", OnMovdqa}, // {"movdqa", OnMovdqa}, // {"movdqu", OnMovdqu}, // @@ -3594,7 +3739,7 @@ static void OnDirective(struct As *a) { for (;;) { s = GetSlice(a); if (Prefix(a, s.p, s.n)) { - if (IsPunct(a, a->i, ';')) { + if (IsSemicolon(a)) { return; } } else { @@ -3611,7 +3756,7 @@ static void OnDirective(struct As *a) { static void Assemble(struct As *a) { while (a->i < a->things.n) { - if (IsPunct(a, a->i, ';')) { + if (IsSemicolon(a)) { ++a->i; continue; } @@ -3908,14 +4053,3 @@ void Assembler(int argc, char *argv[]) { /* malloc_stats(); */ FreeAssembler(a); } - -int main(int argc, char *argv[]) { - showcrashreports(); - if (argc == 1) { - system("o//third_party/chibicc/as.com -o /tmp/o /home/jart/trash/hog.s"); - system("objdump -xwd /tmp/o"); - exit(0); - } - Assembler(argc, argv); - return 0; -} diff --git a/third_party/chibicc/as.main.c b/third_party/chibicc/as.main.c new file mode 100644 index 000000000..f02cc4b63 --- /dev/null +++ b/third_party/chibicc/as.main.c @@ -0,0 +1,30 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "third_party/chibicc/chibicc.h" + +int main(int argc, char *argv[]) { + showcrashreports(); + if (argc == 1) { + system("o//third_party/chibicc/as.com -o /tmp/o /home/jart/trash/hog.s"); + system("objdump -xwd /tmp/o"); + exit(0); + } + Assembler(argc, argv); + return 0; +} diff --git a/third_party/chibicc/chibicc.c b/third_party/chibicc/chibicc.c index fa113f1dc..d430b091a 100644 --- a/third_party/chibicc/chibicc.c +++ b/third_party/chibicc/chibicc.c @@ -563,10 +563,15 @@ static void cc1(void) { fclose(out); } +static int CountArgv(char **argv) { + int n = 0; + while (*argv++) ++n; + return n; +} + static void assemble(char *input, char *output) { char *as = getenv("AS"); if (!as || !*as) as = "as"; - /* as = "o//third_party/chibicc/as.com"; */ StringArray arr = {}; strarray_push(&arr, as); strarray_push(&arr, "-W"); @@ -579,7 +584,11 @@ static void assemble(char *input, char *output) { strarray_push(&arr, "-o"); strarray_push(&arr, output); strarray_push(&arr, NULL); - handle_exit(run_subprocess(arr.data)); + if (1) { + Assembler(CountArgv(arr.data), arr.data); + } else { + handle_exit(run_subprocess(arr.data)); + } } static void run_linker(StringArray *inputs, char *output) { diff --git a/third_party/chibicc/chibicc.h b/third_party/chibicc/chibicc.h index cfeb24cdd..2d51e3c5d 100644 --- a/third_party/chibicc/chibicc.h +++ b/third_party/chibicc/chibicc.h @@ -627,6 +627,12 @@ void output_javadown_asm(const char *, const char *); void drop_dox(const StringArray *, const char *); +// +// as.c +// + +void Assembler(int, char **); + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_THIRD_PARTY_CHIBICC_CHIBICC_H_ */ diff --git a/third_party/chibicc/main.c b/third_party/chibicc/chibicc.main.c similarity index 100% rename from third_party/chibicc/main.c rename to third_party/chibicc/chibicc.main.c diff --git a/third_party/chibicc/chibicc.mk b/third_party/chibicc/chibicc.mk index 06607bb17..a5c923f39 100644 --- a/third_party/chibicc/chibicc.mk +++ b/third_party/chibicc/chibicc.mk @@ -95,7 +95,7 @@ o/$(MODE)/third_party/chibicc/chibicc.com.dbg: \ $(THIRD_PARTY_CHIBICC_A) \ $(APE) \ $(CRT) \ - o/$(MODE)/third_party/chibicc/main.o \ + o/$(MODE)/third_party/chibicc/chibicc.main.o \ $(THIRD_PARTY_CHIBICC_A).pkg @$(APELINK) o/$(MODE)/third_party/chibicc/chibicc2.com.dbg: \ @@ -103,7 +103,7 @@ o/$(MODE)/third_party/chibicc/chibicc2.com.dbg: \ $(THIRD_PARTY_CHIBICC2_A) \ $(APE) \ $(CRT) \ - o/$(MODE)/third_party/chibicc/main.chibicc.o \ + o/$(MODE)/third_party/chibicc/chibicc.main.chibicc.o \ $(THIRD_PARTY_CHIBICC2_A).pkg @$(APELINK)