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_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); }
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); }
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_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn) { OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = ORC_PTR_TO_INT(user); if (src->vartype == ORC_VAR_TYPE_PARAM) { int greg = compiler->gp_tmpreg; powerpc_emit_addi (compiler, greg, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutor, params[insn->src_args[0]])); ORC_ASM_CODE(compiler," lvewx %s, 0, %s\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (greg)); powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc), 0, powerpc_regnum(greg)); ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", powerpc_get_regname (POWERPC_V0), powerpc_get_regname (greg)); powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0), 0, powerpc_regnum(greg)); powerpc_emit_vperm (compiler, dest->alloc, dest->alloc, dest->alloc, POWERPC_V0); switch (size) { case 1: ORC_ASM_CODE(compiler," vspltb %s, %s, 3\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (dest->alloc)); powerpc_emit_VX (compiler, 0x1000020c, powerpc_regnum(dest->alloc), 3, powerpc_regnum(dest->alloc)); break; case 2: ORC_ASM_CODE(compiler," vsplth %s, %s, 1\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (dest->alloc)); powerpc_emit_VX (compiler, 0x1000024c, powerpc_regnum(dest->alloc), 1, powerpc_regnum(dest->alloc)); break; case 4: ORC_ASM_CODE(compiler," vspltw %s, %s, 0\n", powerpc_get_regname (dest->alloc), powerpc_get_regname (dest->alloc)); powerpc_emit_VX (compiler, 0x1000028c, powerpc_regnum(dest->alloc), 0, powerpc_regnum(dest->alloc)); break; } } else { int value = src->value.i; switch (size) { case 1: if (value < 16 && value >= -16) { ORC_ASM_CODE(compiler," vspltisb %s, %d\n", powerpc_get_regname(dest->alloc), value&0x1f); powerpc_emit_VX(compiler, 0x1000030c, powerpc_regnum(dest->alloc), value & 0x1f, 0); } else { value &= 0xff; value |= value << 8; value |= value << 16; powerpc_load_long_constant (compiler, dest->alloc, value, value, value, value); } break; case 2: if (value < 16 && value >= -16) { ORC_ASM_CODE(compiler," vspltish %s, %d\n", powerpc_get_regname(dest->alloc), value&0x1f); powerpc_emit_VX(compiler, 0x1000034c, powerpc_regnum(dest->alloc), value & 0x1f, 0); } else { value &= 0xffff; value |= value << 16; powerpc_load_long_constant (compiler, dest->alloc, value, value, value, value); } break; case 4: if (value < 16 && value >= -16) { ORC_ASM_CODE(compiler," vspltisw %s, %d\n", powerpc_get_regname(dest->alloc), value&0x1f); powerpc_emit_VX(compiler, 0x1000038c, powerpc_regnum(dest->alloc), value & 0x1f, 0); } else { powerpc_load_long_constant (compiler, dest->alloc, value, value, value, value); } 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); }