summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_asm.h
blob: dd586706d1377747f1ae269a5a700a1d03171a6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
#ifndef __PPE42_ASM_H__
#define __PPE42_ASM_H__
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file ppe42_asm.h
/// \brief Generic assembler macros for 32-bit PPE42

// Doxygen is confused by assembler; the best I know how to make it
// work is to put all of the documentation at the beginning like below
// and effectively comment out the code using Doxygen cond/endcond.

/// \page ppe42_asm Generic assembler macros for 32-bit PPE42
///
///
/// \section _lxzi _l<w,h,b>zi - Load register and Zero from Immediate address
///
/// These macros encapsulate the 2-instruction sequence required to
/// load from a 32-bit immediate address.
///
/// \arg \c dreg A register to receive the load data.
/// \arg \c areg A register to hold the immediate address.  This can \e
///              not be register 0. Note that if \a areg != \a dreg
///              then \a areg will contain the address at the end of
///              the macro sequence.
/// \arg \c addr A 32-bit immediate address, which may be either an
///         absolute or relocatable expression.
///
/// Forms:
/// 
/// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n
/// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n
/// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n
/// 
///
/// \section _stxi _st<w,h,b>i - STore register to Immediate address
///
/// These macros encapsulate the 2-instruction sequence required to
/// store to a 32-bit immediate address.
///
/// \arg \c dreg The register to store.
/// \arg \c areg A register to hold the immediate address.  This can \e
///              not be register 0, and can not be the same as \a dreg.
///              Note that \a areg will contain the address at the end of
///              the macro sequence.
/// \arg \c addr A 32-bit immediate address, which may be either an
///         absolute or relocatable expression.
///
/// Forms:
/// 
/// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n
/// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n
/// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n
///
///
/// \section _lstzsd _<l,st><w,h,b><z>sd - Load/STore register from/to Small Data area
///
/// These macros encapulate the small data area relocations for access
/// to storage in the small data sections .sbss, .sdata, .sbss2 and
/// .sdata2.  Use of these macros implies small data area support in
/// the compile environment (for variables shared between compiled and
/// assembled code) and initialization code that sets up the small data
/// area registers R13 (and optionally R2).
///
/// The relocations generated by this macro will work for both SVR4 ABI
/// and EABI environments.  In particular, for EABI environments
/// the link editor will insert offsets to either R13 or R2 depending
/// on the section of the symbol.
///
/// \arg \c dreg The register to load or store.
/// \arg \c addr A 32-bit immediate address, assumed to be a
///              relocatable address in one of the small data sections.
///
/// Forms:      
/// 
/// \b _lbzsd \a dreg, \a addr  - Load Byte and Zero from Small Data area \n
/// \b _lhzsd \a dreg, \a addr  - Load Halfword and Zero from Small Data area \n
/// \b _lwzsd \a dreg, \a addr  - Load Word and Zero from Small Data area \n
/// \b _stbsd \a dreg, \a addr  - STore Byte to Small Data area \n
/// \b _sthsd \a dreg, \a addr  - STore Halfword to Small Data area \n
/// \b _stwsd \a dreg, \a addr  - STore Word to Small Data area \n
///
///
/// \section _liw _liw<a> - Load Immediate Word (Absolute)
///
/// These macros encapsulate the two instructions required to load a
/// 32-bit immediate value into a register.  If the immediate is an
/// absolute expression, then the \c 'a' form may be able to optimize
/// to a single instruction depending on whether only the high- or
/// low-order bits of the immediate are non-zero.
///
/// Forms:
///
/// \b _liw  \a rd, \a imm - Load register \a rd with the 32-bit immediate \a imm \n
/// \b _liwa \a rd, \a imm - Load register \a rd with the 32-bit absolute immediate \a imm \n
///
///
/// \section _oriwa _oriwa - OR Immediate Word Absolute
///
/// This macro encapsulates the logical OR of a 32-bit immediate with a
/// register. The immediate value must be an absolute expression.
///
/// The PowerPC has instructions for OR-ing 16-bit immediates into the
/// upper (\c oris) and lower (\c ori) portions of a register.  This
/// macro optimizes the generated code based on which bits (if any) of
/// the absolte immediate are non-zero.
///
/// This special macro is only provided for the OR function. For other
/// logical operations and recording forms it is necessary in general
/// to first load the 32-bit immediate into a register (e.g., with \c
/// _liwa) then perform the logical operation.
///
/// \arg \c rd The destination register; at the end will contain \c rs
///            OR \a imm
/// \arg \c rs The source register.
/// \arg \c imm 32-bit absolute expression.
///
/// Forms:
///
/// \b _oriwa \a rd, \a rs, \a imm - \a rd gets \a rs OR \a imm \n
///
///
/// \section _incr64_fast - 64-bit increment for fast interrupt handlers
///
/// This macros implements 64-bit counter update in fast interrupt handlers
/// which are forbidden from using the carry-bit in the XER (without
/// saving/restoring it.)
///
/// \arg \c rs Scratch register
/// \arg \c ra Register containing the counter address at entry
///
/// \a rs and \a ra must be unique.  At the end of the macro the count
/// is updated to memory and \a ra is unmodified. 
///        
///
/// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions
///
///  There are situations where it is easier/faster to clear individual bits
///  and bit fields, set bits or copy fields, based on immediate bit numbers
///  and locations, rather than loading masks, since setting up a mask
///  requires 2 instruction in general, whereas these macros generate a single
///  instruction.
///
/// \arg \c rd - The destination register
/// \arg \c rs - The source register
/// \arg \c n - An immediate size of a bit field, in the range 0 to 32
/// \arg \c b - An immediate big-endian bit number in the range 0 to 31
///
/// Forms:
///
/// \b _clrfield \a rd, \a rs, \a n, \a b - Clear an \a n bit field from \a rs
/// to \a rd starting from bit \a b \n
/// \b _clrbit \a rd, \a rs, \a b - Clear bit \a b \n
/// \b _setbit \a rd, \a rs, \a b - Set bit \a b \n
/// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to
/// \a rd starting from bit \a b \n
///
///     
/// \section pseudo_ops Assembler Pseudo-Ops Macros
///
/// Several macros define new 'pseudo-ops'.
///
/// \subsection cache_align .cache_align
///
/// The \c .cache_align pseudo-op is used to force alignment on a
/// cache-line boundary.  It requires a preprocessor symbol definition for
/// \c LOG_CACHE_LINE_SIZE
///
/// Forms:
///
/// \b .cache_align \n
///
///
/// \subsection global_function Local and Global Functions
///
/// The \c .function and \c .global_function pseudo-ops define function
/// symbols in the \c .text section.
///
/// Forms:
///
/// \b .function \a symbol - Define a local function \a symbol \n
/// \b .global_function \a symbol - Define a global function \a symbol \n
///
/// 
/// \subsection epilogue .epilogue
///
/// The \c .epilogue pseudo-op adds size and type information for
/// functions defined in assembler.
///
/// \arg \c symbol - Assembler epilogue for the function \a symbol.
///
/// Forms:
///
/// \b .epilogue \a symbol \n
///
///
/// \cond

