~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/jit/codegen/ppc/instruction.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
4
rSCRATCH = r0
 
5
rSP = r1
 
6
rFP = r2 # the ABI doesn't specify a frame pointer.  however, we want one
 
7
 
 
8
class AllocationSlot(object):
 
9
    offset = 0
 
10
    number = 0
 
11
    def __init__(self):
 
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
 
15
        # once.
 
16
        self.alloc = self
 
17
 
 
18
    def make_loc(self):
 
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."""
 
23
        return self
 
24
 
 
25
class _StackSlot(AllocationSlot):
 
26
    is_register = False
 
27
    def __init__(self, offset):
 
28
        AllocationSlot.__init__(self)
 
29
        self.offset = offset
 
30
    def __repr__(self):
 
31
        return "stack@%s"%(self.offset,)
 
32
 
 
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)
 
42
    return res
 
43
 
 
44
NO_REGISTER = -1
 
45
GP_REGISTER = 0
 
46
FP_REGISTER = 1
 
47
CR_FIELD = 2
 
48
CT_REGISTER = 3
 
49
 
 
50
class Register(AllocationSlot):
 
51
    is_register = True
 
52
    def __init__(self):
 
53
        AllocationSlot.__init__(self)
 
54
 
 
55
class GPR(Register):
 
56
    regclass = GP_REGISTER
 
57
    def __init__(self, number):
 
58
        Register.__init__(self)
 
59
        self.number = number
 
60
    def __repr__(self):
 
61
        return 'r' + str(self.number)
 
62
gprs = map(GPR, range(32))
 
63
 
 
64
class FPR(Register):
 
65
    regclass = FP_REGISTER
 
66
    def __init__(self, number):
 
67
        Register.__init__(self)
 
68
        self.number = number
 
69
 
 
70
fprs = map(FPR, range(32))
 
71
 
 
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. """
 
78
    regclass = CR_FIELD
 
79
    def __init__(self, number):
 
80
        self.number = number
 
81
        self.alloc = self
 
82
    def make_loc(self):
 
83
        return CRF(self)
 
84
 
 
85
crfs = map(BaseCRF, range(8))
 
86
 
 
87
class CRF(Register):
 
88
    regclass = CR_FIELD
 
89
    def __init__(self, crf):
 
90
        Register.__init__(self)
 
91
        self.alloc = crf
 
92
        self.number = crf.number
 
93
        self.info = (-1,-1) # (bit, negated)
 
94
    def set_info(self, info):
 
95
        assert len(info) == 2
 
96
        self.info = info
 
97
    def make_loc(self):
 
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):
 
104
        # cmp2info['ne']
 
105
        self.set_info((2, 1))
 
106
        return _GPR2CRF(self, gpr)
 
107
    def __repr__(self):
 
108
        return 'crf' + str(self.number) + str(self.info)
 
109
 
 
110
class CTR(Register):
 
111
    regclass = CT_REGISTER
 
112
    def move_from_gpr(self, gpr):
 
113
        return _GPR2CTR(gpr)
 
114
 
 
115
ctr = CTR()
 
116
 
 
117
_insn_index = [0]
 
118
 
 
119
class Insn(object):
 
120
    '''
 
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
 
123
 
 
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
 
126
    '''
 
127
    def __init__(self):
 
128
        self._magic_index = _insn_index[0]
 
129
        _insn_index[0] += 1
 
130
    def __repr__(self):
 
131
        return "<%s %d>" % (self.__class__.__name__, self._magic_index)
 
132
    def emit(self, asm):
 
133
        pass
 
134
 
 
135
class Insn_GPR__GPR_GPR(Insn):
 
136
    def __init__(self, methptr, result, args):
 
137
        Insn.__init__(self)
 
138
        self.methptr = methptr
 
139
 
 
140
        self.result = result
 
141
        self.result_regclass = GP_REGISTER
 
142
        self.reg_args = args
 
143
        self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
 
144
 
 
145
        self.result_reg = None
 
