def _collect_and_push_stack_args(self, arglocs): n_args = len(arglocs) reg_args = count_reg_args(arglocs) # all arguments past the 4th go on the stack # first we need to prepare the list so it stays aligned stack_args = [] count = 0 on_stack = 0 if n_args > reg_args: for i in range(reg_args, n_args): arg = arglocs[i] if arg.type != FLOAT: count += 1 on_stack += 1 else: on_stack += 2 if count % 2 != 0: stack_args.append(None) count = 0 on_stack += 1 stack_args.append(arg) if count % 2 != 0: on_stack += 1 stack_args.append(None) if on_stack > 0: self._push_stack_args(stack_args, on_stack * WORD)
def _collect_and_push_stack_args(self, arglocs): n_args = len(arglocs) reg_args = count_reg_args(arglocs) # all arguments past the 4th go on the stack # first we need to prepare the list so it stays aligned stack_args = [] count = 0 on_stack = 0 if n_args > reg_args: for i in range(reg_args, n_args): arg = arglocs[i] if arg.type != FLOAT: count += 1 on_stack += 1 else: on_stack += 2 if count % 2 != 0: stack_args.append(None) count = 0 on_stack += 1 stack_args.append(arg) if count % 2 != 0: on_stack += 1 stack_args.append(None) if on_stack > 0: self._push_stack_args(stack_args, on_stack*WORD)
def prepare_arguments(self): arglocs = self.arglocs reg_args = count_reg_args(arglocs) self._collect_and_push_stack_args(arglocs) # collect variables that need to go in registers and the registers they # will be stored in num = 0 count = 0 non_float_locs = [] non_float_regs = [] float_locs = [] for i in range(reg_args): arg = arglocs[i] if arg.type == FLOAT and count % 2 != 0: num += 1 count = 0 reg = r.caller_resp[num] if arg.type == FLOAT: float_locs.append((arg, reg)) else: non_float_locs.append(arg) non_float_regs.append(reg) if arg.type == FLOAT: num += 2 else: num += 1 count += 1 # Check that the address of the function we want to call is not # currently stored in one of the registers used to pass the arguments # or on the stack, which we can not access later # If this happens to be the case we remap the register to r4 and use r4 # to call the function if not self.fnloc.is_imm(): non_float_locs.append(self.fnloc) non_float_regs.append(r.r4) self.fnloc = r.r4 # remap values stored in core registers remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip) for loc, reg in float_locs: self.asm.mov_from_vfp_loc(loc, reg, r.all_regs[reg.value + 1])
def prepare_arguments(self): arglocs = self.arglocs reg_args = count_reg_args(arglocs) self._collect_and_push_stack_args(arglocs) # collect variables that need to go in registers and the registers they # will be stored in num = 0 count = 0 non_float_locs = [] non_float_regs = [] float_locs = [] for i in range(reg_args): arg = arglocs[i] if arg.type == FLOAT and count % 2 != 0: num += 1 count = 0 reg = r.caller_resp[num] if arg.type == FLOAT: float_locs.append((arg, reg)) else: non_float_locs.append(arg) non_float_regs.append(reg) if arg.type == FLOAT: num += 2 else: num += 1 count += 1 # Check that the address of the function we want to call is not # currently stored in one of the registers used to pass the arguments # or on the stack, which we can not access later # If this happens to be the case we remap the register to r4 and use r4 # to call the function if self.fnloc in r.argument_regs or self.fnloc.is_stack(): non_float_locs.append(self.fnloc) non_float_regs.append(r.r4) self.fnloc = r.r4 # remap values stored in core registers remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip) for loc, reg in float_locs: self.asm.mov_from_vfp_loc(loc, reg, r.all_regs[reg.value + 1])
def test_count_reg_args(): assert count_reg_args([BoxPtr()]) == 1 assert count_reg_args([BoxPtr()] * 2) == 2 assert count_reg_args([BoxPtr()] * 3) == 3 assert count_reg_args([BoxPtr()] * 4) == 4 assert count_reg_args([BoxPtr()] * 5) == 4 assert count_reg_args([BoxFloat()] * 1) == 1 assert count_reg_args([BoxFloat()] * 2) == 2 assert count_reg_args([BoxFloat()] * 3) == 2 assert count_reg_args([BoxInt(), BoxInt(), BoxFloat()]) == 3 assert count_reg_args([BoxInt(), BoxFloat(), BoxInt()]) == 2 assert count_reg_args([BoxInt(), BoxFloat(), BoxInt()]) == 2 assert count_reg_args([BoxInt(), BoxInt(), BoxInt(), BoxFloat()]) == 3