#ifdef __ASSEMBLER__


### ****************************************************************************
### _l<b,h,w>zi
### _st<b,h,w>i
### ****************************************************************************

        .macro  _lbzi dreg, areg, addr
        lis     \areg, \addr@ha
        .ifc    \areg, \dreg
        lbz     \dreg, \addr@l(\areg)
        .else
        lbzu    \dreg, \addr@l(\areg)
        .endif
        .endm
        
        .macro  _lhzi dreg, areg, addr
        lis     \areg, \addr@ha
        .ifc    \areg, \dreg
        lhz     \dreg, \addr@l(\areg)
        .else
        lhzu    \dreg, \addr@l(\areg)
        .endif
        .endm
        
        .macro  _lwzi dreg, areg, addr
        lis     \areg, \addr@ha
        .ifc    \areg, \dreg
        lwz     \dreg, \addr@l(\areg)
        .else
        lwzu    \dreg, \addr@l(\areg)
        .endif
        .endm

        .macro  _stbi dreg, areg, addr
        .ifc    \areg, \dreg
        .err
        .endif
        lis     \areg, \addr@ha
        stbu    \dreg, \addr@l(\areg)
        .endm
        
        .macro  _sthi dreg, areg, addr
        .ifc    \areg, \dreg
        .err
        .endif
        lis     \areg, \addr@ha
        sthu    \dreg, \addr@l(\areg)
        .endm
        
        .macro  _stwi dreg, areg, addr
        .ifc    \areg, \dreg
        .err
        .endif
        lis     \areg, \addr@ha
        stwu    \dreg, \addr@l(\areg)
        .endm


