From 9e3a7563ccfde741187b4163bfde63f9c87b6122 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sat, 26 Nov 2011 22:14:04 +0000 Subject: Support for bitshift (<< and >>) operators, allow for label on asm.pull --- pp2cc.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/pp2cc.py b/pp2cc.py index 40ef5cf..1b5e1c5 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -115,8 +115,8 @@ class Asm(object): def push(self, register, label=""): return self.format_line("PUSH " + register, label) - def pull(self, register): - return self.format_line("PULL " + register) + def pull(self, register, label=""): + return self.format_line("PULL " + register, label) def insert_label(self, instruction, label): new_instruction = instruction.lstrip(" ") @@ -387,6 +387,8 @@ class Parse(object): op = self.binary_ops[node.op] elif node.op in ("&&", "||"): return self.parseBinaryLogicalOp(linked_node) + elif node.op in ("<<", ">>"): + op = node.op else: raise RuntimeError("Binary op is not implemented yet: " + node.op) @@ -438,6 +440,53 @@ class Parse(object): lines.append(self.asm.branch_op("BRA", bin_end)) lines.append(self.asm.binary_op("LOAD", reg_first, 1, label=bin_true)) lines.append(self.asm.noop(bin_end, register=reg_first)) + elif op in ("<<", ">>"): + if isinstance(node.right, c_ast.Constant): + shift_bits = self.convertStrToInteger(operand) + if shift_bits < 0: + self.logger.warning("The number of bits to be shifted are" + "negative, no operation will be performed", + linked_node=linked_node) + operand = 0 + else: + operand = pow(2, shift_bits) + else: + lbl_gen = self.uniqLbl("gen2_loop") + lbl_gen_end = self.uniqLbl("gen2_done") + # save the result of the first operand + lines.append(self.asm.push(reg_first)) + # we could optimize here by trying to insert the LOAD Rx 1 + # operation before the PULL or LOAD operator, but that is not + # flexible + reg_shift_num = reg_first + lines.append(self.asm.binary_op("LOAD", reg_shift_num, 1)) + reg_shift_bits = reg_second + + # necessary to set the status flags for the branch conditions + lines.append(self.asm.binary_op("CMP", reg_shift_bits, 0)) + # if operand 2 is lower than 1, do not bother enlarging the shift number + lines.append(self.asm.branch_op("BLE", lbl_gen_end)) + + lines.append(self.asm.binary_op("MULS", reg_shift_num, 2, label=lbl_gen)) + lines.append(self.asm.binary_op("SUB", reg_shift_bits, 1)) + lines.append(self.asm.branch_op("BGT", lbl_gen)) + + # restore the result of the first operand + lines.append(self.asm.pull(reg_second, label=lbl_gen_end)) + # the result is now stored in the register used for the first + # operand because the second one holds the number which used in + # multiplication/division. Meanwhile the first register was + # used for a counter to calculate 2^counter. That means that + # we've swapped the registers now, which is why the below line + # is required + reg_first = reg_second + operand = reg_shift_num + # shifting only makes sense if shifting a number larger than 0 (e.g. 1 << 1) + if operand > 0: + if op == "<<": + lines.append(self.asm.binary_op("MULS", reg_first, operand)) + elif op == ">>": + lines.append(self.asm.binary_op("DIV", reg_first, operand)) else: lines.append(self.asm.binary_op(op, reg_first, operand)) return lines -- cgit v1.2.1