Commit Diff


commit - f66b5d9d004971b460d24ac4574ffc769b1a81e8
commit + 1b0ac8039426ded10ad6f8a7b1beba4203476ebc
blob - e7791e2edc9e48feb579f2aad1c3a22c6770fd4f
blob + 7f0cf11f6f27af699a78aca32a3398efbe4cbae4
--- cc/irc/irc.c
+++ cc/irc/irc.c
@@ -301,6 +301,12 @@ enum expr_type {
 	EX_SGT,		// .bin
 	EX_SLE,		// .bin
 	EX_SGE,		// .bin
+	EX_FEQ,		// .bin
+	EX_FNE,		// .bin
+	EX_FLT,		// .bin
+	EX_FGT,		// .bin
+	EX_FLE,		// .bin
+	EX_FGE,		// .bin
 	EX_PTRADD,	// .bin
 	EX_READ,	// .read
 	EX_CALL,	// .call
@@ -512,6 +518,19 @@ struct dtype *dt;
 	case DT_FPTR:
 	case DT_SPTR:
 		return error ("this operation is only supported for integers (byte, word, dword, qword)");
+	}
+}
+
+assert_dt_is_float (dt)
+struct dtype *dt;
+{
+	switch (dt->type) {
+	case DT_FLOAT:
+	case DT_DOUBLE:
+	case DT_LDOUBLE:
+		return 0;
+	default:
+		return error ("this operation is only supported for floats (float, double, ldouble)");
 	}
 }
 
@@ -659,7 +678,7 @@ enum expr_type t;
 	expect (TK_REG);
 	e->bin.l = lval.i;
 	expect (',');
-	regimm (&e->bin.r, &default_dt);
+	regimm (&e->bin.r, &fn->regs[e->bin.l].dt);
 	expect (';');
 
 	assert_dt_is_int (&fn->regs[e->bin.l].dt);
@@ -669,6 +688,28 @@ enum expr_type t;
 	return 0;
 }
 
+expr_fcmp (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, &fn->regs[e->bin.l].dt);
+	expect (';');
+
+	assert_dt_is_float (&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");
+	if (e->bin.r.is_imm)
+		error ("immediate arguments not supported");
+	return 0;
+}
+
 expr (fn, dt, e)
 struct func *fn;
 struct dtype *dt;
