commit e2531862ff12c3ffabbcf078d1acdbd9525963ce from: Benjamin Stürz date: Wed Oct 02 22:16:44 2024 UTC irc: add EX_{EQ,NE,{U,S}{LT,GT,LE,GE}} commit - db96e10e218769bf2d6506c723a0704a0e737582 commit + e2531862ff12c3ffabbcf078d1acdbd9525963ce blob - 9885dfb8c28afe1ac754acca835805a3cbfba9d7 blob + b7d08527f09ed9cc03c721c9e4670513f1493dba --- cc/irc/irc.c +++ cc/irc/irc.c @@ -289,6 +289,16 @@ enum expr_type { EX_MUL, // .bin EX_UDIV, // .bin EX_SDIV, // .bin + EX_EQ, // .bin + EX_NE, // .bin + EX_ULT, // .bin + EX_UGT, // .bin + EX_ULE, // .bin + EX_UGE, // .bin + EX_SLT, // .bin + EX_SGT, // .bin + EX_SLE, // .bin + EX_SGE, // .bin EX_PTRADD, // .bin EX_READ, // .read EX_CALL, // .call @@ -642,6 +652,26 @@ enum expr_type t; assert_dt_is_int (dt); assert_dt_is_int (&fn->regs[e->reg].dt); + return 0; +} + +expr_cmp (fn, dt, e, t) +struct func *fn; +struct dtype *dt; +struct expr *e; +enum expr_type t; +{ + e->type = t; + expect (TK_REG); + e->bin.l = lval.i; + expect (','); + regimm (&e->bin.r, &default_dt); + expect (';'); + + 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"); return 0; } @@ -693,6 +723,26 @@ struct expr *e; expr_bin (fn, dt, e, EX_UDIV, 0); } 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); + } else if (strcmp (lval.s, "ne") == 0) { + expr_cmp (fn, dt, e, EX_NE); + } else if (strcmp (lval.s, "ult") == 0) { + expr_cmp (fn, dt, e, EX_ULT); + } else if (strcmp (lval.s, "ugt") == 0) { + expr_cmp (fn, dt, e, EX_UGT); + } else if (strcmp (lval.s, "ule") == 0) { + expr_cmp (fn, dt, e, EX_ULE); + } else if (strcmp (lval.s, "uge") == 0) { + expr_cmp (fn, dt, e, EX_UGE); + } else if (strcmp (lval.s, "slt") == 0) { + expr_cmp (fn, dt, e, EX_SLT); + } else if (strcmp (lval.s, "sgt") == 0) { + expr_cmp (fn, dt, e, EX_SGT); + } else if (strcmp (lval.s, "sle") == 0) { + expr_cmp (fn, dt, e, EX_SLE); + } else if (strcmp (lval.s, "sge") == 0) { + expr_cmp (fn, dt, e, EX_SGE); } else if (strcmp (lval.s, "lsl") == 0) { expr_shift (fn, dt, e, EX_LSL); } else if (strcmp (lval.s, "lsr") == 0) { @@ -1169,8 +1219,48 @@ struct expr *e; break; case EX_SDIV: printf ("sdiv $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_EQ: + printf ("eq $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_NE: + printf ("ne $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_ULT: + printf ("ult $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_UGT: + printf ("ugt $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_ULE: + printf ("ule $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_UGE: + printf ("uge $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_SLT: + printf ("slt $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_SGT: + printf ("sgt $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; + case EX_SLE: + printf ("sle $%d, ", e->bin.l); print_ri (&e->bin.r); break; + case EX_SGE: + printf ("sge $%d, ", e->bin.l); + print_ri (&e->bin.r); + break; case EX_PTRADD: printf ("ptradd $%d, ", e->bin.l); print_ri (&e->bin.r); @@ -1257,6 +1347,8 @@ struct ir *ir; } // ASM MISC + +int nlbl; enum x86_reg8 { AL, @@ -1766,6 +1858,52 @@ struct expr *e; error ("cannot use immediate values for floating-point operations"); load (NULL, acc); load ("fdiv", &fn->regs[ri->reg]); + break; + } + return 0; +} + +gen_cmp (fn, dt, e, cmp, cc) +struct func *fn; +struct dtype *dt; +struct expr *e; +char *cmp, *cc; +{ + int l1, l2; + + switch (dt->type) { + case DT_NONE: + case DT_LABEL: + case DT_DPTR: + case DT_FPTR: + case DT_SPTR: + abort (); + break; + + case DT_BYTE: + case DT_WORD: + load (NULL, &fn->regs[e->bin.l]); + loadri (fn, cmp, &e->bin.r); + goto common; + + case DT_FLOAT: + load (NULL, &fn->regs[e->bin.l]); + loadri (fn, cmp, &e->bin.r); + goto common; + + case DT_DWORD: + case DT_QWORD: + error ("comparisons not implemented for dword, qword, fptr"); + + common: + l1 = nlbl++; + l2 = nlbl++; + printf ("\tj%s .Li%d\n", cc, l1); + printf ("\txor ax, ax\n"); + printf ("\tjmp .Li%d\n\n", l2); + printf (".Li%d:\n", l1); + printf ("\tmov ax, 1\n\n"); + printf (".Li%d:\n", l2); break; } return 0; @@ -1918,6 +2056,36 @@ struct expr *e; case EX_SDIV: gen_div (fn, dt, e, 1); break; + case EX_EQ: + gen_cmp (fn, dt, e, "test", "e"); + break; + case EX_NE: + gen_cmp (fn, dt, e, "test", "ne"); + break; + case EX_ULT: + gen_cmp (fn, dt, e, "cmp", "b"); + break; + case EX_UGT: + gen_cmp (fn, dt, e, "cmp", "a"); + break; + case EX_ULE: + gen_cmp (fn, dt, e, "cmp", "be"); + break; + case EX_UGE: + gen_cmp (fn, dt, e, "cmp", "a"); + break; + case EX_SLT: + gen_cmp (fn, dt, e, "cmp", "l"); + break; + case EX_SGT: + gen_cmp (fn, dt, e, "cmp", "g"); + break; + case EX_SLE: + gen_cmp (fn, dt, e, "cmp", "le"); + break; + case EX_SGE: + gen_cmp (fn, dt, e, "cmp", "l"); + break; case EX_PTRADD: load (NULL, &fn->regs[e->bin.l]); @@ -2297,6 +2465,8 @@ struct func *fn; { struct ir *ir; + nlbl = 1; + printf ("section %s\n", fn->section); if (fn->is_pub) printf ("global %s\n", fn->name); blob - ffe0840484c6e653a8fd2862aa41252da61d608a blob + e8f82398186bfa8a8918662626893d6053c87ed9 --- cc/irc/test.ir +++ cc/irc/test.ir @@ -202,3 +202,10 @@ fn floats (): float { let $6: float = $5; ret $0; } + +fn cmp (): word { + let $0: word = 0; + let $1: word = 1; + let $2: word = eq $0, $1; + ret $2; +}