--- software/libfpvm/fpvm.c | 98 +++++++++++++++++++++++++++++------------------ 1 files changed, 61 insertions(+), 37 deletions(-)
diff --git a/software/libfpvm/fpvm.c b/software/libfpvm/fpvm.c index 68b460d..0d169c7 100644 --- a/software/libfpvm/fpvm.c +++ b/software/libfpvm/fpvm.c @@ -361,7 +361,8 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod int opa, opb; int opcode; - if(node->label[0] == 0) { + switch(node->token) { + case TOK_CONSTANT: /* AST node is a constant */ opa = REG_CONST(node->contents.constant); if(reg != FPVM_INVALID_REG) @@ -369,8 +370,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod else reg = opa; return reg; - } - if(node->contents.branches.a == NULL) { + case TOK_IDENT: /* AST node is a variable */ if(fragment->bind_mode) { opa = sym_to_reg(fragment, node->label, 0, NULL); @@ -390,22 +390,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod else reg = opa; return reg; - } - if((strcmp(node->label, "!") == 0) && - (node->contents.branches.a->label[0] == 0)) { - /* Node is a negative constant */ - struct ast_node *n; - - n = node->contents.branches.a; - opa = REG_CONST(-n->contents.constant); - if(reg != FPVM_INVALID_REG) - ADD_ISN(FPVM_OPCODE_COPY, opa, 0, reg); - else - reg = opa; - return reg; - } - /* AST node is an operator or function */ - if(strcmp(node->label, "if") == 0) { + case TOK_IF: /* * "if" must receive a special treatment. * It is implemented as a ternary function, @@ -417,7 +402,23 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod opa = COMPILE(FPVM_INVALID_REG, node->contents.branches.b); opb = COMPILE(FPVM_INVALID_REG, node->contents.branches.c); COMPILE(FPVM_REG_IFB, node->contents.branches.a); - } else { + break; + case TOK_NOT: + if(node->contents.branches.a->token == TOK_CONSTANT) { + /* Node is a negative constant */ + struct ast_node *n; + + n = node->contents.branches.a; + opa = REG_CONST(-n->contents.constant); + if(reg != FPVM_INVALID_REG) + ADD_ISN(FPVM_OPCODE_COPY, opa, 0, reg); + else + reg = opa; + return reg; + } + /* fall through */ + default: + /* AST node is an operator or function */ opa = COMPILE(FPVM_INVALID_REG, node->contents.branches.a); opb = 0; if(node->contents.branches.b != NULL) { @@ -426,13 +427,18 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod } } - if(reg == FPVM_INVALID_REG) reg = fragment->next_sur--; - if(strcmp(node->label, "below") == 0) { + if(reg == FPVM_INVALID_REG) + reg = fragment->next_sur--; + + switch(node->token) { + case TOK_BELOW: /* * "below" is like "above", but with reversed operands. */ ADD_ISN(FPVM_OPCODE_ABOVE, opb, opa, reg); - } else if((strcmp(node->label, "sin") == 0)||(strcmp(node->label, "cos") == 0)) { + break; + case TOK_SIN: + case TOK_COS: { /* * Trigo functions are implemented with several instructions. * We must convert the floating point argument in radians @@ -442,7 +448,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod int reg_mul = REG_ALLOC(); int reg_f2i = REG_ALLOC(); - if(strcmp(node->label, "sin") == 0) + if(node->token == TOK_SIN) opcode = FPVM_OPCODE_SIN; else opcode = FPVM_OPCODE_COS; @@ -450,9 +456,12 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod ADD_ISN(FPVM_OPCODE_FMUL, reg_const, opa, reg_mul); ADD_ISN(FPVM_OPCODE_F2I, reg_mul, 0, reg_f2i); ADD_ISN(opcode, reg_f2i, 0, reg); - } else if(strcmp(node->label, "sqrt") == 0) { + break; + } + case TOK_SQRT: { /* - * Square root is implemented with a variant of the Quake III algorithm. + * Square root is implemented with a variant of the Quake III + * algorithm. * See http://en.wikipedia.org/wiki/Fast_inverse_square_root * sqrt(x) = x*(1/sqrt(x)) */ @@ -460,9 +469,12 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod ADD_INV_SQRT(opa, reg_invsqrt); ADD_ISN(FPVM_OPCODE_FMUL, opa, reg_invsqrt, reg); - } else if(strcmp(node->label, "invsqrt") == 0) { + break; + } + case TOK_INVSQRT: ADD_INV_SQRT(opa, reg); - } else if(strcmp(node->label, "/") == 0) { + break; + case TOK_DIVIDE: { /* * Floating point division is implemented as * a/b = a*(1/sqrt(b))*(1/sqrt(b)) @@ -480,7 +492,9 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod ADD_ISN(FPVM_OPCODE_FMUL, reg_invsqrt, reg_invsqrt, reg_invsqrt2); ADD_ISN(FPVM_OPCODE_FMUL, reg_invsqrt2, reg_a2, reg); - } else if(strcmp(node->label, "%") == 0) { + break; + } + case TOK_PERCENT: { int reg_invsqrt = REG_ALLOC(); int reg_invsqrt2 = REG_ALLOC(); int reg_div = REG_ALLOC(); @@ -494,28 +508,38 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod ADD_INT(reg_div, reg_idiv); ADD_ISN(FPVM_OPCODE_FMUL, opb, reg_idiv, reg_bidiv); ADD_ISN(FPVM_OPCODE_FSUB, opa, reg_bidiv, reg); - } else if(strcmp(node->label, "min") == 0) { + break; + } + case TOK_MIN: ADD_ISN(FPVM_OPCODE_ABOVE, opa, opb, FPVM_REG_IFB); ADD_ISN(FPVM_OPCODE_IF, opb, opa, reg); - } else if(strcmp(node->label, "max") == 0) { + break; + case TOK_MAX: ADD_ISN(FPVM_OPCODE_ABOVE, opa, opb, FPVM_REG_IFB); ADD_ISN(FPVM_OPCODE_IF, opa, opb, reg); - } else if(strcmp(node->label, "sqr") == 0) { + break; + case TOK_SQR: ADD_ISN(FPVM_OPCODE_FMUL, opa, opa, reg); - } else if(strcmp(node->label, "int") == 0) { + break; + case TOK_INT: ADD_INT(opa, reg); - } else if(strcmp(node->label, "!") == 0) { + break; + case TOK_NOT: opb = find_negative_constant(fragment); - if(opb == FPVM_INVALID_REG) return FPVM_INVALID_REG; + if(opb == FPVM_INVALID_REG) + return FPVM_INVALID_REG; ADD_ISN(FPVM_OPCODE_TSIGN, opa, opb, reg); - } else { + break; + default: /* Normal case */ opcode = operator2opcode(node->token); if(opcode < 0) { - snprintf(fragment->last_error, FPVM_MAXERRLEN, "Operation not supported: %s", node->label); + snprintf(fragment->last_error, FPVM_MAXERRLEN, + "Operation not supported: %s", node->label); return FPVM_INVALID_REG; } ADD_ISN(opcode, opa, opb, reg); + break; } return reg; -- 1.7.1 _______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkymist@Freenode