commit 425857d4ed72c6e8567c39b17680a100acaad7f8 from: Benjamin Stürz date: Mon Oct 07 19:34:16 2024 UTC irc: improve EX_EQ and EX_NE commit - 5cf236395aa88dc8f443b83e7a9b79e34a943b8e commit + 425857d4ed72c6e8567c39b17680a100acaad7f8 blob - 4611deb74a0c263f19dffef9d76504722aa3e8b2 blob + 831bb334e88ec4b53ca52413055e931eb7f39ecd --- cc/irc/Makefile +++ cc/irc/Makefile @@ -7,6 +7,6 @@ clean: run: all ./irc < test.ir > test.asm - cat test.asm nasm -fobj -o /dev/null test.asm + less test.asm blob - fbd52308aca953b521e52120d240c43707f30f48 blob + bea6a8aacde8acc2be2061524fbcaa04da88d369 --- cc/irc/irc.c +++ cc/irc/irc.c @@ -9,6 +9,8 @@ // enable debugging prints #define ENABLE_DEBUG 1 + +int ignore_nan = 0; // ERROR HANDLING @@ -669,7 +671,7 @@ enum expr_type t; return 0; } -expr_cmp (fn, dt, e, t) +expr_cmp (fn, dt, e, t, allow_fp) struct func *fn; struct dtype *dt; struct expr *e; @@ -682,7 +684,11 @@ enum expr_type t; regimm (&e->bin.r, &fn->regs[e->bin.l].dt); expect (';'); - assert_dt_is_int (&fn->regs[e->bin.l].dt); + if (allow_fp) { + assert_dt_is_num (&fn->regs[e->bin.l].dt); + } else { + assert_dt_is_int (&fn->regs[e->bin.l].dt); + } assert_dt_eq (&fn->regs[e->bin.l].dt, e->bin.r.dt); if (dt->type != DT_WORD) error ("result of comparison must be of type word"); @@ -760,25 +766,25 @@ struct expr *e; } else if (strcmp (lval.s, "sdiv") == 0) { expr_bin (fn, dt, e, EX_SDIV, 1); } else if (strcmp (lval.s, "eq") == 0) { - expr_cmp (fn, dt, e, EX_EQ); + expr_cmp (fn, dt, e, EX_EQ, 1); } else if (strcmp (lval.s, "ne") == 0) { - expr_cmp (fn, dt, e, EX_NE); + expr_cmp (fn, dt, e, EX_NE, 1); } else if (strcmp (lval.s, "ult") == 0) { - expr_cmp (fn, dt, e, EX_ULT); + expr_cmp (fn, dt, e, EX_ULT, 0); } else if (strcmp (lval.s, "ugt") == 0) { - expr_cmp (fn, dt, e, EX_UGT); + expr_cmp (fn, dt, e, EX_UGT, 0); } else if (strcmp (lval.s, "ule") == 0) { - expr_cmp (fn, dt, e, EX_ULE); + expr_cmp (fn, dt, e, EX_ULE, 0); } else if (strcmp (lval.s, "uge") == 0) { - expr_cmp (fn, dt, e, EX_UGE); + expr_cmp (fn, dt, e, EX_UGE, 0); } else if (strcmp (lval.s, "slt") == 0) { - expr_cmp (fn, dt, e, EX_SLT); + expr_cmp (fn, dt, e, EX_SLT, 0); } else if (strcmp (lval.s, "sgt") == 0) { - expr_cmp (fn, dt, e, EX_SGT); + expr_cmp (fn, dt, e, EX_SGT, 0); } else if (strcmp (lval.s, "sle") == 0) { - expr_cmp (fn, dt, e, EX_SLE); + expr_cmp (fn, dt, e, EX_SLE, 0); } else if (strcmp (lval.s, "sge") == 0) { - expr_cmp (fn, dt, e, EX_SGE); + expr_cmp (fn, dt, e, EX_SGE, 0); } else if (strcmp (lval.s, "feq") == 0) { expr_fcmp (fn, dt, e, EX_FEQ); } else if (strcmp (lval.s, "fne") == 0) { @@ -2020,7 +2026,85 @@ char *cmp, *cc; printf (".Li%d:\n", l1); printf ("\tmov ax, 1\n\n"); printf (".Li%d:\n", l2); + break; + } + return 0; +} + +gen_eq (fn, e, inv) +struct func *fn; +struct expr *e; +{ + int l1, l2; + + switch (e->bin.r.dt->type) { + case DT_NONE: + case DT_LABEL: + abort (); + break; + + case DT_BYTE: + case DT_WORD: + case DT_DPTR: + case DT_SPTR: + load (NULL, &fn->regs[e->bin.l]); + loadri (fn, "cmp", &e->bin.r); + puts ("\tlahf"); + goto common; + + case DT_FPTR: + case DT_DWORD: + loaddw (NULL, &fn->regs[e->bin.l]); + puts ("\t; TODO: adjust loaddw to allow different register pairs"); + puts ("\tmov bx, ax"); + puts ("\tmov cx, dx"); + loadri (fn, NULL, &e->bin.r); + + puts ("\tcmp bx, ax"); + puts ("\tlahf"); + puts ("\tmov bx, ax"); + puts ("\tcmp cx, dx"); + puts ("\tlahf"); + puts ("\tand ah, bh"); + goto common; + + case DT_QWORD: + error ("TODO: EX_EQ and EX_NE for DT_QWORD"); + + case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: + error ("TODO: gen_eq(): floats"); + + assert (!e->bin.r.is_imm); + loadf (NULL, &fn->regs[e->bin.l]); + loadf ("fcomp", &fn->regs[e->bin.r.reg]); + puts ("\tfstsw ax"); + if (ignore_nan) { + puts ("\tmov al, ah"); + puts ("\tshr al, 3"); + puts ("\tand al, 1"); + } else { + l1 = nlbl++; + l2 = nlbl++; + puts ("\tand ah, 0b1101"); + puts ("\tcmp ah, 0b1000"); + printf ("\tjne .Li%d\n", l1); + printf ("\tmov al, 1\n"); + printf ("\tjmp .Li%d\n\n", l2); + printf (".Li%d:\n", l1); + printf ("\txor al, al\n\n"); + printf (".Li%d:\n", l2); + } break; + + common: + puts ("\tshl ah, 1"); + puts ("\trol ax, 1"); + puts ("\tand ax, 1"); + if (inv) + puts ("\txor ax, 1"); + break; } return 0; } @@ -2245,10 +2329,10 @@ struct expr *e; gen_div (fn, dt, e, 1); break; case EX_EQ: - gen_cmp (fn, e, "test", "e"); + gen_eq (fn, e, 0); break; case EX_NE: - gen_cmp (fn, e, "test", "ne"); + gen_eq (fn, e, 1); break; case EX_ULT: gen_cmp (fn, e, "cmp", "b"); blob - 08dc0947bade90c0785e263d4809546f818db9ad blob + 0fe93a079c3f055271efe5a78fd8ca5c157882fb --- cc/irc/test.ir +++ cc/irc/test.ir @@ -210,7 +210,10 @@ fn cmp (): word { let $0: word = 0; let $1: word = 1; let $2: word = eq $0, $1; - ret $2; + let $3: dword = 0; + let $4: dword = 1; + let $5: word = eq $3, $4; + ret $5; } fn fcmp (): word { @@ -222,6 +225,7 @@ fn fcmp (): word { let $5: word = fgt $0, $1; let $6: word = fle $0, $1; let $7: word = fge $0, $1; + # let $8: word = eq $0, $1; nop; ret 0; }