示例#1
0
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);
  }
}
示例#2
0
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);
}