summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-28 19:17:30 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-28 19:17:30 +0000
commit83d005c9c6937236523ae15eaef792c8ef3dae06 (patch)
tree6b158ced67556fe1947032cf720800184adb386a /pp2cc.py
parent0086c2a0a421df52be49817293fcdab0221e010f (diff)
downloadpp2cc-83d005c9c6937236523ae15eaef792c8ef3dae06.tar.gz
Fix shifting and document is better
Left shift was interpreted as right and left shift did not work properly for negative values
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py41
1 files changed, 35 insertions, 6 deletions
diff --git a/pp2cc.py b/pp2cc.py
index 97e091d..a13be6f 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -531,10 +531,6 @@ 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:
@@ -546,7 +542,25 @@ class Parse(object):
# 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))
+ if op == "<<":
+ lines.append(self.asm.binary_op("MULS", reg_first, operand))
+ else:
+ # because DIV works with signed numbers, right shift is
+ # a bit harder because the sign bit does not vanish
+ lbl_make_positive = self.uniqLbl("shiftPositive")
+ lines.append(self.asm.binary_op("CMP", reg_first, 0))
+ # if it's positive, skip handling for negative values
+ lines.append(self.asm.branch_op("BPL", lbl_make_positive))
+ # shift it by one
+ lines.append(self.asm.binary_op("DIV", reg_first, 1))
+ # make it positive if not already
+ mask = "%0" + (self.WORDSIZE - 1) * "1"
+ lines.append(self.asm.binary_op("AND", reg_first, mask,
+ label=lbl_make_positive))
+ # decrease shift count and finish if nothing to shift
+ operand /= 2
+ if operand > 1:
+ lines.append(self.asm.binary_op("DIV", reg_first, operand))
else:
lbl_gen = self.uniqLbl("gen2_loop")
lbl_gen_end = self.uniqLbl("gen2_done")
@@ -557,7 +571,22 @@ class Parse(object):
# 1 and jump to the end
lines.append(self.asm.branch_op("BLE", lbl_gen_end))
- lines.append(self.asm.binary_op(op, reg_first, 2, label=lbl_gen))
+ if op == "<<":
+ lines.append(self.asm.binary_op("MULS", reg_first, 2, label=lbl_gen))
+ else:
+ # now first check if the first number is negative...
+ lines.append(self.asm.binary_op("CMP", reg_first, 0))
+ lines.append(self.asm.branch_op("BPL", lbl_gen))
+ # shift it by one
+ lines.append(self.asm.binary_op("DIV", reg_first, 1))
+ # make negative values positive
+ mask = "%0" + (self.WORDSIZE - 1) * "1"
+ lines.append(self.asm.binary_op("AND", reg_first, mask))
+ # decrease shift count and finish if shift count is zero
+ lines.append(self.asm.binary_op("SUB", reg_second, 1))
+ lines.append(self.asm.branch_op("BEQ", lbl_gen_end))
+ # continue regular shifting
+ lines.append(self.asm.binary_op("DIV", 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