From 2678ed888b39d27d4bace24d7fad584c5cc91a10 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sun, 27 Nov 2011 10:37:41 +0000 Subject: Fix zero shift not returning a value (e.g. 1<<0), optimize shift on nested expressions (e.g. 1<<(1+1)) --- pp2cc.py | 51 ++++++++++++++++++--------------------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/pp2cc.py b/pp2cc.py index 3ae5c0a..4a1a1b3 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -449,52 +449,37 @@ class Parse(object): 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 ("<<", ">>"): + op = { + "<<": "MULS", + ">>": "DIV" + }[op] 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: + lines.append(self.asm.binary_op("LOAD", reg_first, reg_first)) + elif shift_bits > 0: + # shifting only makes a difference if shifting a number + # larger than 0 (e.g. 1 << 1) operand = pow(2, shift_bits) + lines.append(self.asm.binary_op(op, reg_first, operand)) 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.binary_op("CMP", reg_second, 0)) + # if operand 2 is lower than 1, do not bother shifting operand + # 1 and jump to the end 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)) + lines.append(self.asm.binary_op(op, reg_first, 2, label=lbl_gen)) + lines.append(self.asm.binary_op("SUB", reg_second, 1)) + # if we came from BLE, x <= 0. BGT only jumps if x > 0, so + # we can safe another NOOP by adding the label here + lines.append(self.asm.branch_op("BGT", lbl_gen, label=lbl_gen_end)) else: lines.append(self.asm.binary_op(op, reg_first, operand)) return lines -- cgit v1.2.1