aboutsummaryrefslogtreecommitdiff
path: root/tccasm.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-06-30 15:47:58 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:07 +0100
commit1a5eacb445a0116722e88e1a8a3e88e9d4127d2b (patch)
tree6330bf403930d823891a10d45020476ad583b085 /tccasm.c
parentff5561ff7d699eb9e30e95f1e2cfd1e98e5a990d (diff)
downloadtinycc-1a5eacb445a0116722e88e1a8a3e88e9d4127d2b.tar.gz
tinycc-1a5eacb445a0116722e88e1a8a3e88e9d4127d2b.tar.bz2
tccasm: Implement compare expressions
I.e. implement < > <= >= == !=. Comparisons are signed and result is -1 if true, 0 if false.
Diffstat (limited to 'tccasm.c')
-rw-r--r--tccasm.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/tccasm.c b/tccasm.c
index 185f066..569ff81 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -259,9 +259,51 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
}
}
-ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
+static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
{
+ int op;
+ ExprValue e2;
+
asm_expr_sum(s1, pe);
+ for(;;) {
+ op = tok;
+ if (op != TOK_EQ && op != TOK_NE
+ && (op > TOK_GT || op < TOK_ULE))
+ break;
+ next();
+ asm_expr_sum(s1, &e2);
+ if (pe->sym || e2.sym)
+ tcc_error("invalid operation with label");
+ switch(op) {
+ case TOK_EQ:
+ pe->v = pe->v == e2.v;
+ break;
+ case TOK_NE:
+ pe->v = pe->v != e2.v;
+ break;
+ case TOK_LT:
+ pe->v = (int64_t)pe->v < (int64_t)e2.v;
+ break;
+ case TOK_GE:
+ pe->v = (int64_t)pe->v >= (int64_t)e2.v;
+ break;
+ case TOK_LE:
+ pe->v = (int64_t)pe->v <= (int64_t)e2.v;
+ break;
+ case TOK_GT:
+ pe->v = (int64_t)pe->v > (int64_t)e2.v;
+ break;
+ default:
+ break;
+ }
+ /* GAS compare results are -1/0 not 1/0. */
+ pe->v = -(int64_t)pe->v;
+ }
+}
+
+ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
+{
+ asm_expr_cmp(s1, pe);
}
ST_FUNC int asm_int_expr(TCCState *s1)
@@ -391,6 +433,8 @@ static void asm_parse_directive(TCCState *s1)
if (sec->sh_addralign < n)
sec->sh_addralign = n;
} else {
+ if (n < 0)
+ n = 0;
size = n;
}
v = 0;