Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #5
0
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;
  }
}
Example #6
0
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;
    }
  }

}
Example #7
0
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);
}