/**
   * Translates the generic instruction <code>instruction</code> into an architecture-specific one.
   * The generated instruction(s) are added to the <code>m_ilOut</code> instruction list.
   *
   * @param instruction The instruction to translate
   */
  private void translateInstruction(Instruction instruction) {
    Intrinsic intrinsic = getIntrinsicForInstruction(instruction);
    if (intrinsic == null) {
      LOGGER.debug(
          StringUtil.concat(
              "No intrinsic found for the instruction ", instruction.getInstructionName()));
      m_ilOut.addInstruction(instruction);
      return;
    }

    // get the source operands, i.e., the instruction arguments
    IOperand[] rgSourceOps = instruction.getOperands();
    IOperand opSourceOutput = rgSourceOps[rgSourceOps.length - 1];

    // get the destination operands, i.e., the arguments of the architecture-specific intrinsic
    Argument[] rgDestArgs = null;
    if (intrinsic.getArguments() != null)
      rgDestArgs = Arguments.parseArguments(intrinsic.getArguments());
    else {
      LOGGER.debug(
          StringUtil.concat(
              "No arguments were defined for the intrinsic ",
              intrinsic.getBaseName(),
              ". Assuming generic arguments."));
      rgDestArgs = InstructionListTranslator.createGenericArguments(rgSourceOps.length);
    }

    // check whether the number of arguments of the instruction and the intrinsic to be generated
    // match
    // the source instruction always has a result operand (the last instruction argument); in the
    // intrinsic
    // the result might be merged into one of the operands, so there might be one argument less
    if (rgSourceOps.length != rgDestArgs.length && rgSourceOps.length - 1 != rgDestArgs.length) {
      LOGGER.error(
          StringUtil.concat(
              "The arguments for the instruction ",
              instruction.toString(),
              " mapped to the intrinsic ",
              intrinsic.getBaseName(),
              " don't match"));
      return;
    }

    boolean bIntrinsicHasSharedResult = rgSourceOps.length - 1 == rgDestArgs.length;
    int nOutputArgDestIndex = InstructionListTranslator.getOutputArgumentIndex(rgDestArgs);

    int[] rgPermSourceToDest = new int[rgSourceOps.length];
    int[] rgPermDestToSource = new int[rgDestArgs.length];
    InstructionListTranslator.getArgumentPermutations(
        intrinsic, rgSourceOps, rgDestArgs, rgPermSourceToDest, rgPermDestToSource);

    if (!bIntrinsicHasSharedResult) {
      // the intrinsic to generate has a distinct output operand

      // if possible, swap commutative operands if that helps saving MOVs
      rgSourceOps =
          InstructionListTranslator.compatibilizeCommutatives(
              intrinsic,
              rgSourceOps,
              rgDestArgs,
              rgPermSourceToDest,
              rgPermDestToSource,
              nOutputArgDestIndex,
              bIntrinsicHasSharedResult);
    } else {
      // the intrinsic to generate has an operand which is used for shared input and output,
      // i.e., upon completion of the instruction, the shared operand is overwritten with the result

      if (opSourceOutput.equals(rgSourceOps[rgPermDestToSource[nOutputArgDestIndex]])) {
        // the argument of the instruction corresponding to the shared intrinsic operand
        // is the same as the instruction's result argument
      } else {
        if (rgSourceOps[rgSourceOps.length - 1] instanceof IOperand.IRegisterOperand) {
          // if possible, swap commutative operands if that helps saving MOVs
          rgSourceOps =
              InstructionListTranslator.compatibilizeCommutatives(
                  intrinsic,
                  rgSourceOps,
                  rgDestArgs,
                  rgPermSourceToDest,
                  rgPermDestToSource,
                  nOutputArgDestIndex,
                  bIntrinsicHasSharedResult);
        }
      }
    }

    createInstructions(
        instruction,
        intrinsic,
        rgSourceOps,
        rgDestArgs,
        rgPermSourceToDest,
        rgPermDestToSource,
        nOutputArgDestIndex,
        bIntrinsicHasSharedResult);
  }
Пример #2
0
 /**
  * Creates a copy of <code>instruction</code>. The operands are <b>not</b> deep-copied.
  *
  * @param instruction The instruction to copy
  */
 public Instruction(Instruction instruction) {
   this(instruction.getInstructionName(), instruction.getIntrinsic(), instruction.getOperands());
 }
 /**
  * Finds the intrinsic for the instruction <code>instruction</code>.
  *
  * @param instruction The instruction for which to find the corresponding intrinsic.
  * @return The instrinsic corresponding to the instruction <code>instruction</code>
  */
 private Intrinsic getIntrinsicForInstruction(Instruction instruction) {
   return m_data
       .getArchitectureDescription()
       .getIntrinsic(instruction.getInstructionName(), m_specDatatype);
 }