• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright (C) 2008 Tungsten Graphics, Inc.   All Rights Reserved.
4  * Copyright (C) 2009 VMware, Inc.  All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 
25 /**
26  * PPC code generation.
27  * For reference, see http://www.power.org/resources/reading/PowerISA_V2.05.pdf
28  * ABI info: http://www.cs.utsa.edu/~whaley/teach/cs6463FHPO/LEC/lec12_ho.pdf
29  *
30  * Other PPC refs:
31  * http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
32  * http://www.ibm.com/developerworks/eserver/library/es-archguide-v2.html
33  * http://www.freescale.com/files/product/doc/MPCFPE32B.pdf
34  *
35  * \author Brian Paul
36  */
37 
38 
39 #include <stdio.h>
40 #include "util/u_memory.h"
41 #include "util/u_debug.h"
42 #include "rtasm_execmem.h"
43 #include "rtasm_ppc.h"
44 
45 
46 void
ppc_init_func(struct ppc_function * p)47 ppc_init_func(struct ppc_function *p)
48 {
49    uint i;
50 
51    memset(p, 0, sizeof(*p));
52 
53    p->num_inst = 0;
54    p->max_inst = 100; /* first guess at buffer size */
55    p->store = rtasm_exec_malloc(p->max_inst * PPC_INST_SIZE);
56    p->reg_used = 0x0;
57    p->fp_used = 0x0;
58    p->vec_used = 0x0;
59 
60    p->print = FALSE;
61    p->indent = 0;
62 
63    /* only allow using gp registers 3..12 for now */
64    for (i = 0; i < 3; i++)
65       ppc_reserve_register(p, i);
66    for (i = 12; i < PPC_NUM_REGS; i++)
67       ppc_reserve_register(p, i);
68 }
69 
70 
71 void
ppc_release_func(struct ppc_function * p)72 ppc_release_func(struct ppc_function *p)
73 {
74    assert(p->num_inst <= p->max_inst);
75    if (p->store != NULL) {
76       rtasm_exec_free(p->store);
77    }
78    p->store = NULL;
79 }
80 
81 
82 uint
ppc_num_instructions(const struct ppc_function * p)83 ppc_num_instructions(const struct ppc_function *p)
84 {
85    return p->num_inst;
86 }
87 
88 
ppc_get_func(struct ppc_function * p)89 void (*ppc_get_func(struct ppc_function *p))(void)
90 {
91 #if 0
92    DUMP_END();
93    if (DISASSEM && p->store)
94       debug_printf("disassemble %p %p\n", p->store, p->csr);
95 
96    if (p->store == p->error_overflow)
97       return (void (*)(void)) NULL;
98    else
99 #endif
100       return (void (*)(void)) pointer_to_func(p->store);
101 }
102 
103 
104 void
ppc_dump_func(const struct ppc_function * p)105 ppc_dump_func(const struct ppc_function *p)
106 {
107    uint i;
108    for (i = 0; i < p->num_inst; i++) {
109       debug_printf("%3u: 0x%08x\n", i, p->store[i]);
110    }
111 }
112 
113 
114 void
ppc_print_code(struct ppc_function * p,boolean enable)115 ppc_print_code(struct ppc_function *p, boolean enable)
116 {
117    p->print = enable;
118 }
119 
120 
121 void
ppc_indent(struct ppc_function * p,int spaces)122 ppc_indent(struct ppc_function *p, int spaces)
123 {
124    p->indent += spaces;
125 }
126 
127 
128 static void
indent(const struct ppc_function * p)129 indent(const struct ppc_function *p)
130 {
131    int i;
132    for (i = 0; i < p->indent; i++) {
133       putchar(' ');
134    }
135 }
136 
137 
138 void
ppc_comment(struct ppc_function * p,int rel_indent,const char * s)139 ppc_comment(struct ppc_function *p, int rel_indent, const char *s)
140 {
141    if (p->print) {
142       p->indent += rel_indent;
143       indent(p);
144       p->indent -= rel_indent;
145       printf("# %s\n", s);
146    }
147 }
148 
149 
150 /**
151  * Mark a register as being unavailable.
152  */
153 int
ppc_reserve_register(struct ppc_function * p,int reg)154 ppc_reserve_register(struct ppc_function *p, int reg)
155 {
156    assert(reg < PPC_NUM_REGS);
157    p->reg_used |= (1 << reg);
158    return reg;
159 }
160 
161 
162 /**
163  * Allocate a general purpose register.
164  * \return register index or -1 if none left.
165  */
166 int
ppc_allocate_register(struct ppc_function * p)167 ppc_allocate_register(struct ppc_function *p)
168 {
169    unsigned i;
170    for (i = 0; i < PPC_NUM_REGS; i++) {
171       const uint32_t mask = 1 << i;
172       if ((p->reg_used & mask) == 0) {
173          p->reg_used |= mask;
174          return i;
175       }
176    }
177    printf("OUT OF PPC registers!\n");
178    return -1;
179 }
180 
181 
182 /**
183  * Mark the given general purpose register as "unallocated".
184  */
185 void
ppc_release_register(struct ppc_function * p,int reg)186 ppc_release_register(struct ppc_function *p, int reg)
187 {
188    assert(reg < PPC_NUM_REGS);
189    assert(p->reg_used & (1 << reg));
190    p->reg_used &= ~(1 << reg);
191 }
192 
193 
194 /**
195  * Allocate a floating point register.
196  * \return register index or -1 if none left.
197  */
198 int
ppc_allocate_fp_register(struct ppc_function * p)199 ppc_allocate_fp_register(struct ppc_function *p)
200 {
201    unsigned i;
202    for (i = 0; i < PPC_NUM_FP_REGS; i++) {
203       const uint32_t mask = 1 << i;
204       if ((p->fp_used & mask) == 0) {
205          p->fp_used |= mask;
206          return i;
207       }
208    }
209    printf("OUT OF PPC FP registers!\n");
210    return -1;
211 }
212 
213 
214 /**
215  * Mark the given floating point register as "unallocated".
216  */
217 void
ppc_release_fp_register(struct ppc_function * p,int reg)218 ppc_release_fp_register(struct ppc_function *p, int reg)
219 {
220    assert(reg < PPC_NUM_FP_REGS);
221    assert(p->fp_used & (1 << reg));
222    p->fp_used &= ~(1 << reg);
223 }
224 
225 
226 /**
227  * Allocate a vector register.
228  * \return register index or -1 if none left.
229  */
230 int
ppc_allocate_vec_register(struct ppc_function * p)231 ppc_allocate_vec_register(struct ppc_function *p)
232 {
233    unsigned i;
234    for (i = 0; i < PPC_NUM_VEC_REGS; i++) {
235       const uint32_t mask = 1 << i;
236       if ((p->vec_used & mask) == 0) {
237          p->vec_used |= mask;
238          return i;
239       }
240    }
241    printf("OUT OF PPC VEC registers!\n");
242    return -1;
243 }
244 
245 
246 /**
247  * Mark the given vector register as "unallocated".
248  */
249 void
ppc_release_vec_register(struct ppc_function * p,int reg)250 ppc_release_vec_register(struct ppc_function *p, int reg)
251 {
252    assert(reg < PPC_NUM_VEC_REGS);
253    assert(p->vec_used & (1 << reg));
254    p->vec_used &= ~(1 << reg);
255 }
256 
257 
258 /**
259  * Append instruction to instruction buffer.  Grow buffer if out of room.
260  */
261 static void
emit_instruction(struct ppc_function * p,uint32_t inst_bits)262 emit_instruction(struct ppc_function *p, uint32_t inst_bits)
263 {
264    if (!p->store)
265       return;  /* out of memory, drop the instruction */
266 
267    if (p->num_inst == p->max_inst) {
268       /* allocate larger buffer */
269       uint32_t *newbuf;
270       p->max_inst *= 2;  /* 2x larger */
271       newbuf = rtasm_exec_malloc(p->max_inst * PPC_INST_SIZE);
272       if (newbuf) {
273          memcpy(newbuf, p->store, p->num_inst * PPC_INST_SIZE);
274       }
275       rtasm_exec_free(p->store);
276       p->store = newbuf;
277       if (!p->store) {
278          /* out of memory */
279          p->num_inst = 0;
280          return;
281       }
282    }
283 
284    p->store[p->num_inst++] = inst_bits;
285 }
286 
287 
288 union vx_inst {
289    uint32_t bits;
290    struct {
291       unsigned op:6;
292       unsigned vD:5;
293       unsigned vA:5;
294       unsigned vB:5;
295       unsigned op2:11;
296    } inst;
297 };
298 
299 static INLINE void
emit_vx(struct ppc_function * p,uint op2,uint vD,uint vA,uint vB,const char * format,boolean transpose)300 emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB,
301         const char *format, boolean transpose)
302 {
303    union vx_inst inst;
304    inst.inst.op = 4;
305    inst.inst.vD = vD;
306    inst.inst.vA = vA;
307    inst.inst.vB = vB;
308    inst.inst.op2 = op2;
309    emit_instruction(p, inst.bits);
310    if (p->print) {
311       indent(p);
312       if (transpose)
313          printf(format, vD, vB, vA);
314       else
315          printf(format, vD, vA, vB);
316    }
317 }
318 
319 
320 union vxr_inst {
321    uint32_t bits;
322    struct {
323       unsigned op:6;
324       unsigned vD:5;
325       unsigned vA:5;
326       unsigned vB:5;
327       unsigned rC:1;
328       unsigned op2:10;
329    } inst;
330 };
331 
332 static INLINE void
emit_vxr(struct ppc_function * p,uint op2,uint vD,uint vA,uint vB,const char * format)333 emit_vxr(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB,
334          const char *format)
335 {
336    union vxr_inst inst;
337    inst.inst.op = 4;
338    inst.inst.vD = vD;
339    inst.inst.vA = vA;
340    inst.inst.vB = vB;
341    inst.inst.rC = 0;
342    inst.inst.op2 = op2;
343    emit_instruction(p, inst.bits);
344    if (p->print) {
345       indent(p);
346       printf(format, vD, vA, vB);
347    }
348 }
349 
350 
351 union va_inst {
352    uint32_t bits;
353    struct {
354       unsigned op:6;
355       unsigned vD:5;
356       unsigned vA:5;
357       unsigned vB:5;
358       unsigned vC:5;
359       unsigned op2:6;
360    } inst;
361 };
362 
363 static INLINE void
emit_va(struct ppc_function * p,uint op2,uint vD,uint vA,uint vB,uint vC,const char * format)364 emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC,
365         const char *format)
366 {
367    union va_inst inst;
368    inst.inst.op = 4;
369    inst.inst.vD = vD;
370    inst.inst.vA = vA;
371    inst.inst.vB = vB;
372    inst.inst.vC = vC;
373    inst.inst.op2 = op2;
374    emit_instruction(p, inst.bits);
375    if (p->print) {
376       indent(p);
377       printf(format, vD, vA, vB, vC);
378    }
379 }
380 
381 
382 union i_inst {
383    uint32_t bits;
384    struct {
385       unsigned op:6;
386       unsigned li:24;
387       unsigned aa:1;
388       unsigned lk:1;
389    } inst;
390 };
391 
392 static INLINE void
emit_i(struct ppc_function * p,uint op,uint li,uint aa,uint lk)393 emit_i(struct ppc_function *p, uint op, uint li, uint aa, uint lk)
394 {
395    union i_inst inst;
396    inst.inst.op = op;
397    inst.inst.li = li;
398    inst.inst.aa = aa;
399    inst.inst.lk = lk;
400    emit_instruction(p, inst.bits);
401 }
402 
403 
404 union xl_inst {
405    uint32_t bits;
406    struct {
407       unsigned op:6;
408       unsigned bo:5;
409       unsigned bi:5;
410       unsigned unused:3;
411       unsigned bh:2;
412       unsigned op2:10;
413       unsigned lk:1;
414    } inst;
415 };
416 
417 static INLINE void
emit_xl(struct ppc_function * p,uint op,uint bo,uint bi,uint bh,uint op2,uint lk)418 emit_xl(struct ppc_function *p, uint op, uint bo, uint bi, uint bh,
419         uint op2, uint lk)
420 {
421    union xl_inst inst;
422    inst.inst.op = op;
423    inst.inst.bo = bo;
424    inst.inst.bi = bi;
425    inst.inst.unused = 0x0;
426    inst.inst.bh = bh;
427    inst.inst.op2 = op2;
428    inst.inst.lk = lk;
429    emit_instruction(p, inst.bits);
430 }
431 
432 static INLINE void
dump_xl(const char * name,uint inst)433 dump_xl(const char *name, uint inst)
434 {
435    union xl_inst i;
436 
437    i.bits = inst;
438    debug_printf("%s = 0x%08x\n", name, inst);
439    debug_printf(" op: %d 0x%x\n", i.inst.op, i.inst.op);
440    debug_printf(" bo: %d 0x%x\n", i.inst.bo, i.inst.bo);
441    debug_printf(" bi: %d 0x%x\n", i.inst.bi, i.inst.bi);
442    debug_printf(" unused: %d 0x%x\n", i.inst.unused, i.inst.unused);
443    debug_printf(" bh: %d 0x%x\n", i.inst.bh, i.inst.bh);
444    debug_printf(" op2: %d 0x%x\n", i.inst.op2, i.inst.op2);
445    debug_printf(" lk: %d 0x%x\n", i.inst.lk, i.inst.lk);
446 }
447 
448 
449 union x_inst {
450    uint32_t bits;
451    struct {
452       unsigned op:6;
453       unsigned vrs:5;
454       unsigned ra:5;
455       unsigned rb:5;
456       unsigned op2:10;
457       unsigned unused:1;
458    } inst;
459 };
460 
461 static INLINE void
emit_x(struct ppc_function * p,uint op,uint vrs,uint ra,uint rb,uint op2,const char * format)462 emit_x(struct ppc_function *p, uint op, uint vrs, uint ra, uint rb, uint op2,
463        const char *format)
464 {
465    union x_inst inst;
466    inst.inst.op = op;
467    inst.inst.vrs = vrs;
468    inst.inst.ra = ra;
469    inst.inst.rb = rb;
470    inst.inst.op2 = op2;
471    inst.inst.unused = 0x0;
472    emit_instruction(p, inst.bits);
473    if (p->print) {
474       indent(p);
475       printf(format, vrs, ra, rb);
476    }
477 }
478 
479 
480 union d_inst {
481    uint32_t bits;
482    struct {
483       unsigned op:6;
484       unsigned rt:5;
485       unsigned ra:5;
486       unsigned si:16;
487    } inst;
488 };
489 
490 static INLINE void
emit_d(struct ppc_function * p,uint op,uint rt,uint ra,int si,const char * format,boolean transpose)491 emit_d(struct ppc_function *p, uint op, uint rt, uint ra, int si,
492        const char *format, boolean transpose)
493 {
494    union d_inst inst;
495    assert(si >= -32768);
496    assert(si <= 32767);
497    inst.inst.op = op;
498    inst.inst.rt = rt;
499    inst.inst.ra = ra;
500    inst.inst.si = (unsigned) (si & 0xffff);
501    emit_instruction(p, inst.bits);
502    if (p->print) {
503       indent(p);
504       if (transpose)
505          printf(format, rt, si, ra);
506       else
507          printf(format, rt, ra, si);
508    }
509 }
510 
511 
512 union a_inst {
513    uint32_t bits;
514    struct {
515       unsigned op:6;
516       unsigned frt:5;
517       unsigned fra:5;
518       unsigned frb:5;
519       unsigned unused:5;
520       unsigned op2:5;
521       unsigned rc:1;
522    } inst;
523 };
524 
525 static INLINE void
emit_a(struct ppc_function * p,uint op,uint frt,uint fra,uint frb,uint op2,uint rc,const char * format)526 emit_a(struct ppc_function *p, uint op, uint frt, uint fra, uint frb, uint op2,
527        uint rc, const char *format)
528 {
529    union a_inst inst;
530    inst.inst.op = op;
531    inst.inst.frt = frt;
532    inst.inst.fra = fra;
533    inst.inst.frb = frb;
534    inst.inst.unused = 0x0;
535    inst.inst.op2 = op2;
536    inst.inst.rc = rc;
537    emit_instruction(p, inst.bits);
538    if (p->print) {
539       indent(p);
540       printf(format, frt, fra, frb);
541    }
542 }
543 
544 
545 union xo_inst {
546    uint32_t bits;
547    struct {
548       unsigned op:6;
549       unsigned rt:5;
550       unsigned ra:5;
551       unsigned rb:5;
552       unsigned oe:1;
553       unsigned op2:9;
554       unsigned rc:1;
555    } inst;
556 };
557 
558 static INLINE void
emit_xo(struct ppc_function * p,uint op,uint rt,uint ra,uint rb,uint oe,uint op2,uint rc,const char * format)559 emit_xo(struct ppc_function *p, uint op, uint rt, uint ra, uint rb, uint oe,
560         uint op2, uint rc, const char *format)
561 {
562    union xo_inst inst;
563    inst.inst.op = op;
564    inst.inst.rt = rt;
565    inst.inst.ra = ra;
566    inst.inst.rb = rb;
567    inst.inst.oe = oe;
568    inst.inst.op2 = op2;
569    inst.inst.rc = rc;
570    emit_instruction(p, inst.bits);
571    if (p->print) {
572       indent(p);
573       printf(format, rt, ra, rb);
574    }
575 }
576 
577 
578 
579 
580 
581 /**
582  ** float vector arithmetic
583  **/
584 
585 /** vector float add */
586 void
ppc_vaddfp(struct ppc_function * p,uint vD,uint vA,uint vB)587 ppc_vaddfp(struct ppc_function *p, uint vD, uint vA, uint vB)
588 {
589    emit_vx(p, 10, vD, vA, vB, "vaddfp\t%u, v%u, v%u\n", FALSE);
590 }
591 
592 /** vector float substract */
593 void
ppc_vsubfp(struct ppc_function * p,uint vD,uint vA,uint vB)594 ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB)
595 {
596    emit_vx(p, 74, vD, vA, vB, "vsubfp\tv%u, v%u, v%u\n", FALSE);
597 }
598 
599 /** vector float min */
600 void
ppc_vminfp(struct ppc_function * p,uint vD,uint vA,uint vB)601 ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB)
602 {
603    emit_vx(p, 1098, vD, vA, vB, "vminfp\tv%u, v%u, v%u\n", FALSE);
604 }
605 
606 /** vector float max */
607 void
ppc_vmaxfp(struct ppc_function * p,uint vD,uint vA,uint vB)608 ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB)
609 {
610    emit_vx(p, 1034, vD, vA, vB, "vmaxfp\tv%u, v%u, v%u\n", FALSE);
611 }
612 
613 /** vector float mult add: vD = vA * vB + vC */
614 void
ppc_vmaddfp(struct ppc_function * p,uint vD,uint vA,uint vB,uint vC)615 ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
616 {
617    /* note arg order */
618    emit_va(p, 46, vD, vA, vC, vB, "vmaddfp\tv%u, v%u, v%u, v%u\n");
619 }
620 
621 /** vector float negative mult subtract: vD = vA - vB * vC */
622 void
ppc_vnmsubfp(struct ppc_function * p,uint vD,uint vA,uint vB,uint vC)623 ppc_vnmsubfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
624 {
625    /* note arg order */
626    emit_va(p, 47, vD, vB, vA, vC, "vnmsubfp\tv%u, v%u, v%u, v%u\n");
627 }
628 
629 /** vector float compare greater than */
630 void
ppc_vcmpgtfpx(struct ppc_function * p,uint vD,uint vA,uint vB)631 ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
632 {
633    emit_vxr(p, 710, vD, vA, vB, "vcmpgtfpx\tv%u, v%u, v%u");
634 }
635 
636 /** vector float compare greater than or equal to */
637 void
ppc_vcmpgefpx(struct ppc_function * p,uint vD,uint vA,uint vB)638 ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB)
639 {
640    emit_vxr(p, 454, vD, vA, vB, "vcmpgefpx\tv%u, v%u, v%u");
641 }
642 
643 /** vector float compare equal */
644 void
ppc_vcmpeqfpx(struct ppc_function * p,uint vD,uint vA,uint vB)645 ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
646 {
647    emit_vxr(p, 198, vD, vA, vB, "vcmpeqfpx\tv%u, v%u, v%u");
648 }
649 
650 /** vector float 2^x */
651 void
ppc_vexptefp(struct ppc_function * p,uint vD,uint vB)652 ppc_vexptefp(struct ppc_function *p, uint vD, uint vB)
653 {
654    emit_vx(p, 394, vD, 0, vB, "vexptefp\tv%u, 0%u, v%u\n", FALSE);
655 }
656 
657 /** vector float log2(x) */
658 void
ppc_vlogefp(struct ppc_function * p,uint vD,uint vB)659 ppc_vlogefp(struct ppc_function *p, uint vD, uint vB)
660 {
661    emit_vx(p, 458, vD, 0, vB, "vlogefp\tv%u, 0%u, v%u\n", FALSE);
662 }
663 
664 /** vector float reciprocol */
665 void
ppc_vrefp(struct ppc_function * p,uint vD,uint vB)666 ppc_vrefp(struct ppc_function *p, uint vD, uint vB)
667 {
668    emit_vx(p, 266, vD, 0, vB, "vrefp\tv%u, 0%u, v%u\n", FALSE);
669 }
670 
671 /** vector float reciprocol sqrt estimate */
672 void
ppc_vrsqrtefp(struct ppc_function * p,uint vD,uint vB)673 ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB)
674 {
675    emit_vx(p, 330, vD, 0, vB, "vrsqrtefp\tv%u, 0%u, v%u\n", FALSE);
676 }
677 
678 /** vector float round to negative infinity */
679 void
ppc_vrfim(struct ppc_function * p,uint vD,uint vB)680 ppc_vrfim(struct ppc_function *p, uint vD, uint vB)
681 {
682    emit_vx(p, 714, vD, 0, vB, "vrfim\tv%u, 0%u, v%u\n", FALSE);
683 }
684 
685 /** vector float round to positive infinity */
686 void
ppc_vrfip(struct ppc_function * p,uint vD,uint vB)687 ppc_vrfip(struct ppc_function *p, uint vD, uint vB)
688 {
689    emit_vx(p, 650, vD, 0, vB, "vrfip\tv%u, 0%u, v%u\n", FALSE);
690 }
691 
692 /** vector float round to nearest int */
693 void
ppc_vrfin(struct ppc_function * p,uint vD,uint vB)694 ppc_vrfin(struct ppc_function *p, uint vD, uint vB)
695 {
696    emit_vx(p, 522, vD, 0, vB, "vrfin\tv%u, 0%u, v%u\n", FALSE);
697 }
698 
699 /** vector float round to int toward zero */
700 void
ppc_vrfiz(struct ppc_function * p,uint vD,uint vB)701 ppc_vrfiz(struct ppc_function *p, uint vD, uint vB)
702 {
703    emit_vx(p, 586, vD, 0, vB, "vrfiz\tv%u, 0%u, v%u\n", FALSE);
704 }
705 
706 /** vector store: store vR at mem[rA+rB] */
707 void
ppc_stvx(struct ppc_function * p,uint vR,uint rA,uint rB)708 ppc_stvx(struct ppc_function *p, uint vR, uint rA, uint rB)
709 {
710    emit_x(p, 31, vR, rA, rB, 231, "stvx\tv%u, r%u, r%u\n");
711 }
712 
713 /** vector load: vR = mem[rA+rB] */
714 void
ppc_lvx(struct ppc_function * p,uint vR,uint rA,uint rB)715 ppc_lvx(struct ppc_function *p, uint vR, uint rA, uint rB)
716 {
717    emit_x(p, 31, vR, rA, rB, 103, "lvx\tv%u, r%u, r%u\n");
718 }
719 
720 /** load vector element word: vR = mem_word[ra+rb] */
721 void
ppc_lvewx(struct ppc_function * p,uint vR,uint rA,uint rB)722 ppc_lvewx(struct ppc_function *p, uint vR, uint rA, uint rB)
723 {
724    emit_x(p, 31, vR, rA, rB, 71, "lvewx\tv%u, r%u, r%u\n");
725 }
726 
727 
728 
729 
730 /**
731  ** vector bitwise operations
732  **/
733 
734 /** vector and */
735 void
ppc_vand(struct ppc_function * p,uint vD,uint vA,uint vB)736 ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB)
737 {
738    emit_vx(p, 1028, vD, vA, vB, "vand\tv%u, v%u, v%u\n", FALSE);
739 }
740 
741 /** vector and complement */
742 void
ppc_vandc(struct ppc_function * p,uint vD,uint vA,uint vB)743 ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB)
744 {
745    emit_vx(p, 1092, vD, vA, vB, "vandc\tv%u, v%u, v%u\n", FALSE);
746 }
747 
748 /** vector or */
749 void
ppc_vor(struct ppc_function * p,uint vD,uint vA,uint vB)750 ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB)
751 {
752    emit_vx(p, 1156, vD, vA, vB, "vor\tv%u, v%u, v%u\n", FALSE);
753 }
754 
755 /** vector nor */
756 void
ppc_vnor(struct ppc_function * p,uint vD,uint vA,uint vB)757 ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB)
758 {
759    emit_vx(p, 1284, vD, vA, vB, "vnor\tv%u, v%u, v%u\n", FALSE);
760 }
761 
762 /** vector xor */
763 void
ppc_vxor(struct ppc_function * p,uint vD,uint vA,uint vB)764 ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB)
765 {
766    emit_vx(p, 1220, vD, vA, vB, "vxor\tv%u, v%u, v%u\n", FALSE);
767 }
768 
769 /** Pseudo-instruction: vector move */
770 void
ppc_vmove(struct ppc_function * p,uint vD,uint vA)771 ppc_vmove(struct ppc_function *p, uint vD, uint vA)
772 {
773    boolean print = p->print;
774    p->print = FALSE;
775    ppc_vor(p, vD, vA, vA);
776    if (print) {
777       indent(p);
778       printf("vor\tv%u, v%u, v%u \t# v%u = v%u\n", vD, vA, vA, vD, vA);
779    }
780    p->print = print;
781 }
782 
783 /** Set vector register to {0,0,0,0} */
784 void
ppc_vzero(struct ppc_function * p,uint vr)785 ppc_vzero(struct ppc_function *p, uint vr)
786 {
787    boolean print = p->print;
788    p->print = FALSE;
789    ppc_vxor(p, vr, vr, vr);
790    if (print) {
791       indent(p);
792       printf("vxor\tv%u, v%u, v%u \t# v%u = {0,0,0,0}\n", vr, vr, vr, vr);
793    }
794    p->print = print;
795 }
796 
797 
798 
799 
800 /**
801  ** Vector shuffle / select / splat / etc
802  **/
803 
804 /** vector permute */
805 void
ppc_vperm(struct ppc_function * p,uint vD,uint vA,uint vB,uint vC)806 ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
807 {
808    emit_va(p, 43, vD, vA, vB, vC, "vperm\tr%u, r%u, r%u, r%u");
809 }
810 
811 /** vector select */
812 void
ppc_vsel(struct ppc_function * p,uint vD,uint vA,uint vB,uint vC)813 ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
814 {
815    emit_va(p, 42, vD, vA, vB, vC, "vsel\tr%u, r%u, r%u, r%u");
816 }
817 
818 /** vector splat byte */
819 void
ppc_vspltb(struct ppc_function * p,uint vD,uint vB,uint imm)820 ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm)
821 {
822    emit_vx(p, 42, vD, imm, vB, "vspltb\tv%u, v%u, %u\n", TRUE);
823 }
824 
825 /** vector splat half word */
826 void
ppc_vsplthw(struct ppc_function * p,uint vD,uint vB,uint imm)827 ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm)
828 {
829    emit_vx(p, 588, vD, imm, vB, "vsplthw\tv%u, v%u, %u\n", TRUE);
830 }
831 
832 /** vector splat word */
833 void
ppc_vspltw(struct ppc_function * p,uint vD,uint vB,uint imm)834 ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm)
835 {
836    emit_vx(p, 652, vD, imm, vB, "vspltw\tv%u, v%u, %u\n", TRUE);
837 }
838 
839 /** vector splat signed immediate word */
840 void
ppc_vspltisw(struct ppc_function * p,uint vD,int imm)841 ppc_vspltisw(struct ppc_function *p, uint vD, int imm)
842 {
843    assert(imm >= -16);
844    assert(imm < 15);
845    emit_vx(p, 908, vD, imm, 0, "vspltisw\tv%u, %d, %u\n", FALSE);
846 }
847 
848 /** vector shift left word: vD[word] = vA[word] << (vB[word] & 0x1f) */
849 void
ppc_vslw(struct ppc_function * p,uint vD,uint vA,uint vB)850 ppc_vslw(struct ppc_function *p, uint vD, uint vA, uint vB)
851 {
852    emit_vx(p, 388, vD, vA, vB, "vslw\tv%u, v%u, v%u\n", FALSE);
853 }
854 
855 
856 
857 
858 /**
859  ** integer arithmetic
860  **/
861 
862 /** rt = ra + imm */
863 void
ppc_addi(struct ppc_function * p,uint rt,uint ra,int imm)864 ppc_addi(struct ppc_function *p, uint rt, uint ra, int imm)
865 {
866    emit_d(p, 14, rt, ra, imm, "addi\tr%u, r%u, %d\n", FALSE);
867 }
868 
869 /** rt = ra + (imm << 16) */
870 void
ppc_addis(struct ppc_function * p,uint rt,uint ra,int imm)871 ppc_addis(struct ppc_function *p, uint rt, uint ra, int imm)
872 {
873    emit_d(p, 15, rt, ra, imm, "addis\tr%u, r%u, %d\n", FALSE);
874 }
875 
876 /** rt = ra + rb */
877 void
ppc_add(struct ppc_function * p,uint rt,uint ra,uint rb)878 ppc_add(struct ppc_function *p, uint rt, uint ra, uint rb)
879 {
880    emit_xo(p, 31, rt, ra, rb, 0, 266, 0, "add\tr%u, r%u, r%u\n");
881 }
882 
883 /** rt = ra AND ra */
884 void
ppc_and(struct ppc_function * p,uint rt,uint ra,uint rb)885 ppc_and(struct ppc_function *p, uint rt, uint ra, uint rb)
886 {
887    emit_x(p, 31, ra, rt, rb, 28, "and\tr%u, r%u, r%u\n");  /* note argument order */
888 }
889 
890 /** rt = ra AND imm */
891 void
ppc_andi(struct ppc_function * p,uint rt,uint ra,int imm)892 ppc_andi(struct ppc_function *p, uint rt, uint ra, int imm)
893 {
894    /* note argument order */
895    emit_d(p, 28, ra, rt, imm, "andi\tr%u, r%u, %d\n", FALSE);
896 }
897 
898 /** rt = ra OR ra */
899 void
ppc_or(struct ppc_function * p,uint rt,uint ra,uint rb)900 ppc_or(struct ppc_function *p, uint rt, uint ra, uint rb)
901 {
902    emit_x(p, 31, ra, rt, rb, 444, "or\tr%u, r%u, r%u\n");  /* note argument order */
903 }
904 
905 /** rt = ra OR imm */
906 void
ppc_ori(struct ppc_function * p,uint rt,uint ra,int imm)907 ppc_ori(struct ppc_function *p, uint rt, uint ra, int imm)
908 {
909    /* note argument order */
910    emit_d(p, 24, ra, rt, imm, "ori\tr%u, r%u, %d\n", FALSE);
911 }
912 
913 /** rt = ra XOR ra */
914 void
ppc_xor(struct ppc_function * p,uint rt,uint ra,uint rb)915 ppc_xor(struct ppc_function *p, uint rt, uint ra, uint rb)
916 {
917    emit_x(p, 31, ra, rt, rb, 316, "xor\tr%u, r%u, r%u\n");  /* note argument order */
918 }
919 
920 /** rt = ra XOR imm */
921 void
ppc_xori(struct ppc_function * p,uint rt,uint ra,int imm)922 ppc_xori(struct ppc_function *p, uint rt, uint ra, int imm)
923 {
924    /* note argument order */
925    emit_d(p, 26, ra, rt, imm, "xori\tr%u, r%u, %d\n", FALSE);
926 }
927 
928 /** pseudo instruction: move: rt = ra */
929 void
ppc_mr(struct ppc_function * p,uint rt,uint ra)930 ppc_mr(struct ppc_function *p, uint rt, uint ra)
931 {
932    ppc_or(p, rt, ra, ra);
933 }
934 
935 /** pseudo instruction: load immediate: rt = imm */
936 void
ppc_li(struct ppc_function * p,uint rt,int imm)937 ppc_li(struct ppc_function *p, uint rt, int imm)
938 {
939    boolean print = p->print;
940    p->print = FALSE;
941    ppc_addi(p, rt, 0, imm);
942    if (print) {
943       indent(p);
944       printf("addi\tr%u, r0, %d \t# r%u = %d\n", rt, imm, rt, imm);
945    }
946    p->print = print;
947 }
948 
949 /** rt = imm << 16 */
950 void
ppc_lis(struct ppc_function * p,uint rt,int imm)951 ppc_lis(struct ppc_function *p, uint rt, int imm)
952 {
953    ppc_addis(p, rt, 0, imm);
954 }
955 
956 /** rt = imm */
957 void
ppc_load_int(struct ppc_function * p,uint rt,int imm)958 ppc_load_int(struct ppc_function *p, uint rt, int imm)
959 {
960    ppc_lis(p, rt, (imm >> 16));          /* rt = imm >> 16 */
961    ppc_ori(p, rt, rt, (imm & 0xffff));   /* rt = rt | (imm & 0xffff) */
962 }
963 
964 
965 
966 
967 /**
968  ** integer load/store
969  **/
970 
971 /** store rs at memory[(ra)+d],
972  * then update ra = (ra)+d
973  */
974 void
ppc_stwu(struct ppc_function * p,uint rs,uint ra,int d)975 ppc_stwu(struct ppc_function *p, uint rs, uint ra, int d)
976 {
977    emit_d(p, 37, rs, ra, d, "stwu\tr%u, %d(r%u)\n", TRUE);
978 }
979 
980 /** store rs at memory[(ra)+d] */
981 void
ppc_stw(struct ppc_function * p,uint rs,uint ra,int d)982 ppc_stw(struct ppc_function *p, uint rs, uint ra, int d)
983 {
984    emit_d(p, 36, rs, ra, d, "stw\tr%u, %d(r%u)\n", TRUE);
985 }
986 
987 /** Load rt = mem[(ra)+d];  then zero set high 32 bits to zero. */
988 void
ppc_lwz(struct ppc_function * p,uint rt,uint ra,int d)989 ppc_lwz(struct ppc_function *p, uint rt, uint ra, int d)
990 {
991    emit_d(p, 32, rt, ra, d, "lwz\tr%u, %d(r%u)\n", TRUE);
992 }
993 
994 
995 
996 /**
997  ** Float (non-vector) arithmetic
998  **/
999 
1000 /** add: frt = fra + frb */
1001 void
ppc_fadd(struct ppc_function * p,uint frt,uint fra,uint frb)1002 ppc_fadd(struct ppc_function *p, uint frt, uint fra, uint frb)
1003 {
1004    emit_a(p, 63, frt, fra, frb, 21, 0, "fadd\tf%u, f%u, f%u\n");
1005 }
1006 
1007 /** sub: frt = fra - frb */
1008 void
ppc_fsub(struct ppc_function * p,uint frt,uint fra,uint frb)1009 ppc_fsub(struct ppc_function *p, uint frt, uint fra, uint frb)
1010 {
1011    emit_a(p, 63, frt, fra, frb, 20, 0, "fsub\tf%u, f%u, f%u\n");
1012 }
1013 
1014 /** convert to int: rt = (int) ra */
1015 void
ppc_fctiwz(struct ppc_function * p,uint rt,uint fra)1016 ppc_fctiwz(struct ppc_function *p, uint rt, uint fra)
1017 {
1018    emit_x(p, 63, rt, 0, fra, 15, "fctiwz\tr%u, r%u, r%u\n");
1019 }
1020 
1021 /** store frs at mem[(ra)+offset] */
1022 void
ppc_stfs(struct ppc_function * p,uint frs,uint ra,int offset)1023 ppc_stfs(struct ppc_function *p, uint frs, uint ra, int offset)
1024 {
1025    emit_d(p, 52, frs, ra, offset, "stfs\tr%u, %d(r%u)\n", TRUE);
1026 }
1027 
1028 /** store frs at mem[(ra)+(rb)] */
1029 void
ppc_stfiwx(struct ppc_function * p,uint frs,uint ra,uint rb)1030 ppc_stfiwx(struct ppc_function *p, uint frs, uint ra, uint rb)
1031 {
1032    emit_x(p, 31, frs, ra, rb, 983, "stfiwx\tr%u, r%u, r%u\n");
1033 }
1034 
1035 /** load frt = mem[(ra)+offset] */
1036 void
ppc_lfs(struct ppc_function * p,uint frt,uint ra,int offset)1037 ppc_lfs(struct ppc_function *p, uint frt, uint ra, int offset)
1038 {
1039    emit_d(p, 48, frt, ra, offset, "stfs\tr%u, %d(r%u)\n", TRUE);
1040 }
1041 
1042 
1043 
1044 
1045 
1046 /**
1047  ** branch instructions
1048  **/
1049 
1050 /** BLR: Branch to link register (p. 35) */
1051 void
ppc_blr(struct ppc_function * p)1052 ppc_blr(struct ppc_function *p)
1053 {
1054    emit_i(p, 18, 0, 0, 1);
1055    if (p->print) {
1056       indent(p);
1057       printf("blr\n");
1058    }
1059 }
1060 
1061 /** Branch Conditional to Link Register (p. 36) */
1062 void
ppc_bclr(struct ppc_function * p,uint condOp,uint branchHint,uint condReg)1063 ppc_bclr(struct ppc_function *p, uint condOp, uint branchHint, uint condReg)
1064 {
1065    emit_xl(p, 19, condOp, condReg, branchHint, 16, 0);
1066    if (p->print) {
1067       indent(p);
1068       printf("bclr\t%u %u %u\n", condOp, branchHint, condReg);
1069    }
1070 }
1071 
1072 /** Pseudo instruction: return from subroutine */
1073 void
ppc_return(struct ppc_function * p)1074 ppc_return(struct ppc_function *p)
1075 {
1076    ppc_bclr(p, BRANCH_COND_ALWAYS, BRANCH_HINT_SUB_RETURN, 0);
1077 }
1078