@@ -737,6 +778,18 @@ struct expr *e;
 		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, "feq") == 0) {
+		expr_fcmp (fn, dt, e, EX_FEQ);
+	} else if (strcmp (lval.s, "fne") == 0) {
+		expr_fcmp (fn, dt, e, EX_FNE);
+	} else if (strcmp (lval.s, "flt") == 0) {
+		expr_fcmp (fn, dt, e, EX_FLT);
+	} else if (strcmp (lval.s, "fgt") == 0) {
+		expr_fcmp (fn, dt, e, EX_FGT);
+	} else if (strcmp (lval.s, "fle") == 0) {
+		expr_fcmp (fn, dt, e, EX_FLE);
+	} else if (strcmp (lval.s, "fge") == 0) {
+		expr_fcmp (fn, dt, e, EX_FGE);
 	} else if (strcmp (lval.s, "lsl") == 0) {
 		expr_shift (fn, dt, e, EX_LSL);
 	} else if (strcmp (lval.s, "lsr") == 0) {
@@ -1259,8 +1312,32 @@ struct expr *e;
 		break;
 	case EX_SGE:
 		printf ("sge $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
+	case EX_FEQ:
+		printf ("feq $%d, ", e->bin.l);
 		print_ri (&e->bin.r);
 		break;
+	case EX_FNE:
+		printf ("fne $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
+	case EX_FLT:
+		printf ("flt $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
+	case EX_FGT:
+		printf ("fgt $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
+	case EX_FLE:
+		printf ("fle $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
+	case EX_FGE:
+		printf ("fge $%d, ", e->bin.l);
+		print_ri (&e->bin.r);
+		break;
 	case EX_PTRADD:
 		printf ("ptradd $%d, ", e->bin.l);
 		print_ri (&e->bin.r);
@@ -1893,15 +1970,14 @@ struct expr *e;
 	return 0;
 }
 
-gen_cmp (fn, dt, e, cmp, cc)
+gen_cmp (fn, e, cmp, cc)
 struct func *fn;
-struct dtype *dt;
 struct expr *e;
 char *cmp, *cc;
 {
 	int l1, l2;
 
-	switch (dt->type) {
+	switch (e->bin.r.dt->type) {
 	case DT_NONE:
 	case DT_LABEL:
 	case DT_DPTR:
@@ -1918,10 +1994,8 @@ char *cmp, *cc;
 	
 	case DT_FLOAT:
 	case DT_DOUBLE:
-	case DT_LDOUBLE: // TODO: fix for floats
-		load (NULL, &fn->regs[e->bin.l]);
-		loadri (fn, cmp, &e->bin.r);
-		goto common;
+	case DT_LDOUBLE:
+		error ("normal comparisons not implemented for floats, use feq, flt, etc.");
 
 	case DT_DWORD:
 	case DT_QWORD:
@@ -1937,7 +2011,33 @@ char *cmp, *cc;
 		printf ("\tmov ax, 1\n\n");
 		printf (".Li%d:\n", l2);
 		break;
+	}
+	return 0;
+}
+
+gen_fcmp (fn, e, cc, swap)
+struct func *fn;
+struct expr *e;
+char *cc;
+{
+	int l1, l2;
+
+	assert (!e->bin.r.is_imm);
+	l1 = nlbl++;
+	l2 = nlbl++;
+	if (swap) {
+		loadf (NULL, &fn->regs[e->bin.r.reg]);
+		loadf ("fcomp", &fn->regs[e->bin.l]);
+	} else {
+		loadf (NULL, &fn->regs[e->bin.l]);
+		loadf ("fcomp", &fn->regs[e->bin.r.reg]);
 	}
+	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);
 	return 0;
 }
 
@@ -1957,7 +2057,7 @@ struct expr *e;
 	struct regimm *ri;
 	struct reg *r;
 	char *s;
-	int i, cnt, sz;
+	int i, cnt, sz, l1, l2;
 
 	switch (e->type) {
 	case EX_INT:
@@ -2128,35 +2228,75 @@ struct expr *e;
 		gen_div (fn, dt, e, 1);
 		break;
 	case EX_EQ:
-		gen_cmp (fn, dt, e, "test", "e");
+		gen_cmp (fn, e, "test", "e");
 		break;
 	case EX_NE:
-		gen_cmp (fn, dt, e, "test", "ne");
+		gen_cmp (fn, e, "test", "ne");
 		break;
 	case EX_ULT:
-		gen_cmp (fn, dt, e, "cmp", "b");
+		gen_cmp (fn, e, "cmp", "b");
 		break;
 	case EX_UGT:
-		gen_cmp (fn, dt, e, "cmp", "a");
+		gen_cmp (fn, e, "cmp", "a");
 		break;
 	case EX_ULE:
-		gen_cmp (fn, dt, e, "cmp", "be");
+		gen_cmp (fn, e, "cmp", "be");
 		break;
 	case EX_UGE:
-		gen_cmp (fn, dt, e, "cmp", "a");
+		gen_cmp (fn, e, "cmp", "a");
 		break;
 	case EX_SLT:
-		gen_cmp (fn, dt, e, "cmp", "l");
+		gen_cmp (fn, e, "cmp", "l");
 		break;
 	case EX_SGT:
-		gen_cmp (fn, dt, e, "cmp", "g");
+		gen_cmp (fn, e, "cmp", "g");
 		break;
 	case EX_SLE:
-		gen_cmp (fn, dt, e, "cmp", "le");
+		gen_cmp (fn, e, "cmp", "le");
 		break;
 	case EX_SGE:
-		gen_cmp (fn, dt, e, "cmp", "l");
+		gen_cmp (fn, e, "cmp", "l");
+		break;
+	case EX_FEQ:
+		assert (!e->bin.r.is_imm);
+		l1 = nlbl++;
+		l2 = nlbl++;
+		loadf (NULL, &fn->regs[e->bin.l]);
+		loadf ("fcomp", &fn->regs[e->bin.r.reg]);
+		printf ("\tjp .Li%d\n", l1);
+		printf ("\tjne .Li%d\n", l1);
+		printf ("\tmov ax, 1\n");
+		printf ("\tjmp .Li%d\n\n", l2);
+		printf (".Li%d:\n", l1);
+		printf ("\txor ax, ax\n\n");
+		printf (".Li%d:\n", l2);
+		break;
+	case EX_FNE:
+		assert (!e->bin.r.is_imm);
+		l1 = nlbl++;
+		l2 = nlbl++;
+		loadf (NULL, &fn->regs[e->bin.l]);
+		loadf ("fcomp", &fn->regs[e->bin.r.reg]);
+		printf ("\tjp .Li%d\n", l1);
+		printf ("\tjne .Li%d\n", 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;
+	case EX_FLT:
+		gen_fcmp (fn, e, "a", 1);
+		break;
+	case EX_FGT:
+		gen_fcmp (fn, e, "a", 0);
 		break;
+	case EX_FLE:
+		gen_fcmp (fn, e, "ae", 1);
+		break;
+	case EX_FGE:
+		gen_fcmp (fn, e, "ae", 0);
+		break;
 	case EX_PTRADD:
 		load (NULL, &fn->regs[e->bin.l]);
 
blob - dfb0074af5ead8ecf334031ce9837db67e2cb4c8
blob + 87774e9d23d0c92f8e40e943e6769eaf186b85dd
--- cc/irc/test.ir
+++ cc/irc/test.ir
@@ -212,3 +212,15 @@ fn cmp (): word {
 	let $2: word = eq $0, $1;
 	ret $2;
 }
+
+fn fcmp (): word {
+	let $0: float = 1.23;
+	let $1: float = 4.56;
+	let $2: word = feq $0, $1;
+	let $3: word = fne $0, $1;
+	let $4: word = flt $0, $1;
+	let $5: word = fgt $0, $1;
+	let $6: word = fle $0, $1;
+	let $7: word = fge $0, $1;
+	ret 0;
+}