146
        self.arg_reg1 = None
 
147
        self.arg_reg2 = None
 
148
 
 
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])
 
153
 
 
154
    def __repr__(self):
 
155
        if self.result_reg:
 
156
            r = "%s@%s"%(self.result, self.result_reg)
 
157
        else:
 
158
            r = str(self.result)
 
159
        if self.arg_reg1:
 
160
            a1 = "%s@%s"%(self.reg_args[0], self.arg_reg1)
 
161
        else:
 
162
            a1 = str(self.reg_args[0])
 
163
        if self.arg_reg2:
 
164
            a2 = "%s@%s"%(self.reg_args[1], self.arg_reg2)
 
165
        else:
 
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,
 
169
                                          r, a1, a2)
 
170
 
 
171
    def emit(self, asm):
 
172
        self.methptr(asm,
 
173
                     self.result_reg.number,
 
174
                     self.arg_reg1.number,
 
175
                     self.arg_reg2.number)
 
176
 
 
177
class Insn_GPR__GPR_IMM(Insn):
 
178
    def __init__(self, methptr, result, args):
 
179
        Insn.__init__(self)
 
180
        self.methptr = methptr
 
181
        self.imm = args[1]
 
182
 
 
183
        self.result = result
 
184
        self.result_regclass = GP_REGISTER
 
185
        self.reg_args = [args[0]]
 
186
        self.reg_arg_regclasses = [GP_REGISTER]
 
187
        self.result_reg = None
 
188
        self.arg_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])
 
192
    def __repr__(self):
 
193
        if self.result_reg:
 
194
            r = "%s@%s"%(self.result, self.result_reg)
 
195
        else:
 
196
            r = str(self.result)
 
197
        if self.arg_reg:
 
198
            a = "%s@%s"%(self.reg_args[0], self.arg_reg)
 
199
        else:
 
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)
 
204
 
 
205
    def emit(self, asm):
 
206
        self.methptr(asm,
 
207
                     self.result_reg.number,
 
208
                     self.arg_reg.number,
 
209
                     self.imm.value)
 
210
 
 
211
class Insn_GPR__GPR(Insn):
 
212
    def __init__(self, methptr, result, arg):
 
213
        Insn.__init__(self)
 
214
        self.methptr = methptr
 
215
 
 
216
        self.result = result
 
217
        self.result_regclass = GP_REGISTER
 
218
        self.reg_args = [arg]
 
219
        self.reg_arg_regclasses = [GP_REGISTER]
 
220
 
 
221
        self.result_reg = None
 
222
        self.arg_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])
 
226
    def __repr__(self):
 
227
        if self.result_reg:
 
228
            r = "%s@%s"%(self.result, self.result_reg)
 
229
        else:
 
230
            r = str(self.result)
 
231
        if self.arg_reg:
 
232
            a = "%s@%s"%(self.reg_args[0], self.arg_reg)
 
233
        else:
 
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)
 
237
    def emit(self, asm):
 
238
        self.methptr(asm,
 
239
                     self.result_reg.number,
 
240
                     self.arg_reg.number)
 
241
 
 
242
 
 
243
class Insn_GPR(Insn):
 
244
    def __init__(self, methptr, result):
 
245
        Insn.__init__(self)
 
246
        self.methptr = methptr
 
247
 
 
248
        self.result = result
 
249
        self.result_regclass = GP_REGISTER
 
250
        self.reg_args = []
 
251
        self.reg_arg_regclasses = []
 
252
        self.result_reg = None
 
253
    def allocate(self, allocator):
 
254
        self.result_reg = allocator.loc_of(self.result)
 
255
    def __repr__(self):
 
256
        if self.result_reg:
 
257
            r = "%s@%s"%(self.result, self.result_reg)
 
258
        else:
 
259
            r = str(self.result)
 
260
        return "<%s-%d %s %s>" % (self.__class__.__name__, self._magic_index,
 
261
                                  self.methptr.im_func.func_name, r)
 
262
    def emit(self, asm):
 
