summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-27 10:37:41 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-27 10:37:41 +0000
commit2678ed888b39d27d4bace24d7fad584c5cc91a10 (patch)
tree1184696356336b2fe0b517c92df0e086ec697d80
parent806e7e40726f7262b3969994238861428a571724 (diff)
downloadpp2cc-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-xpp2cc.py51
1 files 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