static void powerpc_rule_swapl (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int perm; perm = powerpc_get_constant_full (p, 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c); powerpc_emit_vperm (p, dest, src1, src1, perm); }
static void powerpc_rule_mergelq (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 perm; perm = powerpc_get_constant_full (p, 0x00010203, 0x10111213, 0x04050607, 0x14151617); powerpc_emit_vperm (p, dest, src1, src2, perm); }
static void powerpc_rule_mergebw (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 perm; perm = powerpc_get_constant_full (p, 0x00100111, 0x02120313, 0x04140515, 0x06160717); powerpc_emit_vperm (p, dest, src1, src2, perm); }
static void powerpc_rule_signl (OrcCompiler *p, void *user, OrcInstruction *insn) { int reg; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); reg = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 1); powerpc_emit_vminsw (p, dest, src1, reg); reg = powerpc_get_constant (p, ORC_CONST_SPLAT_L, -1); powerpc_emit_vmaxsw (p, dest, dest, reg); }
static void powerpc_rule_convulq (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 zero; zero = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 0); perm = powerpc_get_constant_full (p, 0x10101010, 0x00010203, 0x10101010, 0x04050607); powerpc_emit_vperm (p, dest, src1, zero, perm); }
static void powerpc_rule_splatbl (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); #if 0 int perm; perm = powerpc_get_constant_full (p, 0x00000000, 0x01010101, 0x02020202, 0x03030303); powerpc_emit_vperm (p, dest, src1, src1, perm); #else powerpc_emit_VX_2 (p, "vmrghb", 0x1000000c, dest, src1, src1); powerpc_emit_VX_2 (p, "vmrghh", 0x1000004c, dest, dest, dest); #endif }
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_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_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); } }
void orc_arm_emit_loop (OrcCompiler *compiler) { int j; int k; OrcInstruction *insn; OrcStaticOpcode *opcode; OrcRule *rule; for(j=0;j<compiler->n_insns;j++){ insn = compiler->insns + j; opcode = insn->opcode; if (insn->flags & ORC_INSN_FLAG_INVARIANT) continue; orc_compiler_append_code(compiler,"# %d: %s", j, insn->opcode->name); /* set up args */ #if 0 for(k=0;k<opcode->n_src + opcode->n_dest;k++){ args[k] = compiler->vars + insn->args[k]; orc_compiler_append_code(compiler," %d", args[k]->alloc); if (args[k]->is_chained) { orc_compiler_append_code(compiler," (chained)"); } } #endif orc_compiler_append_code(compiler,"\n"); for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){ if (opcode->src_size[k] == 0) continue; switch (compiler->vars[insn->src_args[k]].vartype) { case ORC_VAR_TYPE_SRC: case ORC_VAR_TYPE_DEST: //orc_arm_emit_load_src (compiler, &compiler->vars[insn->src_args[k]]); break; case ORC_VAR_TYPE_CONST: break; case ORC_VAR_TYPE_PARAM: break; case ORC_VAR_TYPE_TEMP: break; default: break; } } rule = insn->rule; if (rule && rule->emit) { int src = ORC_SRC_ARG (compiler, insn, 0); int dest = ORC_DEST_ARG (compiler, insn, 0); if (dest != src) { orc_arm_emit_mov_r (compiler, ORC_ARM_COND_AL, 0, dest, src); } rule->emit (compiler, rule->emit_user, insn); } else { orc_compiler_append_code(compiler,"No rule for: %s\n", opcode->name); } for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){ if (opcode->dest_size[k] == 0) continue; switch (compiler->vars[insn->dest_args[k]].vartype) { case ORC_VAR_TYPE_DEST: //orc_arm_emit_store_dest (compiler, &compiler->vars[insn->dest_args[k]]); break; case ORC_VAR_TYPE_TEMP: break; default: break; } } } for(k=0;k<ORC_N_COMPILER_VARIABLES;k++){ if (compiler->vars[k].name == NULL) continue; if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC || compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) { if (compiler->vars[k].ptr_register) { orc_arm_emit_add_i (compiler, ORC_ARM_COND_AL, 0, compiler->vars[k].ptr_register, compiler->vars[k].ptr_register, compiler->vars[k].size << compiler->loop_shift); } else { //orc_arm_emit_add_imm_memoffset (compiler, orc_arm_ptr_size, // compiler->vars[k].size << compiler->loop_shift, // (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]), // compiler->exec_reg); } } } }