263
        self.methptr(asm,
 
264
                     self.result_reg.number)
 
265
 
 
266
class Insn_GPR__IMM(Insn):
 
267
    def __init__(self, methptr, result, args):
 
268
        Insn.__init__(self)
 
269
        self.methptr = methptr
 
270
        self.imm = args[0]
 
271
 
 
272
        self.result = result
 
273
        self.result_regclass = GP_REGISTER
 
274
        self.reg_args = []
 
275
        self.reg_arg_regclasses = []
 
276
        self.result_reg = None
 
277
    def allocate(self, allocator):
 
278
        self.result_reg = allocator.loc_of(self.result)
 
279
    def __repr__(self):
 
280
        if self.result_reg:
 
281
            r = "%s@%s"%(self.result, self.result_reg)
 
282
        else:
 
283
            r = str(self.result)
 
284
        return "<%s-%d %s %s, (%s)>" % (self.__class__.__name__, self._magic_index,
 
285
                                        self.methptr.im_func.func_name, r,
 
286
                                        self.imm.value)
 
287
    def emit(self, asm):
 
288
        self.methptr(asm,
 
289
                     self.result_reg.number,
 
290
                     self.imm.value)
 
291
 
 
292
class MoveCRB2GPR(Insn):
 
293
    def __init__(self, result, gv_condition):
 
294
        Insn.__init__(self)
 
295
        self.result = result
 
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])
 
302
    def emit(self, asm):
 
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)
 
307
        if negated:
 
308
            asm.xori(self.targetreg.number, self.targetreg.number, 1)
 
309
 
 
310
class Insn_None__GPR_GPR_IMM(Insn):
 
311
    def __init__(self, methptr, args):
 
312
        Insn.__init__(self)
 
313
        self.methptr = methptr
 
314
        self.imm = args[2]
 
315
 
 
316
        self.result = None
 
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])
 
323
    def __repr__(self):
 
324
        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
 
325
 
 
326
    def emit(self, asm):
 
327
        self.methptr(asm,
 
328
                     self.reg1.number,
 
329
                     self.reg2.number,
 
330
                     self.imm.value)
 
331
 
 
332
class Insn_None__GPR_GPR_GPR(Insn):
 
333
    def __init__(self, methptr, args):
 
334
        Insn.__init__(self)
 
335
        self.methptr = methptr
 
336
 
 
337
        self.result = None
 
338
        self.result_regclass = NO_REGISTER
 
339
        self.reg_args = args
 
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])
 
345
    def __repr__(self):
 
346
        return "<%s %s %d>" % (self.__class__.__name__, self.methptr.im_func.func_name, self._magic_index)
 
347
 
 
348
    def emit(self, asm):
 
349
        self.methptr(asm,
 
350
                     self.reg1.number,
 
351
                     self.reg2.number,
 
352
                     self.reg3.number)
 
353
 
 
354
class Extrwi(Insn):
 
355
    def __init__(self, result, source, size, bit):
 
356
        Insn.__init__(self)
 
357
 
 
358
        self.result = result
 
359
        self.result_regclass = GP_REGISTER
 
360
        self.reg_args = [source]
 
361
        self.reg_arg_regclasses = [GP_REGISTER]
 
362
        self.result_reg = None
 
363
        self.arg_reg = None
 
364
 
 
365
        self.size = size
 
366
        self.bit = bit
 
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])
 
370
    def __repr__(self):
 
371
        if self.result_reg:
 
372
            r = "%s@%s"%(self.result, self.result_reg)
 
373
        else:
 
374
            r = str(self.result)
 
375
        if self.arg_reg:
 
376
            a = "%s@%s"%(self.reg_args[0], self.arg_reg)
 
377
        else:
 
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)
 
381
 
 
382
    def emit(self, asm):
 
383
        asm.extrwi(self.result_reg.number,
 
384
                   self.arg_reg.number,
 
385
                   self.size, self.bit)
 
386
 
 
387
 
 
388
class CMPInsn(Insn):
 
