static void powerpc_rule_accsadubl (OrcCompiler *p, void *user, OrcInstruction *insn) { int tmp1 = p->tmpreg; int tmp2 = POWERPC_V31; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); powerpc_emit_vmaxub (p, tmp1, src1, src2); powerpc_emit_vminub (p, tmp2, src1, src2); powerpc_emit_vsububm (p, tmp1, tmp1, tmp2); if (p->loop_shift == 0) { powerpc_emit_vxor (p, tmp2, tmp2, tmp2); powerpc_emit_vmrghb (p, tmp1, tmp2, tmp1); powerpc_emit_vmrghh (p, tmp1, tmp2, tmp1); powerpc_emit_vadduwm (p, dest, dest, tmp1); } else if (p->loop_shift == 1) { powerpc_emit_vxor (p, tmp2, tmp2, tmp2); powerpc_emit_vmrghh (p, tmp1, tmp2, tmp1); powerpc_emit_vsum4ubs (p, dest, dest, tmp1); } else { powerpc_emit_vsum4ubs (p, dest, dest, tmp1); } }
static void powerpc_rule_mullw (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 tmp = POWERPC_V0; powerpc_emit_vxor (p, tmp, tmp, tmp); powerpc_emit_vmladduhm (p, dest, src1, src2, POWERPC_V0); }
void orc_compiler_powerpc_assemble (OrcCompiler *compiler) { int j; int k; OrcInstruction *insn; OrcStaticOpcode *opcode; //OrcVariable *args[10]; OrcRule *rule; int label_outer_loop_start; int label_loop_start; int label_leave; int set_vscr = FALSE; label_outer_loop_start = orc_compiler_label_new (compiler); label_loop_start = orc_compiler_label_new (compiler); label_leave = orc_compiler_label_new (compiler); powerpc_emit_prologue (compiler); if (orc_program_has_float (compiler)) { int tmp = POWERPC_V0; set_vscr = TRUE; ORC_ASM_CODE(compiler," vspltish %s, %d\n", powerpc_get_regname(tmp), 1); powerpc_emit_VX(compiler, 0x1000034c, powerpc_regnum(tmp), 1, 0); powerpc_emit_VX_b(compiler, "mtvscr", 0x10000644, tmp); } if (compiler->program->is_2d) { powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m)); powerpc_emit_srawi (compiler, POWERPC_R0, POWERPC_R0, compiler->loop_shift, 1); powerpc_emit_beq (compiler, label_leave); powerpc_emit_stw (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index)); } //powerpc_load_constants (compiler); powerpc_load_inner_constants (compiler); for(k=0;k<4;k++){ OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k]; if (compiler->vars[ORC_VAR_A1 + k].name == NULL) continue; //powerpc_emit_VX_2(p, "vxor", 0x100004c4, reg, reg, reg); powerpc_emit_vxor (compiler, var->alloc, var->alloc, var->alloc); } powerpc_emit_label (compiler, label_outer_loop_start); powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, n)); powerpc_emit_srawi (compiler, POWERPC_R0, POWERPC_R0, compiler->loop_shift, 1); powerpc_emit_beq (compiler, label_leave); powerpc_emit (compiler, 0x7c0903a6); ORC_ASM_CODE (compiler, " mtctr %s\n", powerpc_get_regname(POWERPC_R0)); powerpc_emit_label (compiler, label_loop_start); for(j=0;j<compiler->n_insns;j++){ insn = compiler->insns + j; opcode = insn->opcode; compiler->insn_index = j; ORC_ASM_CODE(compiler,"# %d: %s\n", j, insn->opcode->name); #if 0 /* set up args */ for(k=0;k<opcode->n_src + opcode->n_dest;k++){ args[k] = compiler->vars + insn->args[k]; ORC_ASM_CODE(compiler," %d", args[k]->alloc); if (args[k]->is_chained) { ORC_ASM_CODE(compiler," (chained)"); } } ORC_ASM_CODE(compiler,"\n"); #endif for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){ OrcVariable *var = compiler->vars + insn->src_args[k]; if (opcode->src_size[k] == 0) continue; switch (var->vartype) { case ORC_VAR_TYPE_SRC: case ORC_VAR_TYPE_DEST: //powerpc_emit_load_src (compiler, var); break; case ORC_VAR_TYPE_CONST: break; case ORC_VAR_TYPE_TEMP: break; default: break; } } compiler->min_temp_reg = ORC_VEC_REG_BASE; rule = insn->rule; if (rule) { rule->emit (compiler, rule->emit_user, insn); } else { ORC_ASM_CODE(compiler,"No rule for: %s\n", opcode->name); } for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){ OrcVariable *var = compiler->vars + insn->dest_args[k]; if (opcode->dest_size[k] == 0) continue; switch (var->vartype) { case ORC_VAR_TYPE_DEST: //powerpc_emit_store_dest (compiler, var); 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) { powerpc_emit_addi (compiler, compiler->vars[k].ptr_register, compiler->vars[k].ptr_register, compiler->vars[k].size << compiler->loop_shift); } else { ORC_ASM_CODE(compiler,"ERROR\n"); } } } powerpc_emit_bne (compiler, label_loop_start); if (compiler->program->is_2d) { powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index)); powerpc_emit_addi_rec (compiler, POWERPC_R0, POWERPC_R0, -1); powerpc_emit_beq (compiler, label_leave); powerpc_emit_stw (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index)); 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) { if (compiler->is_64bit) { powerpc_emit_ld (compiler, compiler->vars[k].ptr_register, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k])); } else { powerpc_emit_lwz (compiler, compiler->vars[k].ptr_register, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k])); } powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, strides[k])); powerpc_emit_add (compiler, compiler->vars[k].ptr_register, compiler->vars[k].ptr_register, POWERPC_R0); if (compiler->is_64bit) { powerpc_emit_std (compiler, compiler->vars[k].ptr_register, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k])); } else { powerpc_emit_stw (compiler, compiler->vars[k].ptr_register, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k])); } } else { ORC_ASM_CODE(compiler,"ERROR\n"); } } } powerpc_emit_b (compiler, label_outer_loop_start); } powerpc_emit_label (compiler, label_leave); for(k=0;k<4;k++){ OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k]; if (compiler->vars[ORC_VAR_A1 + k].name == NULL) continue; powerpc_emit_addi (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, accumulators[k])); if (var->size == 2) { powerpc_emit_vxor (compiler, POWERPC_V0, POWERPC_V0, POWERPC_V0); powerpc_emit_vmrghh (compiler, var->alloc, POWERPC_V0, var->alloc); } ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n", powerpc_get_regname (POWERPC_V0), powerpc_get_regname (POWERPC_R0)); powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(POWERPC_V0), 0, powerpc_regnum(POWERPC_R0)); powerpc_emit_vperm (compiler, var->alloc, var->alloc, var->alloc, POWERPC_V0); ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", powerpc_get_regname (var->alloc), powerpc_get_regname (POWERPC_R0)); powerpc_emit_X (compiler, 0x7c00018e, powerpc_regnum(var->alloc), 0, powerpc_regnum(POWERPC_R0)); } if (set_vscr) { int tmp = POWERPC_V0; ORC_ASM_CODE(compiler," vspltisw %s, %d\n", powerpc_get_regname(tmp), 0); powerpc_emit_VX(compiler, 0x1000038c, powerpc_regnum(tmp), 0, 0); powerpc_emit_VX_b(compiler, "mtvscr", 0x10000644, tmp); } powerpc_emit_epilogue (compiler); powerpc_do_fixups (compiler); }