commit 9f4477b1b689868d51c134baa8664c2fd05fff3f from: Benjamin Stürz date: Wed Oct 02 19:51:47 2024 UTC irc: add EX_F{ADD,SUB,MUL,DIV} commit - d25b45cd908aa3299de02f2507191f81b809ccec commit + 9f4477b1b689868d51c134baa8664c2fd05fff3f blob - 148a4780ca0535b5c9b54ed2cb2d00a891441a32 blob + ae88908c7cd27eaafd5d62f08cdd620c9297919e --- cc/irc/irc.c +++ cc/irc/irc.c @@ -298,6 +298,10 @@ enum expr_type { EX_MUL, // .bin EX_UDIV, // .bin EX_SDIV, // .bin + EX_FADD, // .fbin + EX_FSUB, // .fbin + EX_FMUL, // .fbin + EX_FDIV, // .fbin }; struct call { @@ -324,6 +328,9 @@ struct expr { int l; struct regimm r; } bin; + struct { + int l, r; + } fbin; struct call *call; struct phi *phi; struct { @@ -458,7 +465,7 @@ struct dtype *dt; return 0; } -assert_dt_is_number (dt) +assert_dt_is_int (dt) struct dtype *dt; { switch (dt->type) { @@ -466,33 +473,33 @@ struct dtype *dt; case DT_WORD: case DT_DWORD: case DT_QWORD: - case DT_FLOAT: return 0; + case DT_FLOAT: case DT_NONE: case DT_LABEL: case DT_DPTR: case DT_FPTR: case DT_SPTR: - return error ("this operation is only supported for numbers (byte, word, dword, qword, float)"); + return error ("this operation is only supported for integers (byte, word, dword, qword)"); } } -assert_dt_is_int (dt) +assert_dt_is_float (dt) struct dtype *dt; { switch (dt->type) { + case DT_FLOAT: + return 0; case DT_BYTE: case DT_WORD: case DT_DWORD: case DT_QWORD: - return 0; - case DT_FLOAT: case DT_NONE: case DT_LABEL: case DT_DPTR: case DT_FPTR: case DT_SPTR: - return error ("this operation is only supported for integers (byte, word, dword, qword)"); + return error ("this operation is only supported for floats (float)"); } } @@ -567,11 +574,10 @@ struct dtype *dt; return 0; } -expr_bin (fn, dt, e, t, allow_float) +expr_bin (fn, dt, e, t) struct func *fn; struct dtype *dt; struct expr *e; -enum expr_type t; { e->type = t; expect (TK_REG); @@ -583,11 +589,7 @@ enum expr_type t; assert_dt_eq (dt, &fn->regs[e->bin.l].dt); assert_dt_eq (dt, e->bin.r.dt); - if (allow_float) { - assert_dt_is_number (dt); - } else { - assert_dt_is_int (dt); - } + assert_dt_is_int (dt); return 0; } @@ -627,6 +629,26 @@ enum expr_type t; return 0; } +expr_fbin (fn, dt, e, t) +struct func *fn; +struct dtype *dt; +struct expr *e; +enum expr_type t; +{ + e->type = t; + expect (TK_REG); + e->fbin.l = lval.i; + expect (','); + expect (TK_REG); + e->fbin.r = lval.i; + expect (';'); + + assert_dt_is_float (dt); + assert_dt_eq (dt, &fn->regs[e->fbin.l].dt); + assert_dt_eq (dt, &fn->regs[e->fbin.r].dt); + return 0; +} + expr (fn, dt, e) struct func *fn; struct dtype *dt; @@ -670,21 +692,21 @@ struct expr *e; e->alloca.off = fn->stoff; expect (';'); } else if (strcmp (lval.s, "add") == 0) { - expr_bin (fn, dt, e, EX_ADD, 1); + expr_bin (fn, dt, e, EX_ADD); } else if (strcmp (lval.s, "sub") == 0) { - expr_bin (fn, dt, e, EX_SUB, 1); + expr_bin (fn, dt, e, EX_SUB); } else if (strcmp (lval.s, "and") == 0) { - expr_bin (fn, dt, e, EX_AND, 0); + expr_bin (fn, dt, e, EX_AND); } else if (strcmp (lval.s, "or") == 0) { - expr_bin (fn, dt, e, EX_OR, 0); + expr_bin (fn, dt, e, EX_OR); } else if (strcmp (lval.s, "xor") == 0) { - expr_bin (fn, dt, e, EX_XOR, 0); + expr_bin (fn, dt, e, EX_XOR); } else if (strcmp (lval.s, "mul") == 0) { - expr_bin (fn, dt, e, EX_MUL, 1); - } else if (strcmp (lval.s, "udiv") == 0) { - expr_bin (fn, dt, e, EX_UDIV, 0); + expr_bin (fn, dt, e, EX_MUL); + } else if (strcmp (lval.s, "udiv") == 0) { + expr_bin (fn, dt, e, EX_UDIV); } else if (strcmp (lval.s, "sdiv") == 0) { - expr_bin (fn, dt, e, EX_SDIV, 1); + expr_bin (fn, dt, e, EX_SDIV); } else if (strcmp (lval.s, "lsl") == 0) { expr_shift (fn, dt, e, EX_LSL); } else if (strcmp (lval.s, "lsr") == 0) { @@ -801,6 +823,14 @@ struct expr *e; assert_dt_is_ptr (&fn->regs[e->reg].dt); if (dt->type != fn->regs[e->reg].dt.type) error ("pcast cannot be used to cast between different types of pointers (eg. SPTR -> FPTR)"); + } else if (strcmp (lval.s, "fadd") == 0) { + expr_fbin (fn, dt, e, EX_FADD); + } else if (strcmp (lval.s, "fsub") == 0) { + expr_fbin (fn, dt, e, EX_FSUB); + } else if (strcmp (lval.s, "fmul") == 0) { + expr_fbin (fn, dt, e, EX_FMUL); + } else if (strcmp (lval.s, "fdiv") == 0) { + expr_fbin (fn, dt, e, EX_FDIV); } else { err: error ("expected expr"); @@ -1199,6 +1229,18 @@ struct expr *e; printf ("asr $%d, ", e->bin.l); print_ri (&e->bin.r); break; + case EX_FADD: + printf ("fadd $%d, $%d", e->fbin.l, e->fbin.r); + break; + case EX_FSUB: + printf ("fsub $%d, $%d", e->fbin.l, e->fbin.r); + break; + case EX_FMUL: + printf ("fmul $%d, $%d", e->fbin.l, e->fbin.r); + break; + case EX_FDIV: + printf ("fdiv $%d, $%d", e->fbin.l, e->fbin.r); + break; } return 0; } @@ -1715,6 +1757,32 @@ struct expr *e; break; case DT_FLOAT: error ("division not implemented for DT_FLOAT"); + break; + } + return 0; +} + +fbin (instr, fn, dt, e) +char *instr; +struct func *fn; +struct dtype *dt; +struct expr *e; +{ + switch (dt->type) { + case DT_FLOAT: + printf ("\tfld dword [ss:bp + %d]\n", fn->regs[e->fbin.l].off); + printf ("\t%s dword [ss:bp + %d]\n", instr, fn->regs[e->fbin.r].off); + break; + case DT_NONE: + case DT_LABEL: + case DT_DPTR: + case DT_FPTR: + case DT_SPTR: + case DT_BYTE: + case DT_WORD: + case DT_DWORD: + case DT_QWORD: + abort (); break; } return 0; @@ -2046,7 +2114,19 @@ struct expr *e; break; case EX_ASR: shift (fn, "sar", &fn->regs[e->bin.l], &e->bin.r); + break; + case EX_FADD: + fbin ("fadd", fn, dt, e); + break; + case EX_FSUB: + fbin ("fsub", fn, dt, e); break; + case EX_FMUL: + fbin ("fmul", fn, dt, e); + break; + case EX_FDIV: + fbin ("fdiv", fn, dt, e); + break; } return 0; } blob - fd81b7745aec197bf813bfd56d8670172c319f2d blob + 7f1e3c589980d756242b5fe28f7676d083d7cb94 --- cc/irc/test.ir +++ cc/irc/test.ir @@ -195,5 +195,9 @@ pub section ".text.custom" fn custom_section (): qword fn floats (): float { let $0: float = 1.2; let $1: float = 42; + let $2: float = fadd $0, $1; + let $3: float = fsub $0, $1; + let $4: float = fmul $0, $1; + let $5: float = fdiv $0, $1; ret $0; }