389
    def __init__(self, info, result):
 
390
        Insn.__init__(self)
 
391
        self.info = info
 
392
        self.result = result
 
393
        self.result_reg = None
 
394
 
 
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)
 
399
 
 
400
class CMPW(CMPInsn):
 
401
    def __init__(self, info, result, args):
 
402
        CMPInsn.__init__(self, info, result)
 
403
        self.result_regclass = CR_FIELD
 
404
        self.reg_args = args
 
405
        self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
 
406
        self.arg_reg1 = None
 
407
        self.arg_reg2 = None
 
408
 
 
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])
 
413
 
 
414
    def __repr__(self):
 
415
        if self.result_reg:
 
416
            r = "%s@%s"%(self.result, self.result_reg)
 
417
        else:
 
418
            r = str(self.result)
 
419
        if self.arg_reg1:
 
420
            a1 = "%s@%s"%(self.reg_args[0], self.arg_reg1)
 
421
        else:
 
422
            a1 = str(self.reg_args[0])
 
423
        if self.arg_reg2:
 
424
            a2 = "%s@%s"%(self.reg_args[1], self.arg_reg2)
 
425
        else:
 
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(),
 
429
                                        r, a1, a2)
 
430
 
 
431
    def emit(self, asm):
 
432
        asm.cmpw(self.result_reg.number, self.arg_reg1.number, self.arg_reg2.number)
 
433
 
 
434
class CMPWL(CMPW):
 
435
    def emit(self, asm):
 
436
        asm.cmplw(self.result_reg.number, self.arg_reg1.number, self.arg_reg2.number)
 
437
 
 
438
class CMPWI(CMPInsn):
 
439
    def __init__(self, info, result, args):
 
440
        CMPInsn.__init__(self, info, result)
 
441
        self.imm = args[1]
 
442
        self.result_regclass = CR_FIELD
 
443
        self.reg_args = [args[0]]
 
444
        self.reg_arg_regclasses = [GP_REGISTER]
 
445
        self.arg_reg = None
 
446
 
 
447
    def allocate(self, allocator):
 
448
        CMPInsn.allocate(self, allocator)
 
449
        self.arg_reg = allocator.loc_of(self.reg_args[0])
 
450
 
 
451
    def __repr__(self):
 
452
        if self.result_reg:
 
453
            r = "%s@%s"%(self.result, self.result_reg)
 
454
        else:
 
455
            r = str(self.result)
 
456
        if self.arg_reg:
 
457
            a = "%s@%s"%(self.reg_args[0], self.arg_reg)
 
458
        else:
 
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)
 
463
    def emit(self, asm):
 
464
        #print "CMPWI", asm.mc.tell()
 
465
        asm.cmpwi(self.result_reg.number, self.arg_reg.number, self.imm.value)
 
466
 
 
467
class CMPWLI(CMPWI):
 
468
    def emit(self, asm):
 
469
        asm.cmplwi(self.result_reg.number, self.arg_reg.number, self.imm.value)
 
470
 
 
471
 
 
472
## class MTCTR(Insn):
 
473
##     def __init__(self, result, args):
 
474
##         Insn.__init__(self)
 
475
##         self.result = result
 
476
##         self.result_regclass = CT_REGISTER
 
477
 
 
478
##         self.reg_args = args
 
479
##         self.reg_arg_regclasses = [GP_REGISTER]
 
480
 
 
481
##     def allocate(self, allocator):
 
482
##         self.arg_reg = allocator.loc_of(self.reg_args[0])
 
483
 
 
484
##     def emit(self, asm):
 
485
##         asm.mtctr(self.arg_reg.number)
 
486
 
 
487
class Jump(Insn):
 
488
    def __init__(self, gv_cond, targetbuilder, jump_if_true, jump_args_gv):
 
489
        Insn.__init__(self)
 
490
        self.gv_cond = gv_cond
 
491
        self.jump_if_true = jump_if_true
 
492
 
 
493
        self.result = None
 
