1 /**************************************************************************
3 * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 **************************************************************************/
25 * PPC code generation.
26 * For reference, see http://www.power.org/resources/reading/PowerISA_V2.05.pdf
27 * ABI info: http://www.cs.utsa.edu/~whaley/teach/cs6463FHPO/LEC/lec12_ho.pdf
30 * http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
31 * http://www.ibm.com/developerworks/eserver/library/es-archguide-v2.html
32 * http://www.freescale.com/files/product/doc/MPCFPE32B.pdf
39 #include "util/u_memory.h"
40 #include "pipe/p_debug.h"
41 #include "rtasm_ppc.h"
45 ppc_init_func(struct ppc_function
*p
, unsigned max_inst
)
49 p
->store
= align_malloc(max_inst
* PPC_INST_SIZE
, 16);
51 p
->max_inst
= max_inst
;
56 /* only allow using gp registers 3..12 for now */
57 for (i
= 0; i
< 3; i
++)
58 ppc_reserve_register(p
, i
);
59 for (i
= 12; i
< PPC_NUM_REGS
; i
++)
60 ppc_reserve_register(p
, i
);
65 ppc_release_func(struct ppc_function
*p
)
67 assert(p
->num_inst
<= p
->max_inst
);
68 if (p
->store
!= NULL
) {
75 void (*ppc_get_func(struct ppc_function
*p
))(void)
79 if (DISASSEM
&& p
->store
)
80 debug_printf("disassemble %p %p\n", p
->store
, p
->csr
);
82 if (p
->store
== p
->error_overflow
)
83 return (void (*)(void)) NULL
;
86 return (void (*)(void)) p
->store
;
91 ppc_dump_func(const struct ppc_function
*p
)
94 for (i
= 0; i
< p
->num_inst
; i
++) {
95 debug_printf("%3u: 0x%08x\n", i
, p
->store
[i
]);
101 * Mark a register as being unavailable.
104 ppc_reserve_register(struct ppc_function
*p
, int reg
)
106 assert(reg
< PPC_NUM_REGS
);
107 p
->reg_used
|= (1 << reg
);
113 * Allocate a general purpose register.
114 * \return register index or -1 if none left.
117 ppc_allocate_register(struct ppc_function
*p
)
120 for (i
= 0; i
< PPC_NUM_REGS
; i
++) {
121 const uint64_t mask
= 1 << i
;
122 if ((p
->reg_used
& mask
) == 0) {
132 * Mark the given general purpose register as "unallocated".
135 ppc_release_register(struct ppc_function
*p
, int reg
)
137 assert(reg
< PPC_NUM_REGS
);
138 assert(p
->reg_used
& (1 << reg
));
139 p
->reg_used
&= ~(1 << reg
);
144 * Allocate a floating point register.
145 * \return register index or -1 if none left.
148 ppc_allocate_fp_register(struct ppc_function
*p
)
151 for (i
= 0; i
< PPC_NUM_FP_REGS
; i
++) {
152 const uint64_t mask
= 1 << i
;
153 if ((p
->fp_used
& mask
) == 0) {
163 * Mark the given floating point register as "unallocated".
166 ppc_release_fp_register(struct ppc_function
*p
, int reg
)
168 assert(reg
< PPC_NUM_FP_REGS
);
169 assert(p
->fp_used
& (1 << reg
));
170 p
->fp_used
&= ~(1 << reg
);
175 * Allocate a vector register.
176 * \return register index or -1 if none left.
179 ppc_allocate_vec_register(struct ppc_function
*p
)
182 for (i
= 0; i
< PPC_NUM_VEC_REGS
; i
++) {
183 const uint64_t mask
= 1 << i
;
184 if ((p
->vec_used
& mask
) == 0) {
194 * Mark the given vector register as "unallocated".
197 ppc_release_vec_register(struct ppc_function
*p
, int reg
)
199 assert(reg
< PPC_NUM_VEC_REGS
);
200 assert(p
->vec_used
& (1 << reg
));
201 p
->vec_used
&= ~(1 << reg
);
218 emit_vx(struct ppc_function
*p
, uint op2
, uint vD
, uint vA
, uint vB
)
226 p
->store
[p
->num_inst
++] = inst
.bits
;
227 assert(p
->num_inst
<= p
->max_inst
);
244 emit_vxr(struct ppc_function
*p
, uint op2
, uint vD
, uint vA
, uint vB
)
253 p
->store
[p
->num_inst
++] = inst
.bits
;
254 assert(p
->num_inst
<= p
->max_inst
);
271 emit_va(struct ppc_function
*p
, uint op2
, uint vD
, uint vA
, uint vB
, uint vC
)
280 p
->store
[p
->num_inst
++] = inst
.bits
;
281 assert(p
->num_inst
<= p
->max_inst
);
296 emit_i(struct ppc_function
*p
, uint op
, uint li
, uint aa
, uint lk
)
303 p
->store
[p
->num_inst
++] = inst
.bits
;
304 assert(p
->num_inst
<= p
->max_inst
);
322 emit_xl(struct ppc_function
*p
, uint op
, uint bo
, uint bi
, uint bh
,
329 inst
.inst
.unused
= 0x0;
333 p
->store
[p
->num_inst
++] = inst
.bits
;
334 assert(p
->num_inst
<= p
->max_inst
);
338 dump_xl(const char *name
, uint inst
)
343 debug_printf("%s = 0x%08x\n", name
, inst
);
344 debug_printf(" op: %d 0x%x\n", i
.inst
.op
, i
.inst
.op
);
345 debug_printf(" bo: %d 0x%x\n", i
.inst
.bo
, i
.inst
.bo
);
346 debug_printf(" bi: %d 0x%x\n", i
.inst
.bi
, i
.inst
.bi
);
347 debug_printf(" unused: %d 0x%x\n", i
.inst
.unused
, i
.inst
.unused
);
348 debug_printf(" bh: %d 0x%x\n", i
.inst
.bh
, i
.inst
.bh
);
349 debug_printf(" op2: %d 0x%x\n", i
.inst
.op2
, i
.inst
.op2
);
350 debug_printf(" lk: %d 0x%x\n", i
.inst
.lk
, i
.inst
.lk
);
367 emit_x(struct ppc_function
*p
, uint op
, uint vrs
, uint ra
, uint rb
, uint op2
)
375 inst
.inst
.unused
= 0x0;
376 p
->store
[p
->num_inst
++] = inst
.bits
;
377 assert(p
->num_inst
<= p
->max_inst
);
392 emit_d(struct ppc_function
*p
, uint op
, uint rt
, uint ra
, int si
)
395 assert(si
>= -32768);
400 inst
.inst
.si
= (unsigned) (si
& 0xffff);
401 p
->store
[p
->num_inst
++] = inst
.bits
;
402 assert(p
->num_inst
<= p
->max_inst
);
420 emit_a(struct ppc_function
*p
, uint op
, uint frt
, uint fra
, uint frb
, uint op2
,
428 inst
.inst
.unused
= 0x0;
431 p
->store
[p
->num_inst
++] = inst
.bits
;
432 assert(p
->num_inst
<= p
->max_inst
);
450 emit_xo(struct ppc_function
*p
, uint op
, uint rt
, uint ra
, uint rb
, uint oe
,
461 p
->store
[p
->num_inst
++] = inst
.bits
;
462 assert(p
->num_inst
<= p
->max_inst
);
470 ** float vector arithmetic
473 /** vector float add */
475 ppc_vaddfp(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
477 emit_vx(p
, 10, vD
, vA
, vB
);
480 /** vector float substract */
482 ppc_vsubfp(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
484 emit_vx(p
, 74, vD
, vA
, vB
);
487 /** vector float min */
489 ppc_vminfp(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
491 emit_vx(p
, 1098, vD
, vA
, vB
);
494 /** vector float max */
496 ppc_vmaxfp(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
498 emit_vx(p
, 1034, vD
, vA
, vB
);
501 /** vector float mult add: vD = vA * vB + vC */
503 ppc_vmaddfp(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
, uint vC
)
505 emit_va(p
, 46, vD
, vA
, vC
, vB
); /* note arg order */
508 /** vector float compare greater than */
510 ppc_vcmpgtfpx(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
512 emit_vxr(p
, 710, vD
, vA
, vB
);
515 /** vector float compare greater than or equal to */
517 ppc_vcmpgefpx(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
519 emit_vxr(p
, 454, vD
, vA
, vB
);
522 /** vector float compare equal */
524 ppc_vcmpeqfpx(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
526 emit_vxr(p
, 198, vD
, vA
, vB
);
529 /** vector float 2^x */
531 ppc_vexptefp(struct ppc_function
*p
, uint vD
, uint vB
)
533 emit_vx(p
, 394, vD
, 0, vB
);
536 /** vector float log2(x) */
538 ppc_vlogefp(struct ppc_function
*p
, uint vD
, uint vB
)
540 emit_vx(p
, 458, vD
, 0, vB
);
543 /** vector float reciprocol */
545 ppc_vrefp(struct ppc_function
*p
, uint vD
, uint vB
)
547 emit_vx(p
, 266, vD
, 0, vB
);
550 /** vector float reciprocol sqrt estimate */
552 ppc_vrsqrtefp(struct ppc_function
*p
, uint vD
, uint vB
)
554 emit_vx(p
, 330, vD
, 0, vB
);
557 /** vector float round to negative infinity */
559 ppc_vrfim(struct ppc_function
*p
, uint vD
, uint vB
)
561 emit_vx(p
, 714, vD
, 0, vB
);
564 /** vector float round to positive infinity */
566 ppc_vrfip(struct ppc_function
*p
, uint vD
, uint vB
)
568 emit_vx(p
, 650, vD
, 0, vB
);
571 /** vector float round to nearest int */
573 ppc_vrfin(struct ppc_function
*p
, uint vD
, uint vB
)
575 emit_vx(p
, 522, vD
, 0, vB
);
578 /** vector float round to int toward zero */
580 ppc_vrfiz(struct ppc_function
*p
, uint vD
, uint vB
)
582 emit_vx(p
, 586, vD
, 0, vB
);
585 /** vector store: store vR at mem[vA+vB] */
587 ppc_stvx(struct ppc_function
*p
, uint vR
, uint vA
, uint vB
)
589 emit_x(p
, 31, vR
, vA
, vB
, 231);
592 /** vector load: vR = mem[vA+vB] */
594 ppc_lvx(struct ppc_function
*p
, uint vR
, uint vA
, uint vB
)
596 emit_x(p
, 31, vR
, vA
, vB
, 103);
599 /** load vector element word: vR = mem_word[ra+rb] */
601 ppc_lvewx(struct ppc_function
*p
, uint vr
, uint ra
, uint rb
)
603 emit_x(p
, 31, vr
, ra
, rb
, 71);
606 /** vector load float: vr = splats(imm) */
608 ppc_vload_float(struct ppc_function
*p
, uint vr
, float imm
)
611 ppc_vxor(p
, vr
, vr
, vr
);
613 else if (imm
== 1.0f
) {
614 /* use 2^0=1 to get 1.0 */
615 ppc_vxor(p
, vr
, vr
, vr
); /* vr = {0,0,0,0} */
616 ppc_vexptefp(p
, vr
, vr
); /* vr = 0^0 */
627 ** vector bitwise operations
632 ppc_vand(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
634 emit_vx(p
, 1028, vD
, vA
, vB
);
637 /** vector and complement */
639 ppc_vandc(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
641 emit_vx(p
, 1092, vD
, vA
, vB
);
646 ppc_vor(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
648 emit_vx(p
, 1156, vD
, vA
, vB
);
653 ppc_vnor(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
655 emit_vx(p
, 1284, vD
, vA
, vB
);
660 ppc_vxor(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
662 emit_vx(p
, 1220, vD
, vA
, vB
);
665 /** Pseudo-instruction: vector move */
667 ppc_vecmove(struct ppc_function
*p
, uint vD
, uint vA
)
669 ppc_vor(p
, vD
, vA
, vA
);
675 ** Vector shuffle / select / splat / etc
678 /** vector permute */
680 ppc_vperm(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
, uint vC
)
682 emit_va(p
, 43, vD
, vA
, vB
, vC
);
687 ppc_vsel(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
, uint vC
)
689 emit_va(p
, 42, vD
, vA
, vB
, vC
);
692 /** vector splat byte */
694 ppc_vspltb(struct ppc_function
*p
, uint vD
, uint vB
, uint imm
)
696 emit_vx(p
, 42, vD
, imm
, vB
);
699 /** vector splat half word */
701 ppc_vsplthw(struct ppc_function
*p
, uint vD
, uint vB
, uint imm
)
703 emit_vx(p
, 588, vD
, imm
, vB
);
706 /** vector splat word */
708 ppc_vspltw(struct ppc_function
*p
, uint vD
, uint vB
, uint imm
)
710 emit_vx(p
, 652, vD
, imm
, vB
);
713 /** vector splat signed immediate word */
715 ppc_vspltisw(struct ppc_function
*p
, uint vD
, int imm
)
719 emit_vx(p
, 908, vD
, imm
, 0);
722 /** vector shift left word: vD[word] = vA[word] << (vB[word] & 0x1f) */
724 ppc_vslw(struct ppc_function
*p
, uint vD
, uint vA
, uint vB
)
726 emit_vx(p
, 388, vD
, vA
, vB
);
733 ** integer arithmetic
738 ppc_addi(struct ppc_function
*p
, uint rt
, uint ra
, int imm
)
740 emit_d(p
, 14, rt
, ra
, imm
);
743 /** rt = ra + (imm << 16) */
745 ppc_addis(struct ppc_function
*p
, uint rt
, uint ra
, int imm
)
747 emit_d(p
, 15, rt
, ra
, imm
);
752 ppc_add(struct ppc_function
*p
, uint rt
, uint ra
, uint rb
)
754 emit_xo(p
, 31, rt
, ra
, rb
, 0, 266, 0);
757 /** rt = ra AND ra */
759 ppc_and(struct ppc_function
*p
, uint rt
, uint ra
, uint rb
)
761 emit_x(p
, 31, ra
, rt
, rb
, 28); /* note argument order */
764 /** rt = ra AND imm */
766 ppc_andi(struct ppc_function
*p
, uint rt
, uint ra
, int imm
)
768 emit_d(p
, 28, ra
, rt
, imm
); /* note argument order */
773 ppc_or(struct ppc_function
*p
, uint rt
, uint ra
, uint rb
)
775 emit_x(p
, 31, ra
, rt
, rb
, 444); /* note argument order */
778 /** rt = ra OR imm */
780 ppc_ori(struct ppc_function
*p
, uint rt
, uint ra
, int imm
)
782 emit_d(p
, 24, ra
, rt
, imm
); /* note argument order */
785 /** rt = ra XOR ra */
787 ppc_xor(struct ppc_function
*p
, uint rt
, uint ra
, uint rb
)
789 emit_x(p
, 31, ra
, rt
, rb
, 316); /* note argument order */
792 /** rt = ra XOR imm */
794 ppc_xori(struct ppc_function
*p
, uint rt
, uint ra
, int imm
)
796 emit_d(p
, 26, ra
, rt
, imm
); /* note argument order */
799 /** pseudo instruction: move: rt = ra */
801 ppc_mr(struct ppc_function
*p
, uint rt
, uint ra
)
803 ppc_or(p
, rt
, ra
, ra
);
806 /** pseudo instruction: load immediate: rt = imm */
808 ppc_li(struct ppc_function
*p
, uint rt
, int imm
)
810 ppc_addi(p
, rt
, 0, imm
);
813 /** rt = imm << 16 */
815 ppc_lis(struct ppc_function
*p
, uint rt
, int imm
)
817 ppc_addis(p
, rt
, 0, imm
);
822 ppc_load_int(struct ppc_function
*p
, uint rt
, int imm
)
824 ppc_lis(p
, rt
, (imm
>> 16)); /* rt = imm >> 16 */
825 ppc_ori(p
, rt
, rt
, (imm
& 0xffff)); /* rt = rt | (imm & 0xffff) */
832 ** integer load/store
835 /** store rs at memory[(ra)+d],
836 * then update ra = (ra)+d
839 ppc_stwu(struct ppc_function
*p
, uint rs
, uint ra
, int d
)
841 emit_d(p
, 37, rs
, ra
, d
);
844 /** store rs at memory[(ra)+d] */
846 ppc_stw(struct ppc_function
*p
, uint rs
, uint ra
, int d
)
848 emit_d(p
, 36, rs
, ra
, d
);
851 /** Load rt = mem[(ra)+d]; then zero set high 32 bits to zero. */
853 ppc_lwz(struct ppc_function
*p
, uint rt
, uint ra
, int d
)
855 emit_d(p
, 32, rt
, ra
, d
);
861 ** Float (non-vector) arithmetic
864 /** add: frt = fra + frb */
866 ppc_fadd(struct ppc_function
*p
, uint frt
, uint fra
, uint frb
)
868 emit_a(p
, 63, frt
, fra
, frb
, 21, 0);
871 /** sub: frt = fra - frb */
873 ppc_fsub(struct ppc_function
*p
, uint frt
, uint fra
, uint frb
)
875 emit_a(p
, 63, frt
, fra
, frb
, 20, 0);
878 /** convert to int: rt = (int) ra */
880 ppc_fctiwz(struct ppc_function
*p
, uint rt
, uint fra
)
882 emit_x(p
, 63, rt
, 0, fra
, 15);
885 /** store frs at mem[(ra)+offset] */
887 ppc_stfs(struct ppc_function
*p
, uint frs
, uint ra
, int offset
)
889 emit_d(p
, 52, frs
, ra
, offset
);
892 /** store frs at mem[(ra)+(rb)] */
894 ppc_stfiwx(struct ppc_function
*p
, uint frs
, uint ra
, uint rb
)
896 emit_x(p
, 31, frs
, ra
, rb
, 983);
899 /** load frt = mem[(ra)+offset] */
901 ppc_lfs(struct ppc_function
*p
, uint frt
, uint ra
, int offset
)
903 emit_d(p
, 48, frt
, ra
, offset
);
911 ** branch instructions
914 /** BLR: Branch to link register (p. 35) */
916 ppc_blr(struct ppc_function
*p
)
918 emit_i(p
, 18, 0, 0, 1);
921 /** Branch Conditional to Link Register (p. 36) */
923 ppc_bclr(struct ppc_function
*p
, uint condOp
, uint branchHint
, uint condReg
)
925 emit_xl(p
, 19, condOp
, condReg
, branchHint
, 16, 0);
928 /** Pseudo instruction: return from subroutine */
930 ppc_return(struct ppc_function
*p
)
932 ppc_bclr(p
, BRANCH_COND_ALWAYS
, BRANCH_HINT_SUB_RETURN
, 0);