### ****************************************************************************
### _l<b,h,w>zsd
### _st<b,h,w>sd
### ****************************************************************************

        .macro  _lbzsd  dreg, addr
        lbz     \dreg, \addr@sda21(0)
        .endm

        .macro  _lhzsd  dreg, addr
        lhz     \dreg, \addr@sda21(0)
        .endm

        .macro  _lwzsd  dreg, addr
        lwz     \dreg, \addr@sda21(0)
        .endm

        .macro  _stbsd  dreg, addr
        stb     \dreg, \addr@sda21(0)
        .endm

        .macro  _sthsd  dreg, addr
        sth     \dreg, \addr@sda21(0)
        .endm

        .macro  _stwsd  dreg, addr
        stw     \dreg, \addr@sda21(0)
        .endm


### ****************************************************************************
### _liw<a>
### _oriwa
### ****************************************************************************

        .macro  _liw    rd, imm
        lis     \rd, \imm@h
        ori     \rd, \rd, \imm@l
        .endm

        .macro  _liwa   rd, imm
        .if     (\imm & 0xffff0000)
        lis     \rd, \imm@h
                .if     (\imm & 0xffff)
                ori     \rd, \rd, \imm@l
                .endif
        .else
        li      \rd, \imm@l
        .endif
        .endm

        .macro  _oriwa  rd, rs, imm
        .if     (\imm & 0xffff0000)
        oris    \rd, \rs, \imm@h
                .if     (\imm & 0xffff)
                ori     \rd, \rd, \imm@l
                .endif
        .else
        ori     \rd, \rs, \imm@l
        .endif
        .endm

### ****************************************************************************
### _incr64_fast
### ****************************************************************************

        .macro  _incr64_fast, rs:req, ra:req

        lwz     \rs, 4(\ra)
        addi    \rs, \rs, 1
        cmpwi   \rs, 0
        stw     \rs, 4(\ra)
        bne     233643278f

        lwz     \rs, 0(\ra)
        addi    \rs, \rs, 1
        stw     \rs, 0(\ra)
233643278:              

        .endm        

### ****************************************************************************
### _clrfield
### _clrbit
### _setbit
### _copyfield
### ****************************************************************************

        .macro  _clrfield, rd, rs, n, b
        rlwinm   \rd, \rs, 0, (\b + \n) & 0x1f, (\b - 1) & 0x1f
        .endm           

        .macro  _clrbit, rd, rs, b
        _clrfield \rd, \rs, 1, \b
        .endm

        .macro  _setbit, rd, rs, b
        .ifle   \b - 15
        oris    \rd, \rs, 1 << (15 - \b)
        .else
        ori     \rd, \rs, 1 << (31 - \b)
        .endif
        .endm

        .macro  _copyfield, rd, rs, n, b
        rlwimi  \rd, \rs, 0, \b , (\b + \n - 1)
        .endm

### ****************************************************************************
### .cache_align
### .<global_>function
### .epilogue
### ****************************************************************************

        .set    _log_cache_line_size, LOG_CACHE_LINE_SIZE

        .macro  .cache_align
        .align  _log_cache_line_size
        .endm

        .macro  .function symbol
        .text
        .align  2
        .endm

        .macro  .global_function symbol
        .text
        .align  2
        .global \symbol
        .endm

        .macro .epilogue symbol
        .type   \symbol, @function
        .size   \symbol, . - \symbol
        .endm           

### ***************************************************************************
###                                 64-bit macros
### ***************************************************************************

### ***************************************************************************
### Using symbols for register names makes the code more readable and allows
### us to do register arithmetic within macros.
### ***************************************************************************

.equiv  r0, 0
.equiv  r1, 1
.equiv  sp, 1
.equiv  r3, 3
.equiv  r4, 4
.equiv  r5, 5
.equiv  r6, 6
.equiv  r7, 7
.equiv  r8, 8
.equiv  r9, 9
.equiv  r10, 10

.equiv  r28, 28
.equiv  r29, 29
.equiv  r30, 30
.equiv  r31, 31

.equiv  d3, 3
.equiv  d4, 4
.equiv  d5, 5
.equiv  d6, 6
.equiv  d7, 7
.equiv  d8, 8
.equiv  d9, 9
.equiv  d10, 10
.equiv  d28, 28
.equiv  d29, 29
.equiv  d30, 30
.equiv  d31, 31