494
        self.result_regclass = NO_REGISTER
 
495
        self.reg_args = [gv_cond]
 
496
        self.reg_arg_regclasses = [CR_FIELD]
 
497
        self.crf = None
 
498
 
 
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
 
504
 
 
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)
 
512
    def __repr__(self):
 
513
        if self.jump_if_true:
 
514
            op = 'if_true'
 
515
        else:
 
516
            op = 'if_false'
 
517
        if self.crf:
 
518
            a = '%s@%s'%(self.reg_args[0], self.crf)
 
519
        else:
 
520
            a = self.reg_args[0]
 
521
        return '<%s-%d %s %s>'%(self.__class__.__name__, self._magic_index,
 
522
                                op, a)
 
523
    def emit(self, asm):
 
524
        if self.targetbuilder.start:
 
525
            asm.load_word(rSCRATCH, self.targetbuilder.start)
 
526
        else:
 
527
            self.targetbuilder.patch_start_here = asm.mc.tell()
 
528
            asm.load_word(rSCRATCH, 0)
 
529
        asm.mtctr(rSCRATCH)
 
530
        bit, negated = self.crf.info
 
531
        assert bit != -1
 
532
        if negated ^ self.jump_if_true:
 
533
            BO = 12 # jump if relavent bit is set in the CR
 
534
        else:
 
535
            BO = 4  # jump if relavent bit is NOT set in the CR
 
536
        asm.bcctr(BO, self.crf.number*4 + bit)
 
537
 
 
538
class Label(Insn):
 
539
    def __init__(self, label):
 
540
        Insn.__init__(self)
 
541
        self.reg_args = []
 
542
        self.reg_arg_regclasses = []
 
543
        self.result_regclass =  NO_REGISTER
 
544
        self.result = None
 
545
        self.label = label
 
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))
 
556
                loc = new_loc
 
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)
 
562
    def __repr__(self):
 
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)]) + ']'
 
567
        else:
 
568
            arg_locations = str(self.label.args_gv)
 
569
        return '<Label-%s %s>'%(self._magic_index,
 
570
                                arg_locations)
 
571
    def emit(self, asm):
 
572
        self.label.startaddr = asm.mc.tell()
 
573
 
 
574
class LoadFramePointer(Insn):
 
575
    def __init__(self, result):
 
576
        Insn.__init__(self)
 
577
        self.reg_args = []
 
578
        self.reg_arg_regclasses = []
 
579
        self.result = result
 
580
        self.result_regclass = GP_REGISTER
 
581
    def allocate(self, allocator):
 
582
        self.result_reg = allocator.loc_of(self.result)
 
583
    def emit(self, asm):
 
584
        asm.mr(self.result_reg.number, rFP)
 
585
 
 
586
class CopyIntoStack(Insn):
 
587
    def __init__(self, place, v):
 
588
        Insn.__init__(self)
 
589
        self.reg_args = [v]
 
590
        self.reg_arg_regclasses = [GP_REGISTER]
 
591
        self.result = None
 
592
        self.result_regclass = NO_REGISTER
 
593
        self.place = place
 
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
 
598
    def emit(self, asm):
 
599
        asm.stw(self.arg_reg.number, rFP, self.target_slot.offset)
 
600
 
 
601
class CopyOffStack(Insn):
 
602
    def __init__(self, v, place):
 
603
        Insn.__init__(self)
 
604
        self.reg_args = []
 
605
        self.reg_arg_regclasses = []
 
606
        self.result = v
 
607
        self.result_regclass = GP_REGISTER
 
608
        self.place = place
 
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))
 
612
    def emit(self, asm):
 
613
        asm.lwz(self.result_reg.number, rFP, self.place.offset)
 
614
 
 
615
class SpillCalleeSaves(Insn):
 
616
    def __init__(self):
 
617
        Insn.__init__(self)
 
618
        self.reg_args = []
 
619
        self.reg_arg_regclasses = []
 
620
        self.result = None
 
