1
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, \
2
r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, \
3
r23, r24, r25, r26, r27, r28, r29, r30, r31 = range(32)
6
rFP = r2 # the ABI doesn't specify a frame pointer. however, we want one
8
class AllocationSlot(object):
12
# The field alloc points to a singleton used by the register
13
# allocator to detect conflicts. No two AllocationSlot
14
# instances with the same value in self.alloc can be used at
19
""" When we assign a variable to one of these registers, we
20
call make_loc() to get the actual location instance; that
21
instance will have its alloc field set to self. For
22
everything but condition registers, this is self."""
25
class _StackSlot(AllocationSlot):
27
def __init__(self, offset):
28
AllocationSlot.__init__(self)
31
return "stack@%s"%(self.offset,)
33
_stack_slot_cache = {}
34
def stack_slot(offset):
35
# because stack slots are put into dictionaries which compare by
36
# identity, it is important that there's a unique _StackSlot
37
# object for each offset, at least per function generated or
38
# something. doing the caching here is easier, though.
39
if offset in _stack_slot_cache:
40
return _stack_slot_cache[offset]
41
_stack_slot_cache[offset] = res = _StackSlot(offset)
50
class Register(AllocationSlot):
53
AllocationSlot.__init__(self)
56
regclass = GP_REGISTER
57
def __init__(self, number):
58
Register.__init__(self)
61
return 'r' + str(self.number)
62
gprs = map(GPR, range(32))
65
regclass = FP_REGISTER
66
def __init__(self, number):
67
Register.__init__(self)
70
fprs = map(FPR, range(32))
72
class BaseCRF(Register):
73
""" These represent condition registers; however, we never actually
74
use these as the location of something in the register allocator.
75
Instead, we place it in an instance of CRF which indicates which
76
bits are required to extract the value. Note that CRF().alloc will
77
always be an instance of this. """
79
def __init__(self, number):
85
crfs = map(BaseCRF, range(8))
89
def __init__(self, crf):
90
Register.__init__(self)
92
self.number = crf.number
93
self.info = (-1,-1) # (bit, negated)
94
def set_info(self, info):
98
# should never call this on a CRF, only a BaseCRF
99
raise NotImplementedError
100
def move_to_gpr(self, gpr):
101
bit, negated = self.info
102
return _CRF2GPR(gpr, self.alloc.number*4 + bit, negated)
103
def move_from_gpr(self, gpr):
105
self.set_info((2, 1))
106
return _GPR2CRF(self, gpr)
108
return 'crf' + str(self.number) + str(self.info)
111
regclass = CT_REGISTER
112
def move_from_gpr(self, gpr):
121
result is the Var instance that holds the result, or None
122
result_regclass is the class of the register the result goes into
124
reg_args is the vars that need to have registers allocated for them
125
reg_arg_regclasses is the type of register that needs to be allocated
128
self._magic_index = _insn_index[0]
131
return "<%s %d>" % (self.__class__.__name__, self._magic_index)
135
class Insn_GPR__GPR_GPR(Insn):
136
def __init__(self, methptr, result, args):
138
self.methptr = methptr
141
self.result_regclass = GP_REGISTER
143
self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
145
self.result_reg = None
149
def allocate(self, allocator):
150
self.result_reg = allocator.loc_of(self.result)
151
self.arg_reg1 = allocator.loc_of(self.reg_args[0])
152
self.arg_reg2 = allocator.loc_of(self.reg_args[1])
156
r = "%s@%s"%(self.result, self.result_reg)
160
a1 = "%s@%s"%(self.reg_args[0], self.arg_reg1)
162
a1 = str(self.reg_args[0])
164
a2 = "%s@%s"%(self.reg_args[1], self.arg_reg2)
166
a2 = str(self.reg_args[1])
167
return "<%s-%s %s %s, %s, %s>" % (self.__class__.__name__, self._magic_index,
168
self.methptr.im_func.func_name,
173
self.result_reg.number,
174
self.arg_reg1.number,
175
self.arg_reg2.number)
177
class Insn_GPR__GPR_IMM(Insn):
178
def __init__(self, methptr, result, args):
180
self.methptr = methptr
184
self.result_regclass = GP_REGISTER
185
self.reg_args = [args[0]]
186
self.reg_arg_regclasses = [GP_REGISTER]
187
self.result_reg = None
189
def allocate(self, allocator):
190
self.result_reg = allocator.loc_of(self.result)
191
self.arg_reg = allocator.loc_of(self.reg_args[0])
194
r = "%s@%s"%(self.result, self.result_reg)
198
a = "%s@%s"%(self.reg_args[0], self.arg_reg)
200
a = str(self.reg_args[0])
201
return "<%s-%d %s %s, %s, (%s)>" % (self.__class__.__name__, self._magic_index,
202
self.methptr.im_func.func_name,
203
r, a, self.imm.value)
207
self.result_reg.number,
211
class Insn_GPR__GPR(Insn):
212
def __init__(self, methptr, result, arg):
214
self.methptr = methptr
217
self.result_regclass = GP_REGISTER
218
self.reg_args = [arg]
219
self.reg_arg_regclasses = [GP_REGISTER]
221
self.result_reg = None
223
def allocate(self, allocator):
224
self.result_reg = allocator.loc_of(self.result)
225
self.arg_reg = allocator.loc_of(self.reg_args[0])
228
r = "%s@%s"%(self.result, self.result_reg)
232
a = "%s@%s"%(self.reg_args[0], self.arg_reg)
234
a = str(self.reg_args[0])
235
return "<%s-%d %s %s, %s>" % (self.__class__.__name__, self._magic_index,
236
self.methptr.im_func.func_name, r, a)
239
self.result_reg.number,
243
class Insn_GPR(Insn):
244
def __init__(self, methptr, result):
246
self.methptr = methptr
249
self.result_regclass = GP_REGISTER
251
self.reg_arg_regclasses = []
252
self.result_reg = None
253
def allocate(self, allocator):
254
self.result_reg = allocator.loc_of(self.result)
257
r = "%s@%s"%(self.result, self.result_reg)
260
return "<%s-%d %s %s>" % (self.__class__.__name__, self._magic_index,
261
self.methptr.im_func.func_name, r)
264
self.result_reg.number)
266
class Insn_GPR__IMM(Insn):
267
def __init__(self, methptr, result, args):
269
self.methptr = methptr
273
self.result_regclass = GP_REGISTER
275
self.reg_arg_regclasses = []
276
self.result_reg = None
277
def allocate(self, allocator):
278
self.result_reg = allocator.loc_of(self.result)
281
r = "%s@%s"%(self.result, self.result_reg)
284
return "<%s-%d %s %s, (%s)>" % (self.__class__.__name__, self._magic_index,
285
self.methptr.im_func.func_name, r,
289
self.result_reg.number,
292
class MoveCRB2GPR(Insn):
293
def __init__(self, result, gv_condition):
296
self.result_regclass = GP_REGISTER
297
self.reg_args = [gv_condition]
298
self.reg_arg_regclasses = [CR_FIELD]
299
def allocate(self, allocator):
300
self.targetreg = allocator.loc_of(self.result)
301
self.crf = allocator.loc_of(self.reg_args[0])
303
assert isinstance(self.crf, CRF)
304
bit, negated = self.crf.info
305
asm.mfcr(self.targetreg.number)
306
asm.extrwi(self.targetreg.number, self.targetreg.number, 1, self.crf.number*4+bit)
308
asm.xori(self.targetreg.number, self.targetreg.number, 1)
310
class Insn_None__GPR_GPR_IMM(Insn):
311
def __init__(self, methptr, args):
313
self.methptr = methptr
317
self.result_regclass = NO_REGISTER
318
self.reg_args = args[:2]
319
self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
320
def allocate(self, allocator):
321
self.reg1 = allocator.loc_of(self.reg_args[0])
322
self.reg2 = allocator.loc_of(self.reg_args[1])
324
return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
332
class Insn_None__GPR_GPR_GPR(Insn):
333
def __init__(self, methptr, args):
335
self.methptr = methptr
338
self.result_regclass = NO_REGISTER
340
self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER, GP_REGISTER]
341
def allocate(self, allocator):
342
self.reg1 = allocator.loc_of(self.reg_args[0])
343
self.reg2 = allocator.loc_of(self.reg_args[1])
344
self.reg3 = allocator.loc_of(self.reg_args[2])
346
return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
355
def __init__(self, result, source, size, bit):
359
self.result_regclass = GP_REGISTER
360
self.reg_args = [source]
361
self.reg_arg_regclasses = [GP_REGISTER]
362
self.result_reg = None
367
def allocate(self, allocator):
368
self.result_reg = allocator.loc_of(self.result)
369
self.arg_reg = allocator.loc_of(self.reg_args[0])
372
r = "%s@%s"%(self.result, self.result_reg)
376
a = "%s@%s"%(self.reg_args[0], self.arg_reg)
378
a = str(self.reg_args[0])
379
return "<%s-%d extrwi %s, %s, %s, %s>" % (self.__class__.__name__, self._magic_index,
380
r, a, self.size, self.bit)
383
asm.extrwi(self.result_reg.number,
389
def __init__(self, info, result):
393
self.result_reg = None
395
def allocate(self, allocator):
396
self.result_reg = allocator.loc_of(self.result)
397
assert isinstance(self.result_reg, CRF)
398
self.result_reg.set_info(self.info)
401
def __init__(self, info, result, args):
402
CMPInsn.__init__(self, info, result)
403
self.result_regclass = CR_FIELD
405
self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
409
def allocate(self, allocator):
410
CMPInsn.allocate(self, allocator)
411
self.arg_reg1 = allocator.loc_of(self.reg_args[0])
412
self.arg_reg2 = allocator.loc_of(self.reg_args[1])
416
r = "%s@%s"%(self.result, self.result_reg)
420
a1 = "%s@%s"%(self.reg_args[0], self.arg_reg1)
422
a1 = str(self.reg_args[0])
424
a2 = "%s@%s"%(self.reg_args[1], self.arg_reg2)
426
a2 = str(self.reg_args[1])
427
return "<%s-%d %s %s, %s, %s>"%(self.__class__.__name__, self._magic_index,
428
self.__class__.__name__.lower(),
432
asm.cmpw(self.result_reg.number, self.arg_reg1.number, self.arg_reg2.number)
436
asm.cmplw(self.result_reg.number, self.arg_reg1.number, self.arg_reg2.number)
438
class CMPWI(CMPInsn):
439
def __init__(self, info, result, args):
440
CMPInsn.__init__(self, info, result)
442
self.result_regclass = CR_FIELD
443
self.reg_args = [args[0]]
444
self.reg_arg_regclasses = [GP_REGISTER]
447
def allocate(self, allocator):
448
CMPInsn.allocate(self, allocator)
449
self.arg_reg = allocator.loc_of(self.reg_args[0])
453
r = "%s@%s"%(self.result, self.result_reg)
457
a = "%s@%s"%(self.reg_args[0], self.arg_reg)
459
a = str(self.reg_args[0])
460
return "<%s-%d %s %s, %s, (%s)>"%(self.__class__.__name__, self._magic_index,
461
self.__class__.__name__.lower(),
462
r, a, self.imm.value)
464
#print "CMPWI", asm.mc.tell()
465
asm.cmpwi(self.result_reg.number, self.arg_reg.number, self.imm.value)
469
asm.cmplwi(self.result_reg.number, self.arg_reg.number, self.imm.value)
472
## class MTCTR(Insn):
473
## def __init__(self, result, args):
474
## Insn.__init__(self)
475
## self.result = result
476
## self.result_regclass = CT_REGISTER
478
## self.reg_args = args
479
## self.reg_arg_regclasses = [GP_REGISTER]
481
## def allocate(self, allocator):
482
## self.arg_reg = allocator.loc_of(self.reg_args[0])
484
## def emit(self, asm):
485
## asm.mtctr(self.arg_reg.number)
488
def __init__(self, gv_cond, targetbuilder, jump_if_true, jump_args_gv):
490
self.gv_cond = gv_cond
491
self.jump_if_true = jump_if_true
494
self.result_regclass = NO_REGISTER
495
self.reg_args = [gv_cond]
496
self.reg_arg_regclasses = [CR_FIELD]
499
self.jump_args_gv = jump_args_gv
500
self.targetbuilder = targetbuilder
501
def allocate(self, allocator):
502
self.crf = allocator.loc_of(self.reg_args[0])
503
assert self.crf.info[0] != -1
505
assert self.targetbuilder.initial_var2loc is None
506
self.targetbuilder.initial_var2loc = {}
507
from pypy.jit.codegen.ppc.rgenop import Var
508
for gv_arg in self.jump_args_gv:
509
if isinstance(gv_arg, Var):
510
self.targetbuilder.initial_var2loc[gv_arg] = allocator.var2loc[gv_arg]
511
allocator.builders_to_tell_spill_offset_to.append(self.targetbuilder)
513
if self.jump_if_true:
518
a = '%s@%s'%(self.reg_args[0], self.crf)
521
return '<%s-%d %s %s>'%(self.__class__.__name__, self._magic_index,
524
if self.targetbuilder.start:
525
asm.load_word(rSCRATCH, self.targetbuilder.start)
527
self.targetbuilder.patch_start_here = asm.mc.tell()
528
asm.load_word(rSCRATCH, 0)
530
bit, negated = self.crf.info
532
if negated ^ self.jump_if_true:
533
BO = 12 # jump if relavent bit is set in the CR
535
BO = 4 # jump if relavent bit is NOT set in the CR
536
asm.bcctr(BO, self.crf.number*4 + bit)
539
def __init__(self, label):
542
self.reg_arg_regclasses = []
543
self.result_regclass = NO_REGISTER
546
def allocate(self, allocator):
547
for gv in self.label.args_gv:
548
loc = allocator.loc_of(gv)
549
if isinstance(loc, CRF):
550
allocator.forget(gv, loc)
551
allocator.lru.remove(gv)
552
allocator.freeregs[loc.regclass].append(loc.alloc)
553
new_loc = allocator._allocate_reg(GP_REGISTER, gv)
554
allocator.lru.append(gv)
555
allocator.insns.append(loc.move_to_gpr(new_loc.number))
557
self.label.arg_locations = []
558
for gv in self.label.args_gv:
559
loc = allocator.loc_of(gv)
560
self.label.arg_locations.append(loc)
561
allocator.labels_to_tell_spill_offset_to.append(self.label)
563
if hasattr(self.label, 'arg_locations'):
564
arg_locations = '[' + ', '.join(
565
['%s@%s'%(gv, loc) for gv, loc in
566
zip(self.label.args_gv, self.label.arg_locations)]) + ']'
568
arg_locations = str(self.label.args_gv)
569
return '<Label-%s %s>'%(self._magic_index,
572
self.label.startaddr = asm.mc.tell()
574
class LoadFramePointer(Insn):
575
def __init__(self, result):
578
self.reg_arg_regclasses = []
580
self.result_regclass = GP_REGISTER
581
def allocate(self, allocator):
582
self.result_reg = allocator.loc_of(self.result)
584
asm.mr(self.result_reg.number, rFP)
586
class CopyIntoStack(Insn):
587
def __init__(self, place, v):
590
self.reg_arg_regclasses = [GP_REGISTER]
592
self.result_regclass = NO_REGISTER
594
def allocate(self, allocator):
595
self.arg_reg = allocator.loc_of(self.reg_args[0])
596
self.target_slot = allocator.spill_slot()
597
self.place.offset = self.target_slot.offset
599
asm.stw(self.arg_reg.number, rFP, self.target_slot.offset)
601
class CopyOffStack(Insn):
602
def __init__(self, v, place):
605
self.reg_arg_regclasses = []
607
self.result_regclass = GP_REGISTER
609
def allocate(self, allocator):
610
self.result_reg = allocator.loc_of(self.result)
611
allocator.free_stack_slots.append(stack_slot(self.place.offset))
613
asm.lwz(self.result_reg.number, rFP, self.place.offset)
615
class SpillCalleeSaves(Insn):
619
self.reg_arg_regclasses = []
621
self.result_regclass = NO_REGISTER
622
def allocate(self, allocator):
624
callersave = gprs[3:13]
625
for v in allocator.var2loc:
626
loc = allocator.loc_of(v)
627
if loc in callersave:
628
allocator.spill(loc, v)
629
allocator.freeregs[GP_REGISTER].append(loc)
634
def __init__(self, argnumber, arg):
637
self.reg_arg_regclasses = []
639
self.result_regclass = NO_REGISTER
641
self.argnumber = argnumber
643
def allocate(self, allocator):
644
from pypy.jit.codegen.ppc.rgenop import Var
645
if isinstance(self.arg, Var):
646
self.loc = allocator.loc_of(self.arg)
650
if self.argnumber < 8: # magic numbers 'r' us
651
targetreg = 3+self.argnumber
653
self.arg.load_now(asm, gprs[targetreg])
654
elif self.loc.is_register:
655
asm.mr(targetreg, self.loc.number)
657
asm.lwz(targetreg, rFP, self.loc.offset)
659
targetoffset = 24+self.argnumber*4
661
self.arg.load_now(asm, gprs[0])
662
asm.stw(r0, r1, targetoffset)
663
elif self.loc.is_register:
664
asm.stw(self.loc.number, r1, targetoffset)
666
asm.lwz(r0, rFP, self.loc.offset)
667
asm.stw(r0, r1, targetoffset)
670
def __init__(self, result, target):
672
from pypy.jit.codegen.ppc.rgenop import Var
673
if isinstance(target, Var):
674
self.reg_args = [target]
675
self.reg_arg_regclasses = [CT_REGISTER]
678
self.reg_arg_regclasses = []
681
self.result_regclass = GP_REGISTER
682
def allocate(self, allocator):
684
assert allocator.loc_of(self.reg_args[0]) is ctr
685
self.resultreg = allocator.loc_of(self.result)
687
if not self.reg_args:
688
self.target.load_now(asm, gprs[0])
692
if self.resultreg != gprs[3]:
693
asm.mr(self.resultreg.number, 3)
696
class AllocTimeInsn(Insn):
700
self.reg_arg_regclasses = []
701
self.result_regclass = NO_REGISTER
704
class Move(AllocTimeInsn):
705
def __init__(self, dest, src):
706
AllocTimeInsn.__init__(self)
710
asm.mr(self.dest.number, self.src.number)
712
class Load(AllocTimeInsn):
713
def __init__(self, dest, const):
714
AllocTimeInsn.__init__(self)
718
return "<Load-%d %s, (%s)>"%(self._magic_index, self.dest, self.const)
720
self.const.load_now(asm, self.dest)
722
class Unspill(AllocTimeInsn):
723
""" A special instruction inserted by our register "allocator." It
724
indicates that we need to load a value from the stack into a register
725
because we spilled a particular value. """
726
def __init__(self, var, reg, stack):
728
var --- the var we spilled (a Var)
729
reg --- the reg we spilled it from (an integer)
730
offset --- the offset on the stack we spilled it to (an integer)
732
AllocTimeInsn.__init__(self)
736
if not isinstance(self.reg, GPR):
737
assert isinstance(self.reg, CRF) or isinstance(self.reg, CTR)
738
self.moveinsn = self.reg.move_from_gpr(0)
742
return '<Unspill-%d %s: %s, %s>'%(self._magic_index, self.var, self.reg, self.stack)
744
if isinstance(self.reg, GPR):
748
asm.lwz(r, rFP, self.stack.offset)
750
self.moveinsn.emit(asm)
752
class Spill(AllocTimeInsn):
753
""" A special instruction inserted by our register "allocator."
754
It indicates that we need to store a value from the register into
755
the stack because we spilled a particular value."""
756
def __init__(self, var, reg, stack):
758
var --- the var we are spilling (a Var)
759
reg --- the reg we are spilling it from (an integer)
760
offset --- the offset on the stack we are spilling it to (an integer)
762
AllocTimeInsn.__init__(self)
767
return '<Spill-%d %s: %s, %s>'%(self._magic_index, self.var, self.stack, self.reg)
769
if isinstance(self.reg, GPR):
772
assert isinstance(self.reg, CRF)
773
self.reg.move_to_gpr(0).emit(asm)
775
#print 'spilling to', self.stack.offset
776
asm.stw(r, rFP, self.stack.offset)
778
class _CRF2GPR(AllocTimeInsn):
779
def __init__(self, targetreg, bit, negated):
780
AllocTimeInsn.__init__(self)
781
self.targetreg = targetreg
783
self.negated = negated
785
number = self.bit // 4
787
return '<CRF2GPR-%d r%s, crf%s(%s, %s)>' % (
788
self._magic_index, self.targetreg, number, bit, self.negated)
790
asm.mfcr(self.targetreg)
791
asm.extrwi(self.targetreg, self.targetreg, 1, self.bit)
793
asm.xori(self.targetreg, self.targetreg, 1)
795
class _GPR2CRF(AllocTimeInsn):
796
def __init__(self, targetreg, fromreg):
797
AllocTimeInsn.__init__(self)
798
self.targetreg = targetreg
799
self.fromreg = fromreg
801
return '<GPR2CRF-%d %s, r%s>' % (
802
self._magic_index, self.targetreg, self.fromreg)
804
asm.cmpwi(self.targetreg.number, self.fromreg, 0)
806
class _GPR2CTR(AllocTimeInsn):
807
def __init__(self, fromreg):
808
AllocTimeInsn.__init__(self)
809
self.fromreg = fromreg
811
asm.mtctr(self.fromreg)
814
""" Ensures the return value is in r3 """
815
def __init__(self, var):
818
self.reg_args = [self.var]
819
self.reg_arg_regclasses = [GP_REGISTER]
821
self.result_regclass = NO_REGISTER
823
def allocate(self, allocator):
824
self.reg = allocator.loc_of(self.reg_args[0])
826
if self.reg.number != 3:
827
asm.mr(r3, self.reg.number)
830
""" A fake use of a var to get it into a register. And reserving
831
a condition register field."""
832
def __init__(self, rvar, var):
835
self.reg_args = [self.var]
836
self.reg_arg_regclasses = [GP_REGISTER]
838
self.result_regclass = CR_FIELD
839
def allocate(self, allocator):