def test_reordering(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) remap_frame_layout(self.assembler, [r7, s8, s20, r4], [s8, r4, r7, r2], "?") assert self.assembler.got([("mov", r4, r2), ("mov", s8, r4), ("mov", r7, s8), ("mov", s20, r7)])
def test_cycle_2(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) s2 = frame_pos(2, INT) s3 = frame_pos(3, INT) remap_frame_layout( self.assembler, [r0, s8, r1, s20, r0, s20, s24, r3, s2, s3], [s8, s20, r1, r0, r4, s24, r5, s12, s3, s2], ip ) assert self.assembler.got( [ ("mov", r0, r4), ("mov", s24, r5), ("mov", r3, s12), ("mov", s20, ip), ("mov", ip, s24), ("push", s8), ("mov", r0, s8), ("mov", s20, r0), ("pop", s20), ("push", s3), ("mov", s2, ip), ("mov", ip, s3), ("pop", s2), ] )
def test_simple_framelocs(self): s8 = frame_pos(0, INT) s12 = frame_pos(13, INT) s20 = frame_pos(20, INT) s24 = frame_pos(221, INT) remap_frame_layout(self.assembler, [s8, r7, s12], [s20, s24, r9], ip) assert self.assembler.ops == [("mov", s8, ip), ("mov", ip, s20), ("mov", r7, s24), ("mov", s12, r9)]
def test_cycle(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) remap_frame_layout(self.assembler, [r4, s8, s20, r7], [s8, r7, r4, s20], "?") assert self.assembler.got([("push", s8), ("mov", r4, s8), ("mov", s20, r4), ("mov", r7, s20), ("pop", r7)])
def test_simple_framelocs(self): s8 = frame_pos(0, INT) s12 = frame_pos(13, INT) s20 = frame_pos(20, INT) s24 = frame_pos(221, INT) remap_frame_layout(self.assembler, [s8, r7, s12], [s20, s24, r9], ip) assert self.assembler.ops == [('mov', s8, ip), ('mov', ip, s20), ('mov', r7, s24), ('mov', s12, r9)]
def test_reordering(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) remap_frame_layout(self.assembler, [r7, s8, s20, r4], [s8, r4, r7, r2], '?') assert self.assembler.got([('mov', r4, r2), ('mov', s8, r4), ('mov', r7, s8), ('mov', s20, r7)])
def test_cycle(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) remap_frame_layout(self.assembler, [r4, s8, s20, r7], [s8, r7, r4, s20], '?') assert self.assembler.got([('push', s8), ('mov', r4, s8), ('mov', s20, r4), ('mov', r7, s20), ('pop', r7)])
def prepare_arguments(self): non_float_locs = [] non_float_regs = [] float_locs = [] float_regs = [] stack_args = [] arglocs = self.arglocs argtypes = self.argtypes count = 0 # stack alignment counter on_stack = 0 for arg in arglocs: if arg.type != FLOAT: if len(non_float_regs) < len(r.argument_regs): reg = r.argument_regs[len(non_float_regs)] non_float_locs.append(arg) non_float_regs.append(reg) else: # non-float argument that needs to go on the stack count += 1 on_stack += 1 stack_args.append(arg) else: if len(float_regs) < len(r.vfp_argument_regs): reg = r.vfp_argument_regs[len(float_regs)] float_locs.append(arg) float_regs.append(reg) else: # float argument that needs to go on the stack if count % 2 != 0: stack_args.append(None) count = 0 on_stack += 1 stack_args.append(arg) on_stack += 2 # align the stack if count % 2 != 0: stack_args.append(None) on_stack += 1 self._push_stack_args(stack_args, on_stack*WORD) # 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 non_float_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) # remap values stored in vfp registers remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip)
def test_cycle_2(self): s8 = frame_pos(8, INT) s12 = frame_pos(12, INT) s20 = frame_pos(19, INT) s24 = frame_pos(1, INT) s2 = frame_pos(2, INT) s3 = frame_pos(3, INT) remap_frame_layout(self.assembler, [r0, s8, r1, s20, r0, s20, s24, r3, s2, s3], [s8, s20, r1, r0, r4, s24, r5, s12, s3, s2], ip) assert self.assembler.got([('mov', r0, r4), ('mov', s24, r5), ('mov', r3, s12), ('mov', s20, ip), ('mov', ip, s24), ('push', s8), ('mov', r0, s8), ('mov', s20, r0), ('pop', s20), ('push', s3), ('mov', s2, ip), ('mov', ip, s3), ('pop', s2)])
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_trivial(self): remap_frame_layout(self.assembler, [], [], "?") assert self.assembler.ops == [] remap_frame_layout(self.assembler, [r0, r1, r3, r5, r6, r7, r9], [r0, r1, r3, r5, r6, r7, r9], "?") assert self.assembler.ops == [] s8 = frame_pos(1, INT) s12 = frame_pos(31, INT) s20 = frame_pos(6, INT) remap_frame_layout( self.assembler, [r0, r1, s20, s8, r3, r5, r6, s12, r7, r9], [r0, r1, s20, s8, r3, r5, r6, s12, r7, r9], "?" ) assert self.assembler.ops == []
def test_trivial(self): remap_frame_layout(self.assembler, [], [], '?') assert self.assembler.ops == [] remap_frame_layout(self.assembler, [r0, r1, r3, r5, r6, r7, r9], [r0, r1, r3, r5, r6, r7, r9], '?') assert self.assembler.ops == [] s8 = frame_pos(1, INT) s12 = frame_pos(31, INT) s20 = frame_pos(6, INT) remap_frame_layout(self.assembler, [r0, r1, s20, s8, r3, r5, r6, s12, r7, r9], [r0, r1, s20, s8, r3, r5, r6, s12, r7, r9], '?') assert self.assembler.ops == []
def prepare_arguments(self): non_float_locs = [] non_float_regs = [] float_locs = [] float_regs = [] stack_args = [] singlefloats = None arglocs = self.arglocs argtypes = self.argtypes count = 0 # stack alignment counter on_stack = 0 for i in range(len(arglocs)): argtype = INT if i < len(argtypes) and argtypes[i] == 'S': argtype = argtypes[i] arg = arglocs[i] if arg.is_float(): argtype = FLOAT reg = self.get_next_vfp(argtype) if reg: assert len(float_regs) < len(r.vfp_argument_regs) float_locs.append(arg) assert reg not in float_regs float_regs.append(reg) else: # float argument that needs to go on the stack if count % 2 != 0: stack_args.append(None) count = 0 on_stack += 1 stack_args.append(arg) on_stack += 2 elif argtype == 'S': # Singlefloat argument if singlefloats is None: singlefloats = [] tgt = self.get_next_vfp(argtype) if tgt: singlefloats.append((arg, tgt)) else: # Singlefloat argument that needs to go on the stack # treated the same as a regular core register argument count += 1 on_stack += 1 stack_args.append(arg) else: if len(non_float_regs) < len(r.argument_regs): reg = r.argument_regs[len(non_float_regs)] non_float_locs.append(arg) non_float_regs.append(reg) else: # non-float argument that needs to go on the stack count += 1 on_stack += 1 stack_args.append(arg) # align the stack if count % 2 != 0: stack_args.append(None) on_stack += 1 self._push_stack_args(stack_args, on_stack*WORD) # 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 non_float_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 vfp registers remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip) if singlefloats: for src, dest in singlefloats: if src.is_float(): assert 0, 'unsupported case' if src.is_stack(): # use special VLDR for 32bit self.asm.regalloc_mov(src, r.ip) src = r.ip if src.is_imm(): self.mc.gen_load_int(r.ip.value, src.value) src = r.ip if src.is_core_reg(): self.mc.VMOV_cs(dest.value, src.value) # remap values stored in core registers remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip)
def test_constants2(self): c3 = ImmLocation(3) s12 = frame_pos(12, INT) remap_frame_layout(self.assembler, [c3], [s12], "?") assert self.assembler.ops == [("mov", c3, s12)]
def test_constants_and_cycle(self): c3 = ImmLocation(3) s12 = frame_pos(13, INT) remap_frame_layout(self.assembler, [r5, c3, s12], [s12, r0, r5], r1) assert self.assembler.ops == [("mov", c3, r0), ("push", s12), ("mov", r5, s12), ("pop", r5)]
def test_simple_registers(self): remap_frame_layout(self.assembler, [r0, r1, r2], [r3, r4, r5], '?') assert self.assembler.ops == [('mov', r0, r3), ('mov', r1, r4), ('mov', r2, r5)]
def test_constants_and_cycle(self): c3 = ImmLocation(3) s12 = frame_pos(13, INT) remap_frame_layout(self.assembler, [r5, c3, s12], [s12, r0, r5], r1) assert self.assembler.ops == [('mov', c3, r0), ('push', s12), ('mov', r5, s12), ('pop', r5)]
def test_constants2(self): c3 = ImmLocation(3) s12 = frame_pos(12, INT) remap_frame_layout(self.assembler, [c3], [s12], '?') assert self.assembler.ops == [('mov', c3, s12)]
def test_constants(self): c3 = ImmLocation(3) remap_frame_layout(self.assembler, [c3], [r0], '?') assert self.assembler.ops == [('mov', c3, r0)]
def prepare_arguments(self): non_float_locs = [] non_float_regs = [] float_locs = [] float_regs = [] stack_args = [] singlefloats = None longlong_mask = 0 arglocs = self.arglocs argtypes = self.argtypes r_register_count = 0 on_stack = 0 for i in range(len(arglocs)): argtype = INT if i < len(argtypes) and argtypes[i] == 'S': argtype = argtypes[i] arg = arglocs[i] if arg.is_float(): if i < len(argtypes) and argtypes[i] == 'L': # A longlong argument. It uses two regular argument # positions, but aligned to an even number. This is # a bit strange, but it is the case even for registers: # it can be in r0-r1 or in r2-r3 but not in r1-r2. assert arg.is_float() if r_register_count == 0: # will temporarily load the register into d8 float_locs.append(arg) float_regs.append(r.d8) longlong_mask |= 1 r_register_count = 2 continue elif r_register_count <= 2: # will temporarily load the register into d9 float_locs.append(arg) float_regs.append(r.d9) longlong_mask |= 2 r_register_count = 4 continue elif r_register_count == 3: r_register_count = 4 else: # A 64-bit float argument. Goes into the next free v# # register, or if none, to the stack aligned to an # even number of words. argtype = FLOAT reg = self.get_next_vfp(argtype) if reg: float_locs.append(arg) assert reg not in float_regs float_regs.append(reg) continue # float or longlong argument that needs to go on the stack if on_stack & 1: # odd: realign stack_args.append(None) on_stack += 1 stack_args.append(arg) on_stack += 2 elif argtype == 'S': # Singlefloat (32-bit) argument. Goes into the next free # v# register, or if none, to the stack in a single word. if singlefloats is None: singlefloats = [] tgt = self.get_next_vfp(argtype) if tgt: singlefloats.append((arg, tgt)) else: # Singlefloat argument that needs to go on the stack # treated the same as a regular core register argument stack_args.append(arg) on_stack += 1 else: # Regular one-word argument. Goes into the next register # free from the list r0, r1, r2, r3, or to the stack. if r_register_count < len(r.argument_regs): reg = r.argument_regs[r_register_count] r_register_count += 1 non_float_locs.append(arg) non_float_regs.append(reg) else: # non-float argument that needs to go on the stack stack_args.append(arg) on_stack += 1 # align the stack if on_stack & 1: # odd: realign stack_args.append(None) on_stack += 1 self._push_stack_args(stack_args, on_stack * WORD) # 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 vfp registers remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip) if singlefloats: for src, dest in singlefloats: if src.is_float(): assert 0, 'unsupported case' if src.is_stack(): # use special VLDR for 32bit self.asm.regalloc_mov(src, r.ip) src = r.ip if src.is_imm(): self.mc.gen_load_int(r.ip.value, src.value) src = r.ip if src.is_core_reg(): self.mc.VMOV_cs(dest.value, src.value) # remap values stored in core registers remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip) if longlong_mask & 1: self.mc.FMRRD(r.r0.value, r.r1.value, r.d8.value) if longlong_mask & 2: self.mc.FMRRD(r.r2.value, r.r3.value, r.d9.value)
def test_constants(self): c3 = ImmLocation(3) remap_frame_layout(self.assembler, [c3], [r0], "?") assert self.assembler.ops == [("mov", c3, r0)]
def prepare_arguments(self): non_float_locs = [] non_float_regs = [] float_locs = [] float_regs = [] stack_args = [] singlefloats = None longlong_mask = 0 arglocs = self.arglocs argtypes = self.argtypes r_register_count = 0 on_stack = 0 for i in range(len(arglocs)): argtype = INT if i < len(argtypes) and argtypes[i] == 'S': argtype = argtypes[i] arg = arglocs[i] if arg.is_float(): if i < len(argtypes) and argtypes[i] == 'L': # A longlong argument. It uses two regular argument # positions, but aligned to an even number. This is # a bit strange, but it is the case even for registers: # it can be in r0-r1 or in r2-r3 but not in r1-r2. assert arg.is_float() if r_register_count == 0: # will temporarily load the register into d8 float_locs.append(arg) float_regs.append(r.d8) longlong_mask |= 1 r_register_count = 2 continue elif r_register_count <= 2: # will temporarily load the register into d9 float_locs.append(arg) float_regs.append(r.d9) longlong_mask |= 2 r_register_count = 4 continue elif r_register_count == 3: r_register_count = 4 else: # A 64-bit float argument. Goes into the next free v# # register, or if none, to the stack aligned to an # even number of words. argtype = FLOAT reg = self.get_next_vfp(argtype) if reg: float_locs.append(arg) assert reg not in float_regs float_regs.append(reg) continue # float or longlong argument that needs to go on the stack if on_stack & 1: # odd: realign stack_args.append(None) on_stack += 1 stack_args.append(arg) on_stack += 2 elif argtype == 'S': # Singlefloat (32-bit) argument. Goes into the next free # v# register, or if none, to the stack in a single word. if singlefloats is None: singlefloats = [] tgt = self.get_next_vfp(argtype) if tgt: singlefloats.append((arg, tgt)) else: # Singlefloat argument that needs to go on the stack # treated the same as a regular core register argument stack_args.append(arg) on_stack += 1 else: # Regular one-word argument. Goes into the next register # free from the list r0, r1, r2, r3, or to the stack. if r_register_count < len(r.argument_regs): reg = r.argument_regs[r_register_count] r_register_count += 1 non_float_locs.append(arg) non_float_regs.append(reg) else: # non-float argument that needs to go on the stack stack_args.append(arg) on_stack += 1 # align the stack if on_stack & 1: # odd: realign stack_args.append(None) on_stack += 1 self._push_stack_args(stack_args, on_stack*WORD) # 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 vfp registers remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip) if singlefloats: for src, dest in singlefloats: if src.is_float(): assert 0, 'unsupported case' if src.is_stack(): # use special VLDR for 32bit self.asm.regalloc_mov(src, r.ip) src = r.ip if src.is_imm(): self.mc.gen_load_int(r.ip.value, src.value) src = r.ip if src.is_core_reg(): self.mc.VMOV_cs(dest.value, src.value) # remap values stored in core registers remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip) if longlong_mask & 1: self.mc.FMRRD(r.r0.value, r.r1.value, r.d8.value) if longlong_mask & 2: self.mc.FMRRD(r.r2.value, r.r3.value, r.d9.value)
def test_simple_registers(self): remap_frame_layout(self.assembler, [r0, r1, r2], [r3, r4, r5], "?") assert self.assembler.ops == [("mov", r0, r3), ("mov", r1, r4), ("mov", r2, r5)]