621
        self.result_regclass = NO_REGISTER
 
622
    def allocate(self, allocator):
 
623
        # cough cough cough
 
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)
 
630
    def emit(self, asm):
 
631
        pass
 
632
 
 
633
class LoadArg(Insn):
 
634
    def __init__(self, argnumber, arg):
 
635
        Insn.__init__(self)
 
636
        self.reg_args = []
 
637
        self.reg_arg_regclasses = []
 
638
        self.result = None
 
639
        self.result_regclass = NO_REGISTER
 
640
 
 
641
        self.argnumber = argnumber
 
642
        self.arg = arg
 
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)
 
647
        else:
 
648
            self.loc = None
 
649
    def emit(self, asm):
 
650
        if self.argnumber < 8: # magic numbers 'r' us
 
651
            targetreg = 3+self.argnumber
 
652
            if self.loc is None:
 
653
                self.arg.load_now(asm, gprs[targetreg])
 
654
            elif self.loc.is_register:
 
655
                asm.mr(targetreg, self.loc.number)
 
656
            else:
 
657
                asm.lwz(targetreg, rFP, self.loc.offset)
 
658
        else:
 
659
            targetoffset = 24+self.argnumber*4
 
660
            if self.loc is None:
 
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)
 
665
            else:
 
666
                asm.lwz(r0, rFP, self.loc.offset)
 
667
                asm.stw(r0, r1, targetoffset)
 
668
 
 
669
class CALL(Insn):
 
670
    def __init__(self, result, target):
 
671
        Insn.__init__(self)
 
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]
 
676
        else:
 
677
            self.reg_args = []
 
678
            self.reg_arg_regclasses = []
 
679
            self.target = target
 
680
        self.result = result
 
681
        self.result_regclass = GP_REGISTER
 
682
    def allocate(self, allocator):
 
683
        if self.reg_args:
 
684
            assert allocator.loc_of(self.reg_args[0]) is ctr
 
685
        self.resultreg = allocator.loc_of(self.result)
 
686
    def emit(self, asm):
 
687
        if not self.reg_args:
 
688
            self.target.load_now(asm, gprs[0])
 
689
            asm.mtctr(0)
 
690
        asm.bctrl()
 
691
        asm.lwz(rFP, rSP, 0)
 
692
        if self.resultreg != gprs[3]:
 
693
            asm.mr(self.resultreg.number, 3)
 
694
 
 
695
 
 
696
class AllocTimeInsn(Insn):
 
697
    def __init__(self):
 
698
        Insn.__init__(self)
 
699
        self.reg_args = []
 
700
        self.reg_arg_regclasses = []
 
701
        self.result_regclass =  NO_REGISTER
 
702
        self.result = None
 
703
 
 
704
class Move(AllocTimeInsn):
 
705
    def __init__(self, dest, src):
 
706
        AllocTimeInsn.__init__(self)
 
707
        self.dest = dest
 
708
        self.src = src
 
709
    def emit(self, asm):
 
710
        asm.mr(self.dest.number, self.src.number)
 
711
 
 
712
class Load(AllocTimeInsn):
 
713
    def __init__(self, dest, const):
 
714
        AllocTimeInsn.__init__(self)
 
715
        self.dest = dest
 
716
        self.const = const
 
717
    def __repr__(self):
 
718
        return "<Load-%d %s, (%s)>"%(self._magic_index, self.dest, self.const)
 
719
    def emit(self, asm):
 
720
        self.const.load_now(asm, self.dest)
 
721
 
 
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):
 
727
        """
 
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)
 
731
        """
 
732
        AllocTimeInsn.__init__(self)
 
733
        self.var = var
 
734
        self.reg = reg
 
735
        self.stack = stack
 
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)
 
739
        else:
 
740
            self.moveinsn = None
 
741
    def __repr__(self):
 
742
        return '<Unspill-%d %s: %s, %s>'%(self._magic_index, self.var, self.reg, self.stack)
 
743
    def emit(self, asm):
 
