Add flonum ==, !=, < and <=

This commit is contained in:
Rui Ueyama 2020-09-22 18:28:37 +09:00
parent 29de46aed4
commit cf9ceecb2f
3 changed files with 74 additions and 0 deletions

View File

@ -34,6 +34,18 @@ static void pop(char *arg) {
depth--;
}
static void pushf(void) {
println(" sub $8, %%rsp");
println(" movsd %%xmm0, (%%rsp)");
depth++;
}
static void popf(char *arg) {
println(" movsd (%%rsp), %s", arg);
println(" add $8, %%rsp");
depth--;
}
// Round up `n` to the nearest multiple of `align`. For instance,
// align_to(5, 8) returns 8 and align_to(11, 8) returns 16.
int align_to(int n, int align) {
@ -403,6 +415,43 @@ static void gen_expr(Node *node) {
}
}
if (is_flonum(node->lhs->ty)) {
gen_expr(node->rhs);
pushf();
gen_expr(node->lhs);
popf("%xmm1");
char *sz = (node->lhs->ty->kind == TY_FLOAT) ? "ss" : "sd";
switch (node->kind) {
case ND_EQ:
case ND_NE:
case ND_LT:
case ND_LE:
println(" ucomi%s %%xmm0, %%xmm1", sz);
if (node->kind == ND_EQ) {
println(" sete %%al");
println(" setnp %%dl");
println(" and %%dl, %%al");
} else if (node->kind == ND_NE) {
println(" setne %%al");
println(" setp %%dl");
println(" or %%dl, %%al");
} else if (node->kind == ND_LT) {
println(" seta %%al");
} else {
println(" setae %%al");
}
println(" and $1, %%al");
println(" movzb %%al, %%rax");
return;
}
error_tok(node->tok, "invalid expression");
}
gen_expr(node->rhs);
push();
gen_expr(node->lhs);

View File

@ -39,6 +39,26 @@ int main() {
ASSERT(-2147483648, (double)(unsigned long)(long)-1);
ASSERT(1, 2e3==2e3);
ASSERT(0, 2e3==2e5);
ASSERT(1, 2.0==2);
ASSERT(0, 5.1<5);
ASSERT(0, 5.0<5);
ASSERT(1, 4.9<5);
ASSERT(0, 5.1<=5);
ASSERT(1, 5.0<=5);
ASSERT(1, 4.9<=5);
ASSERT(1, 2e3f==2e3);
ASSERT(0, 2e3f==2e5);
ASSERT(1, 2.0f==2);
ASSERT(0, 5.1f<5);
ASSERT(0, 5.0f<5);
ASSERT(1, 4.9f<5);
ASSERT(0, 5.1f<=5);
ASSERT(1, 5.0f<=5);
ASSERT(1, 4.9f<=5);
printf("OK\n");
return 0;
}

5
type.c
View File

@ -73,6 +73,11 @@ static Type *get_common_type(Type *ty1, Type *ty2) {
if (ty1->base)
return pointer_to(ty1->base);
if (ty1->kind == TY_DOUBLE || ty2->kind == TY_DOUBLE)
return ty_double;
if (ty1->kind == TY_FLOAT || ty2->kind == TY_FLOAT)
return ty_float;
if (ty1->size < 4)
ty1 = ty_int;
if (ty2->size < 4)