/*
Copyright 2011-2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.google.security.zynamics.reil.translators.ppc;
import com.google.security.zynamics.reil.OperandSize;
import com.google.security.zynamics.reil.ReilHelpers;
import com.google.security.zynamics.reil.ReilInstruction;
import com.google.security.zynamics.reil.translators.ITranslationEnvironment;
import com.google.security.zynamics.reil.translators.InternalTranslationException;
import com.google.security.zynamics.reil.translators.TranslationHelpers;
import com.google.security.zynamics.zylib.disassembly.IInstruction;
import com.google.security.zynamics.zylib.disassembly.IOperandTreeNode;
import java.util.List;
public class DivGenerator {
public static void generate(long baseOffset, final ITranslationEnvironment environment,
final IInstruction instruction, final List<ReilInstruction> instructions,
final String mnemonic, final boolean isSigned, final boolean setCr, final boolean setOv)
throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, mnemonic);
final IOperandTreeNode registerOperand1 =
instruction.getOperands().get(0).getRootNode().getChildren().get(0);
final IOperandTreeNode registerOperand2 =
instruction.getOperands().get(1).getRootNode().getChildren().get(0);
final IOperandTreeNode registerOperand3 =
instruction.getOperands().get(2).getRootNode().getChildren().get(0);
final String targetRegister = registerOperand1.getValue();
final String dividend = registerOperand2.getValue();
final String divisor = registerOperand3.getValue();
final OperandSize dw = OperandSize.DWORD;
final OperandSize wd = OperandSize.WORD;
final OperandSize bt = OperandSize.BYTE;
final String crTemp = setCr ? environment.getNextVariableString() : null;
final String zeroCheck = environment.getNextVariableString();
final String overflowTmp1 = setOv && isSigned ? environment.getNextVariableString() : null;
final String overflowTmp2 = setOv && isSigned ? environment.getNextVariableString() : null;
final String overflowTmp3 = setOv && isSigned ? environment.getNextVariableString() : null;
final String overflowTmp4 = setOv && isSigned ? environment.getNextVariableString() : null;
final String overflowTmp5 = setOv && isSigned ? environment.getNextVariableString() : null;
final String overflowTmp6 = setOv && isSigned ? environment.getNextVariableString() : null;
final String dividendMSB = isSigned ? environment.getNextVariableString() : null;
final String divisorMSB = isSigned ? environment.getNextVariableString() : null;
final String newMSB = isSigned ? environment.getNextVariableString() : null;
final String tmpResult = isSigned ? environment.getNextVariableString() : null;
// do zero check on divisor
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, divisor, dw, zeroCheck));
if (isSigned) {
final String firstComplementVar2 = environment.getNextVariableString();
final String secondComplementVar2 = environment.getNextVariableString();
final String finalComplement = environment.getNextVariableString();
final String finalFirstComplement = environment.getNextVariableString();
final String finalSecondComplement = environment.getNextVariableString();
final String firstOneComplement = environment.getNextVariableString();
final String firstTwoComplement = environment.getNextVariableString();
final String secondOneComplement = environment.getNextVariableString();
final String secondTwoComplement = environment.getNextVariableString();
final String shiftedTmpResult = environment.getNextVariableString();
final String allOnes = environment.getNextVariableString();
final String resultOneComplement = environment.getNextVariableString();
final String allOnesCheck = environment.getNextVariableString();
// do check if divisor == 0xFFFFFFFF
instructions.add(ReilHelpers.createXor(baseOffset++, dw, divisor, dw,
String.valueOf(0xFFFFFFFFL), dw, allOnes));
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, allOnes, dw, allOnesCheck));
instructions.add(ReilHelpers.createOr(baseOffset++, dw, zeroCheck, dw, allOnesCheck, dw,
zeroCheck));
// jump away if divisor is == 0
instructions.add(ReilHelpers.createJcc(baseOffset++, dw, zeroCheck, dw,
String.format("%d.%d", instruction.getAddress().toLong(), 23)));
// construct the complement variables
instructions.add(ReilHelpers.createBsh(baseOffset++, dw, dividend, bt, String.valueOf(-31L),
bt, dividendMSB));
instructions.add(ReilHelpers.createBsh(baseOffset++, dw, divisor, bt, String.valueOf(-31L),
bt, divisorMSB));
instructions.add(ReilHelpers.createBisz(baseOffset++, bt, dividendMSB, bt,
firstComplementVar2));
instructions.add(ReilHelpers.createBisz(baseOffset++, bt, divisorMSB, bt,
secondComplementVar2));
instructions.add(ReilHelpers.createAdd(baseOffset++, dw, String.valueOf(0xFFFFFFFFL), bt,
firstComplementVar2, dw, finalFirstComplement));
instructions.add(ReilHelpers.createAnd(baseOffset++, dw, finalFirstComplement, dw,
String.valueOf(0xFFFFFFFFL), dw, finalFirstComplement));
instructions.add(ReilHelpers.createAdd(baseOffset++, dw, String.valueOf(0xFFFFFFFFL), bt,
secondComplementVar2, dw, finalSecondComplement));
instructions.add(ReilHelpers.createAnd(baseOffset++, dw, finalSecondComplement, dw,
String.valueOf(0xFFFFFFFFL), dw, finalSecondComplement));
instructions.add(ReilHelpers.createXor(baseOffset++, bt, dividendMSB, bt, divisorMSB, bt,
newMSB));
instructions.add(ReilHelpers.createXor(baseOffset++, dw, finalFirstComplement, dw,
finalSecondComplement, dw, finalComplement));
instructions.add(ReilHelpers.createXor(baseOffset++, dw, dividend, dw, finalFirstComplement,
dw, firstOneComplement));
instructions.add(ReilHelpers.createXor(baseOffset++, dw, divisor, dw, finalSecondComplement,
dw, secondOneComplement));
instructions.add(ReilHelpers.createAdd(baseOffset++, dw, firstOneComplement, bt, dividendMSB,
dw, firstTwoComplement));
instructions.add(ReilHelpers.createAdd(baseOffset++, dw, secondOneComplement, bt, divisorMSB,
dw, secondTwoComplement));
// perform division
instructions.add(ReilHelpers.createDiv(baseOffset++, dw, firstTwoComplement, dw,
secondTwoComplement, dw, tmpResult));
instructions.add(ReilHelpers.createAnd(baseOffset++, dw, tmpResult, dw,
String.valueOf(0xFFFFFFFFL), dw, shiftedTmpResult));
instructions.add(ReilHelpers.createXor(baseOffset++, dw, shiftedTmpResult, dw,
finalComplement, dw, resultOneComplement));
instructions.add(ReilHelpers.createAdd(baseOffset++, dw, resultOneComplement, bt, newMSB, dw,
tmpResult));
instructions.add(ReilHelpers.createAnd(baseOffset++, dw, tmpResult, dw,
String.valueOf(0xFFFFFFFFL), dw, targetRegister));
} else {
// jump away if divisor == 0
instructions.add(ReilHelpers.createJcc(baseOffset++, dw, zeroCheck, dw,
String.format("%d.%d", instruction.getAddress().toLong(), 3)));
// perform division
instructions.add(ReilHelpers.createDiv(baseOffset++, dw, dividend, dw, divisor, dw,
targetRegister));
}
if (setOv) {
if (isSigned) {
// case where divisor == 0
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, divisor, dw, overflowTmp1));
// case where dividend == 0x8000 0000 and divisor == -1
// divisor
instructions.add(ReilHelpers.createXor(baseOffset++, dw, divisor, dw,
String.valueOf(0xFFFFFFFFL), dw, overflowTmp2));
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, overflowTmp2, dw, overflowTmp3));
// dividend
instructions.add(ReilHelpers.createXor(baseOffset++, dw, dividend, dw,
String.valueOf(0x80000000L), dw, overflowTmp4));
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, overflowTmp4, dw, overflowTmp5));
// combination
instructions.add(ReilHelpers.createAnd(baseOffset++, dw, overflowTmp3, dw, overflowTmp5,
dw, overflowTmp6));
// set XER register according to result
instructions.add(ReilHelpers.createOr(baseOffset++, dw, overflowTmp1, dw, overflowTmp6, bt,
Helpers.XER_OVERFLOW));
instructions.add(ReilHelpers.createOr(baseOffset++, bt, Helpers.XER_OVERFLOW, bt,
Helpers.XER_SUMMARY_OVERFLOW, bt, Helpers.XER_SUMMARY_OVERFLOW));
} else {
// case where divisor == 0
instructions.add(ReilHelpers
.createBisz(baseOffset++, dw, divisor, bt, Helpers.XER_OVERFLOW));
instructions.add(ReilHelpers.createOr(baseOffset++, bt, Helpers.XER_OVERFLOW, bt,
Helpers.XER_SUMMARY_OVERFLOW, bt, Helpers.XER_SUMMARY_OVERFLOW));
}
}
if (setCr) {
// EQ CR0
instructions.add(ReilHelpers.createBisz(baseOffset++, dw, targetRegister, bt,
Helpers.CR0_EQUAL));
// LT CR0
instructions.add(ReilHelpers.createBsh(baseOffset++, dw, targetRegister, wd, "-31", bt,
Helpers.CR0_LESS_THEN));
// GT CR0
instructions.add(ReilHelpers.createOr(baseOffset++, bt, Helpers.CR0_EQUAL, bt,
Helpers.CR0_LESS_THEN, bt, crTemp));
instructions.add(ReilHelpers.createBisz(baseOffset++, bt, crTemp, bt,
Helpers.CR0_GREATER_THEN));
// SO CR0
instructions.add(ReilHelpers.createStr(baseOffset, bt, Helpers.XER_SUMMARY_OVERFLOW, bt,
Helpers.CRO_SUMMARY_OVERFLOW));
}
}
}