diff options
author | Peter Wu <lekensteyn@gmail.com> | 2011-11-27 10:37:41 +0000 |
---|---|---|
committer | Peter Wu <lekensteyn@gmail.com> | 2011-11-27 10:37:41 +0000 |
commit | 2678ed888b39d27d4bace24d7fad584c5cc91a10 (patch) | |
tree | 1184696356336b2fe0b517c92df0e086ec697d80 | |
parent | 806e7e40726f7262b3969994238861428a571724 (diff) | |
download | pp2cc-2678ed888b39d27d4bace24d7fad584c5cc91a10.tar.gz |
Fix zero shift not returning a value (e.g. 1<<0), optimize shift on nested expressions (e.g. 1<<(1+1))
-rwxr-xr-x | pp2cc.py | 51 |
1 files changed, 18 insertions, 33 deletions
@@ -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 |