### ***************************************************************************
### Load virtual doubleword generic. Load a virtual doubleword from a relocatable
### address expression. If the optional RA is specified, the address remains in
### RA.
### ***************************************************************************
.macro _lvdg DT:req addr:req RA=-1
    .if \RA == -1
        lis     \DT, (\addr)@ha
        lvd     \DT, (\addr)@l(\DT)
    .else
        lis     \RA, (\addr)@ha
        lvdu    \DT, (\addr)@l(\RA)
    .endif
.endm

### ***************************************************************************
### Load virtual doubleword from a relocatable small data area address
### ***************************************************************************
.macro _lvdsd DT:req addr:req
    lvd     \DT, (\addr)@sda21(0)
.endm

### ***************************************************************************
### Store virtual doubleword generic. Store a virtual doubleword based on a
### relocatable address expression. The address remains in RA.
### ***************************************************************************
.macro _stvdg DS:req addr:req RA:req
    lis     \RA, (\addr)@ha
    stvdu   \DS, (\addr)@l(\RA)
.endm

### ***************************************************************************
### Store virtual doubleword to a relocatable small data address expression
### ***************************************************************************
.macro _stvdsd DS:req addr:req
    stvd    \DS, (\addr)@sda21(0)
.endm

### ***************************************************************************
###  Load virtual doubleword absolute. Set DT to an absolute 64-bit constant
### ***************************************************************************
.macro _lvda DT, cvalue
    lwa (\DT + 1)%32, (\cvalue) & 0x00000000ffffffff
    lwa \DT, (\cvalue) >> 32
.endm

### ***************************************************************************
###
###                         64-bit arithmetic macros
###
### ***************************************************************************

.macro check_overlap2 DA, DB
    .if ((\DA - \DB) % 32) == 1 || ((\DA - \DB) % 32) == -1
        .error "virtual doubleword registers must be identical or non-overlapping"
    .endif
.endm

.macro check_overlap3 DA, DB, DC
    check_overlap2 \DA, \DB
    check_overlap2 \DA, \DC
    check_overlap2 \DB, \DC
.endm

### ***************************************************************************
###  Add virtual doubleword carrying
### ***************************************************************************
.macro _addvdc   DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    addc    (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    adde    \DT, \DA, \DB
.endm

### ***************************************************************************
###  Add virtual doubleword to signed 16-bit immediate carrying
### ***************************************************************************
.macro _addvdic  DT, DA, SI
    .if \DA == 31
        .error "d31 for addend register is not supported"
    .endif
    check_overlap2 \DT, \DA
    addi    (\DT+1)%32, \DA+1, SI
    addze   \DT, \DA
.endm

### ***************************************************************************
###  Add virtual doubleword to unsigned word carrying
### ***************************************************************************
.macro _addvdwuc DT, DA, RB
    check_overlap2 \DT, \DA
    addc    (\DT+1)%32, (\DA+1)%32, \RB
    addze   \DT, \DA
.endm

### ***************************************************************************
###  Subtract virtual doubleword carrying
### ***************************************************************************
.macro _subvdc   DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    subfc   (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    subfe   \DT, \DA, \DB
.endm

### ***************************************************************************
### 
###                             64-bit logic macros
### 
### ***************************************************************************

### ***************************************************************************
###  AND virtual doubleword
### ***************************************************************************
.macro _andvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    and (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    and \DT, \DA, \DB
.endm

### ***************************************************************************
###  ANDC virtual doubleword
### ***************************************************************************
.macro _andcvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    andc    (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    andc    \DT, \DA, \DB
.endm

### ***************************************************************************
###  EQV virtual doubleword
### ***************************************************************************
.macro _eqvvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    eqv (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    eqv \DT, \DA, \DB
.endm

### ***************************************************************************
###  OR virtual doubleword
### ***************************************************************************
.macro _orvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    or (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    or \DT, \DA, \DB
.endm

### ***************************************************************************
###  ORC virtual doubleword
### ***************************************************************************
.macro _orcvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    orc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    orc \DT, \DA, \DB
.endm

### ***************************************************************************
###  XOR virtual doubleword
### ***************************************************************************
.macro _xorvd DT, DA, DB
    check_overlap3 \DT, \DA, \DB
    xor (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
    xor \DT, \DA, \DB
.endm

#endif /* __ASSEMBLER__ */

/// \endcond
        
// Local Variables:
// mode:asm
// End:
        
#endif /* __PPE42_ASM_H__ */
OpenPOWER on IntegriCloud