summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-26 22:14:04 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-26 22:14:04 +0000
commit9e3a7563ccfde741187b4163bfde63f9c87b6122 (patch)
treece9f3b3dc1395df3f3f51a00fdf44935fd03c6a9
parent04bb63fd5ec285b38de88635985885d70460ba71 (diff)
downloadpp2cc-9e3a7563ccfde741187b4163bfde63f9c87b6122.tar.gz
Support for bitshift (<< and >>) operators, allow for label on asm.pull
-rwxr-xr-xpp2cc.py53
1 files 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