/* 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.mips; 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.IInstructionTranslator; 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 SwlTranslator implements IInstructionTranslator { @Override public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException { TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "swl"); final OperandSize dw = OperandSize.DWORD; final String lastTwoAddressBits = environment.getNextVariableString(); final String shiftValue = environment.getNextVariableString(); final String memoryMaskShiftValue = environment.getNextVariableString(); final String registerShiftAmount = environment.getNextVariableString(); final String memoryContent = environment.getNextVariableString(); final String memoryMask = environment.getNextVariableString(); final String memoryMaskedContent = environment.getNextVariableString(); final String combinedContent = environment.getNextVariableString(); final String registerShiftedContent = environment.getNextVariableString(); final String address = environment.getNextVariableString(); final IOperandTreeNode sourceRegister = instruction.getOperands().get(0).getRootNode().getChildren().get(0); final long baseOffset = ReilHelpers.toReilAddress(instruction.getAddress()).toLong(); long offset = baseOffset; final String extendedValue = SignExtendGenerator.extendAndAdd(offset, environment, instruction.getOperands().get(1), instructions); offset = baseOffset + instructions.size(); instructions.add(ReilHelpers.createAnd(offset++, dw, extendedValue, dw, String.valueOf(0xFFFFFFFCL), dw, address)); instructions.add(ReilHelpers.createLdm(offset++, dw, address, dw, memoryContent)); instructions.add(ReilHelpers.createAnd(offset++, dw, extendedValue, dw, String.valueOf(3L), dw, lastTwoAddressBits)); instructions.add(ReilHelpers.createBsh(offset++, dw, lastTwoAddressBits, dw, String.valueOf(3L), dw, shiftValue)); final String endianess = "little"; if (endianess.equalsIgnoreCase("little")) { // little endianess case // address bits 1:0 00 // register contents 0x11223344 shifted right by 24 -> 0x00000011 // memory contents 0xAABBCCDD masked with 0xFFFFFF00 -> 0xAABBCC00 // both ored -> 0xAABBCCDD11 // anded with register mask 0xFFFFFFFF -> 0xAABBCC11 instructions.add(ReilHelpers.createAdd(offset++, dw, String.valueOf(-24L), dw, shiftValue, dw, registerShiftAmount)); instructions.add(ReilHelpers.createAdd(offset++, dw, String.valueOf(8L), dw, shiftValue, dw, memoryMaskShiftValue)); } else if (endianess.equalsIgnoreCase("big")) { // big endian case // address bits 1:0 // register contents 0x11223344 shifted right by 0 -> 0x11223344 // memory contents 0xAABBCCDD masked with 0x00000000 -> 0x00000000 // both ored -> 0x11223344 // stored to memory instructions.add(ReilHelpers.createSub(offset++, dw, String.valueOf(0L), dw, shiftValue, dw, registerShiftAmount)); instructions.add(ReilHelpers.createSub(offset++, dw, String.valueOf(32L), dw, shiftValue, dw, memoryMaskShiftValue)); } // prepare memory to be correct for storage instructions.add(ReilHelpers.createBsh(offset++, dw, String.valueOf(0xFFFFFFFFL), dw, memoryMaskShiftValue, dw, memoryMask)); instructions.add(ReilHelpers.createAnd(offset++, dw, memoryContent, dw, memoryMask, dw, memoryMaskedContent)); // prepare register for storage instructions.add(ReilHelpers.createBsh(offset++, dw, sourceRegister.getValue(), dw, registerShiftAmount, dw, registerShiftedContent)); // combine memory and register instructions.add(ReilHelpers.createOr(offset++, dw, registerShiftedContent, dw, memoryMaskedContent, dw, combinedContent)); // store to memory instructions.add(ReilHelpers.createStm(offset++, dw, combinedContent, dw, address)); } }