744
        if isinstance(self.reg, GPR):
 
745
            r = self.reg.number
 
746
        else:
 
747
            r = 0
 
748
        asm.lwz(r, rFP, self.stack.offset)
 
749
        if self.moveinsn:
 
750
            self.moveinsn.emit(asm)
 
751
 
 
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):
 
757
        """
 
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)
 
761
        """
 
762
        AllocTimeInsn.__init__(self)
 
763
        self.var = var
 
764
        self.reg = reg
 
765
        self.stack = stack
 
766
    def __repr__(self):
 
767
        return '<Spill-%d %s: %s, %s>'%(self._magic_index, self.var, self.stack, self.reg)
 
768
    def emit(self, asm):
 
769
        if isinstance(self.reg, GPR):
 
770
            r = self.reg.number
 
771
        else:
 
772
            assert isinstance(self.reg, CRF)
 
773
            self.reg.move_to_gpr(0).emit(asm)
 
774
            r = 0
 
775
        #print 'spilling to', self.stack.offset
 
776
        asm.stw(r, rFP, self.stack.offset)
 
777
 
 
778
class _CRF2GPR(AllocTimeInsn):
 
779
    def __init__(self, targetreg, bit, negated):
 
780
        AllocTimeInsn.__init__(self)
 
781
        self.targetreg = targetreg
 
782
        self.bit = bit
 
783
        self.negated = negated
 
784
    def __repr__(self):
 
785
        number = self.bit // 4
 
786
        bit = self.bit % 4
 
787
        return '<CRF2GPR-%d r%s, crf%s(%s, %s)>' % (
 
788
            self._magic_index, self.targetreg, number, bit, self.negated)
 
789
    def emit(self, asm):
 
790
        asm.mfcr(self.targetreg)
 
791
        asm.extrwi(self.targetreg, self.targetreg, 1, self.bit)
 
792
        if self.negated:
 
793
            asm.xori(self.targetreg, self.targetreg, 1)
 
794
 
 
795
class _GPR2CRF(AllocTimeInsn):
 
796
    def __init__(self, targetreg, fromreg):
 
797
        AllocTimeInsn.__init__(self)
 
798
        self.targetreg = targetreg
 
799
        self.fromreg = fromreg
 
800
    def __repr__(self):
 
801
        return '<GPR2CRF-%d %s, r%s>' % (
 
802
            self._magic_index, self.targetreg, self.fromreg)
 
803
    def emit(self, asm):
 
804
        asm.cmpwi(self.targetreg.number, self.fromreg, 0)
 
805
 
 
806
class _GPR2CTR(AllocTimeInsn):
 
807
    def __init__(self, fromreg):
 
808
        AllocTimeInsn.__init__(self)
 
809
        self.fromreg = fromreg
 
810
    def emit(self, asm):
 
811
        asm.mtctr(self.fromreg)
 
812
 
 
813
class Return(Insn):
 
814
    """ Ensures the return value is in r3 """
 
815
    def __init__(self, var):
 
816
        Insn.__init__(self)
 
817
        self.var = var
 
818
        self.reg_args = [self.var]
 
819
        self.reg_arg_regclasses = [GP_REGISTER]
 
820
        self.result = None
 
821
        self.result_regclass = NO_REGISTER
 
822
        self.reg = None
 
823
    def allocate(self, allocator):
 
824
        self.reg = allocator.loc_of(self.reg_args[0])
 
825
    def emit(self, asm):
 
826
        if self.reg.number != 3:
 
827
            asm.mr(r3, self.reg.number)
 
828
 
 
829
class FakeUse(Insn):
 
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):
 
833
        Insn.__init__(self)
 
834
        self.var = var
 
835
        self.reg_args = [self.var]
 
836
        self.reg_arg_regclasses = [GP_REGISTER]
 
837
        self.result = rvar
 
838
        self.result_regclass = CR_FIELD
 
839
    def allocate(self, allocator):
 
840
        pass
 
841
    def emit(self, asm):
 
842
        pass