int orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value) { int tmp; tmp = orc_compiler_get_temp_reg (compiler); orc_compiler_load_constant (compiler, tmp, size, value); return tmp; }
static void powerpc_rule_div255w (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = orc_compiler_get_temp_reg (p); int tmp2 = orc_compiler_get_temp_reg (p); int tmpc; tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_W, 0x0080); powerpc_emit_VX_2 (p, "vadduhm", 0x10000040, dest, src1, tmpc); ORC_ASM_CODE(p," vspltish %s, 8\n", powerpc_get_regname(tmp2)); powerpc_emit_VX(p, 0x1000034c, powerpc_regnum(tmp2), 8, 0); powerpc_emit_VX_2 (p, "vsrh", 0x10000244, tmp, dest, tmp2); powerpc_emit_VX_2 (p, "vadduhm", 0x10000040, dest, dest, tmp); powerpc_emit_VX_2 (p, "vsrh", 0x10000244, dest, dest, tmp2); }
static void powerpc_rule_divf (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); int y = orc_compiler_get_temp_reg (p); int t = orc_compiler_get_temp_reg (p); int c1; int c0; c1 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x3f800000); /* 1.0 */ powerpc_emit_VX_db (p, "vrefp", 0x1000010a, y, src2); powerpc_emit_VA_acb (p, "vnmsubfp", 0x1000002f, t, y, c1, src2); powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, y, y, y, t); c0 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x00000000); /* 0.0 */ powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, dest, y, c0, src1); }
static void powerpc_rule_loadX (OrcCompiler *compiler, void *user, OrcInstruction *insn) { OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = src->size << compiler->loop_shift; int perm = orc_compiler_get_temp_reg (compiler); switch (size) { case 1: ORC_ASM_CODE(compiler," lvebx %s, 0, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00000e, powerpc_regnum(dest->alloc), 0, powerpc_regnum(src->ptr_register)); break; case 2: ORC_ASM_CODE(compiler," lvehx %s, 0, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00004e, powerpc_regnum(dest->alloc), 0, powerpc_regnum(src->ptr_register)); break; case 4: ORC_ASM_CODE(compiler," lvewx %s, 0, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc), 0, powerpc_regnum(src->ptr_register)); break; case 8: case 16: ORC_ASM_CODE(compiler," lvx %s, 0, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c0000ce, powerpc_regnum(dest->alloc), 0, powerpc_regnum(src->ptr_register)); break; default: ORC_COMPILER_ERROR(compiler,"bad load size %d", src->size << compiler->loop_shift); break; } ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", powerpc_get_regname (perm), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(perm), 0, powerpc_regnum(src->ptr_register)); powerpc_emit_vperm (compiler, dest->alloc, dest->alloc, dest->alloc, perm); }
static void powerpc_rule_convslq (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int perm; int tmp = orc_compiler_get_temp_reg (p); ORC_ASM_CODE(p," vspltisb %s, -1\n", powerpc_get_regname(tmp)); powerpc_emit_VX(p, 0x1000030c, powerpc_regnum(tmp), 0x1f, 0); powerpc_emit_VX_2 (p, "vsraw", 0x10000384, tmp, src1, tmp); perm = powerpc_get_constant_full (p, 0x10101010, 0x00010203, 0x10101010, 0x04050607); powerpc_emit_vperm (p, dest, src1, tmp, perm); }
static void powerpc_rule_absl (OrcCompiler *p, void *user, OrcInstruction *insn) { int tmp; int tmpc; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0); if (src1 != dest) { tmp = dest; } else { tmp = orc_compiler_get_temp_reg (p); } powerpc_emit_VX_2 (p, "vsubuwm", 0x10000480, tmp, tmpc, src1); powerpc_emit_VX_2 (p, "vminuw", 0x10000282, dest, tmp, src1); }
static void powerpc_rule_convfl (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = orc_compiler_get_temp_reg (p); int tmpc; int tmpc2; if (p->target_flags & ORC_TARGET_FAST_NAN) { powerpc_emit_VX_dbi (p, "vctsxs", 0x100003ca, dest, src1, 0); } else { /* This changes NANs into infinities of the same sign */ tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x7f800000); tmpc2 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x007fffff); powerpc_emit_VX_2 (p, "vand", 0x10000404, tmp, tmpc, src1); powerpc_emit_VX_2 (p, "vcmpequw", 0x10000086, tmp, tmp, tmpc); powerpc_emit_VX_2 (p, "vand", 0x10000404, tmp, tmp, tmpc2); powerpc_emit_vandc (p, tmp, src1, tmp); powerpc_emit_VX_dbi (p, "vctsxs", 0x100003ca, dest, tmp, 0); } }
int orc_compiler_get_constant (OrcCompiler *compiler, int size, int value) { int i; int tmp; if (size < 4) { if (size < 2) { value &= 0xff; value |= (value<<8); } value &= 0xffff; value |= (value<<16); } for(i=0;i<compiler->n_constants;i++){ if (compiler->constants[i].is_long == FALSE && compiler->constants[i].value == value) { break; } } if (i == compiler->n_constants) { compiler->n_constants++; compiler->constants[i].value = value; compiler->constants[i].alloc_reg = 0; compiler->constants[i].use_count = 0; compiler->constants[i].is_long = FALSE; } compiler->constants[i].use_count++; if (compiler->constants[i].alloc_reg != 0) {; return compiler->constants[i].alloc_reg; } tmp = orc_compiler_get_temp_reg (compiler); orc_compiler_load_constant (compiler, tmp, size, value); return tmp; }
int orc_compiler_get_constant_long (OrcCompiler *compiler, orc_uint32 a, orc_uint32 b, orc_uint32 c, orc_uint32 d) { int i; int tmp; for(i=0;i<compiler->n_constants;i++){ if (compiler->constants[i].is_long == TRUE && compiler->constants[i].full_value[0] == a && compiler->constants[i].full_value[1] == b && compiler->constants[i].full_value[2] == c && compiler->constants[i].full_value[3] == d) { break; } } if (i == compiler->n_constants) { compiler->n_constants++; compiler->constants[i].full_value[0] = a; compiler->constants[i].full_value[1] = b; compiler->constants[i].full_value[2] = c; compiler->constants[i].full_value[3] = d; compiler->constants[i].is_long = TRUE; compiler->constants[i].alloc_reg = 0; compiler->constants[i].use_count = 0; } compiler->constants[i].use_count++; if (compiler->constants[i].alloc_reg != 0) {; return compiler->constants[i].alloc_reg; } tmp = orc_compiler_get_temp_reg (compiler); orc_compiler_load_constant_long (compiler, tmp, &compiler->constants[i]); return tmp; }
static void powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn) { OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = dest->size << compiler->loop_shift; int perm = orc_compiler_get_temp_reg (compiler); int tmp = orc_compiler_get_temp_reg (compiler); ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n", powerpc_get_regname (perm), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(perm), 0, powerpc_regnum(dest->ptr_register)); powerpc_emit_vperm (compiler, tmp, src->alloc, src->alloc, perm); switch (size) { case 1: ORC_ASM_CODE(compiler," stvebx %s, 0, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00010e, powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; case 2: ORC_ASM_CODE(compiler," stvehx %s, 0, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00014e, powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; case 4: ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00018e, powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; case 8: ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00018e, powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); powerpc_emit_D (compiler, "addi", 0x38000000, compiler->gp_tmpreg, POWERPC_R0, 4); ORC_ASM_CODE(compiler," stvewx %s, %s, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00018e, powerpc_regnum(tmp), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(dest->ptr_register)); break; case 16: ORC_ASM_CODE(compiler," stvx %s, 0, %s\n", powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c0001ce, powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; default: ORC_COMPILER_ERROR(compiler,"bad store size %d", dest->size << compiler->loop_shift); break; } }
static void powerpc_rule_loadoffX (OrcCompiler *compiler, void *user, OrcInstruction *insn) { OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = src->size << compiler->loop_shift; int perm = orc_compiler_get_temp_reg (compiler); int offset; if (compiler->vars[insn->src_args[1]].vartype != ORC_VAR_TYPE_CONST) { ORC_COMPILER_ERROR(compiler, "Rule only works with consts"); return; } offset = compiler->vars[insn->src_args[1]].value.i * src->size; powerpc_emit_addi (compiler, compiler->gp_tmpreg, POWERPC_R0, offset); switch (size) { case 1: ORC_ASM_CODE(compiler," lvebx %s, %s, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00000e, powerpc_regnum(dest->alloc), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(src->ptr_register)); break; case 2: ORC_ASM_CODE(compiler," lvehx %s, %s, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00004e, powerpc_regnum(dest->alloc), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(src->ptr_register)); break; case 4: ORC_ASM_CODE(compiler," lvewx %s, %s, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(src->ptr_register)); break; case 8: case 16: ORC_ASM_CODE(compiler," lvx %s, %s, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c0000ce, powerpc_regnum(dest->alloc), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(src->ptr_register)); break; default: ORC_COMPILER_ERROR(compiler,"bad load size %d", src->size << compiler->loop_shift); break; } ORC_ASM_CODE(compiler," lvsl %s, %s, %s\n", powerpc_get_regname (perm), powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (src->ptr_register)); powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(perm), powerpc_regnum(compiler->gp_tmpreg), powerpc_regnum(src->ptr_register)); powerpc_emit_vperm (compiler, dest->alloc, dest->alloc, dest->alloc, perm); }