示例#1
0
    def preprocess_binop(self, expr):
        """
        Several nml operators are not directly support by nfo so we have to work
        around that by implementing those operators in terms of others.

        @return: A pre-processed version of the expression.
        @rtype:  L{Expression}
        """
        assert isinstance(expr, expression.BinOp)
        if expr.op == nmlop.CMP_LT:
            # return value is 0, 1 or 2, we want to map 0 to 1 and the others to 0
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            # reduce the problem to 0/1
            expr = nmlop.MIN(expr, 1)
            # and invert the result
            expr = nmlop.XOR(expr, 1)
        elif expr.op == nmlop.CMP_GT:
            # return value is 0, 1 or 2, we want to map 2 to 1 and the others to 0
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            # subtract one
            expr = nmlop.SUB(expr, 1)
            # map -1 and 0 to 0
            expr = nmlop.MAX(expr, 0)
        elif expr.op == nmlop.CMP_LE:
            # return value is 0, 1 or 2, we want to map 2 to 0 and the others to 1
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            # swap 0 and 2
            expr = nmlop.XOR(expr, 2)
            # map 1/2 to 1
            expr = nmlop.MIN(expr, 1)
        elif expr.op == nmlop.CMP_GE:
            # return value is 0, 1 or 2, we want to map 1/2 to 1
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            expr = nmlop.MIN(expr, 1)
        elif expr.op == nmlop.CMP_EQ:
            # return value is 0, 1 or 2, we want to map 1 to 1, other to 0
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            expr = nmlop.AND(expr, 1)
        elif expr.op == nmlop.CMP_NEQ:
            # same as CMP_EQ but invert the result
            expr = nmlop.VACT2_CMP(expr.expr1, expr.expr2)
            expr = nmlop.AND(expr, 1)
            expr = nmlop.XOR(expr, 1)

        elif expr.op == nmlop.HASBIT:
            # hasbit(x, n) ==> (x >> n) & 1
            expr = nmlop.SHIFTU_RIGHT(expr.expr1, expr.expr2)
            expr = nmlop.AND(expr, 1)
        elif expr.op == nmlop.NOTHASBIT:
            # !hasbit(x, n) ==> ((x >> n) & 1) ^ 1
            expr = nmlop.SHIFTU_RIGHT(expr.expr1, expr.expr2)
            expr = nmlop.AND(expr, 1)
            expr = nmlop.XOR(expr, 1)

        return expr.reduce()
示例#2
0
    def parse(self, expr):
        # Preprocess the expression
        if isinstance(expr, expression.SpecialParameter):
            # do this first, since it may evaluate to a BinOp
            expr = expr.to_reading()

        if isinstance(expr, expression.BinOp):
            expr = self.preprocess_binop(expr)

        elif isinstance(expr, expression.Boolean):
            expr = nmlop.MINU(expr.expr, 1)

        elif isinstance(expr, expression.BinNot):
            expr = nmlop.XOR(expr.expr, 0xFFFFFFFF)

        elif isinstance(
                expr,
                expression.TernaryOp) and not expr.supported_by_actionD(False):
            expr = self.preprocess_ternaryop(expr)

        elif isinstance(expr, expression.StorageOp):
            expr = self.preprocess_storageop(expr)

        # Try to parse the expression to a list of variables+operators
        if isinstance(expr, expression.ConstantNumeric):
            self.parse_constant(expr)

        elif isinstance(expr, expression.Parameter) and isinstance(
                expr.num, expression.ConstantNumeric):
            self.parse_param(expr)

        elif isinstance(expr, expression.Variable):
            self.parse_variable(expr)

        elif expr.supported_by_actionD(False):
            self.parse_via_actionD(expr)

        elif isinstance(expr, expression.BinOp):
            self.parse_binop(expr)

        elif isinstance(expr, expression.Not):
            self.parse_not(expr)

        elif isinstance(expr, expression.String):
            self.parse_string(expr)

        elif isinstance(expr,
                        (VarAction2LoadTempVar, VarAction2LoadCallParam)):
            self.var_list.append(expr)
            self.var_list_size += expr.get_size()

        elif isinstance(expr, expression.SpriteGroupRef):
            self.parse_proc_call(expr)

        else:
            expr.supported_by_action2(True)
            raise AssertionError(
                "supported_by_action2 should have raised the correct error already"
            )
示例#3
0
def builtin_getbits(name, args, pos):
    """
    getbits(value, first, amount) builtin function.

    @return Extract C{amount} bits starting at C{first} from C{value},
            that is (C{value} >> C{first}) & (1 << C{amount} - 1)
    """
    if len(args) != 3:
        raise generic.ScriptError(name + "() must have exactly three parameters", pos)

    # getbits(value, first, amount) = (value >> first) & ((0xFFFFFFFF << amount) ^ 0xFFFFFFFF)
    part1 = nmlop.SHIFTU_RIGHT(args[0], args[1], pos)
    part2 = nmlop.SHIFT_LEFT(0xFFFFFFFF, args[2], pos)
    part3 = nmlop.XOR(part2, 0xFFFFFFFF, pos)

    return nmlop.AND(part1, part3, pos)
示例#4
0
 def parse_not(self, expr):
     self.parse_binop(nmlop.XOR(expr.expr, 1))
示例#5
0
def value_sign_extend(var, info):
    #r = (x ^ m) - m; with m being (1 << (num_bits -1))
    m = expression.ConstantNumeric(1 << (info['size'] - 1))
    return nmlop.SUB(nmlop.XOR(var, m), m)