Пример #1
0
    def execute(self, simulatorContext):
        if not self._checkCondition(simulatorContext.regs):
            # Nothing to do, instruction not executed
            self.countExecConditionFalse += 1
            return
        self.countExec += 1

        if self.modeWrite:
            if self.usespsr and simulatorContext.regs.mode == "User":
                # Check if SPSR exists (we are not in user mode)
                raise ExecutionException(
                    "Erreur : écriture de SPSR en mode 'User' (ce mode ne possede pas de registre SPSR)"
                )
            if self.flagsOnly:
                if self.imm:
                    valToSet = self.val
                    if self.shift[2] != 0:
                        _unused, valToSet = utils.applyShift(
                            valToSet, self.shift, simulatorContext.regs.C)
                else:
                    valToSet = simulatorContext.regs[
                        self.
                        val] & 0xF0000000  # We only keep the condition flag bits
                if self.usespsr:
                    valToSet |= simulatorContext.regs.SPSR & 0x0FFFFFFF
                else:
                    valToSet |= simulatorContext.regs.CPSR & 0x0FFFFFFF
            else:
                valToSet = simulatorContext.regs[self.val]

            if (valToSet & 0x1F) not in simulatorContext.regs.bits2mode:
                raise ExecutionException(
                    "Erreur : les bits ({:05b}) du mode du {} ne correspondent à aucun mode valide!"
                    .format(valToSet & 0x1F,
                            "SPSR" if self.usespsr else "CPSR"))

            if self.usespsr:
                simulatorContext.regs.SPSR = valToSet
            else:
                if not simulatorContext.allowSwitchModeInUserMode and simulatorContext.regs.mode == "User" and simulatorContext.regs.CPSR & 0x1F != valToSet & 0x1F:
                    raise ExecutionException(
                        "Erreur : tentative de changer le mode du processeur à partir d'un mode non privilégié!"
                    )
                simulatorContext.regs.CPSR = valToSet
        else:  # Read
            if self.usespsr and simulatorContext.regs.mode == "User":
                # Check if SPSR exists (we are not in user mode)
                raise ExecutionException(
                    "Erreur : lecture de SPSR en mode 'User' (ce mode ne possede pas de registre SPSR)"
                )
            else:
                simulatorContext.regs[
                    self.
                    rd] = simulatorContext.regs.SPSR if self.usespsr else simulatorContext.regs.CPSR
Пример #2
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

        disassembly = self.opcode
        description = "<ol>\n"
        disCond, descCond = self._explainCondition()
        description += descCond

        disassembly += disCond
        if self.modeWrite:
            disassembly += " SPSR" if self.usespsr else " CPSR"
            if self.flagsOnly:
                disassembly += "_flg"
                if self.imm:
                    _unused, valToSet = utils.applyShift(
                        self.val, self.shift, simulatorContext.regs.C)
                    description += "<li>Écrit la constante {} dans {}</li>\n".format(
                        valToSet, "SPSR" if self.usespsr else "CPSR")
                    disassembly += ", #{}".format(hex(valToSet))
                else:
                    disassembly += ", R{}".format(self.val)
                    self._writeregs |= utils.registerWithCurrentBank(
                        self.val, bank)
                    description += "<li>Lit la valeur de {}</li>\n".format(
                        utils.regSuffixWithBank(self.val, bank))
                    description += "<li>Écrit les 4 bits les plus significatifs de cette valeur (qui correspondent aux drapeaux) dans {}</li>\n".format(
                        "SPSR" if self.usespsr else "CPSR")
            else:
                description += "<li>Lit la valeur de {}</li>\n".format(
                    utils.regSuffixWithBank(self.val, bank))
                description += "<li>Écrit cette valeur dans {}</li>\n".format(
                    "SPSR" if self.usespsr else "CPSR")
                disassembly += ", R{}".format(self.val)
        else:  # Read
            disassembly += " R{}, {}".format(
                self.rd, "SPSR" if self.usespsr else "CPSR")
            self._writeregs |= utils.registerWithCurrentBank(self.rd, bank)
            description += "<li>Lit la valeur de {}</li>\n".format(
                "SPSR" if self.usespsr else "CPSR")
            description += "<li>Écrit le résultat dans {}</li>\n".format(
                utils.regSuffixWithBank(self.rd, bank))

        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #3
0
    def decode(self):
        instrInt = self.instrInt
        if not utils.checkMask(instrInt, (), (27, 26)):
            raise ExecutionException("Le bytecode à cette adresse ne correspond à aucune instruction valide (2)", 
                                        internalError=False)

        # Retrieve the condition field
        self._decodeCondition()

        # Get the opcode
        self.opcodeNum = (instrInt >> 21) & 0xF
        self.opcode = utils.dataOpcodeMappingR[self.opcodeNum]

        # "Immediate" and "set flags"
        self.imm = bool(instrInt & (1 << 25))
        self.modifyFlags = bool(instrInt & (1 << 20))

        self.rd = (instrInt >> 12) & 0xF    # Destination register
        self.rn = (instrInt >> 16) & 0xF    # First operand register

        if self.imm:
            self.shiftedVal = instrInt & 0xFF
            # see 4.5.3 of ARM doc to understand the * 2
            self.shift = utils.shiftInfo(type="ROR", 
                                            immediate=True, 
                                            value=((instrInt >> 8) & 0xF) * 2)
            self.carryOutImmShift = 0
            if self.shift.value != 0:
                # If it is a constant, we shift as we decode
                self.carryOutImmShift, self.shiftedVal = utils.applyShift(self.shiftedVal, 
                                                                            self.shift, 
                                                                            False)
        else:
            self.op2reg = instrInt & 0xF
            if instrInt & (1 << 4):
                self.shift = utils.shiftInfo(type=utils.shiftMappingR[(instrInt >> 5) & 0x3],
                                                immediate=False,
                                                value=(instrInt >> 8) & 0xF)
            else:
                self.shift = utils.shiftInfo(type=utils.shiftMappingR[(instrInt >> 5) & 0x3],
                                                immediate=True,
                                                value=(instrInt >> 7) & 0x1F)
Пример #4
0
    def execute(self, simulatorContext):
        self.pcmodified = False
        if not self._checkCondition(simulatorContext.regs):
            # Nothing to do, instruction not executed
            self.countExecConditionFalse += 1
            return
        self.countExec += 1

        addr = baseval = simulatorContext.regs[self.basereg]
        if self.imm:
            addr += self.sign * self.offsetImm
        else:
            _, sval = utils.applyShift(simulatorContext.regs[self.offsetReg],
                                       self.offsetRegShift,
                                       simulatorContext.regs.C)
            addr += self.sign * sval

        realAddr = addr if self.pre else baseval
        s = 1 if self.byte else 4
        if self.mode == 'LDR':
            m = simulatorContext.mem.get(realAddr, size=s)
            if m is None:  # No such address in the mapped memory, we cannot continue
                raise ExecutionException(
                    "Tentative de lecture de {} octets à partir de l'adresse {} invalide : mémoire non initialisée"
                    .format(s, realAddr))
            res = struct.unpack("<B" if self.byte else "<I", m)[0]

            simulatorContext.regs[self.rd] = res
            if self.rd == simulatorContext.PC:
                self.pcmodified = True
        else:  # STR
            valWrite = simulatorContext.regs[self.rd]
            if self.rd == simulatorContext.PC and simulatorContext.PCSpecialBehavior:
                valWrite += 4  # Special case for PC (see ARM datasheet, 4.9.4)
            simulatorContext.mem.set(realAddr,
                                     valWrite,
                                     size=1 if self.byte else 4)

        if self.writeback:
            simulatorContext.regs[self.basereg] = addr
Пример #5
0
    def execute(self, simulatorContext):
        self.pcmodified = False
        if not self._checkCondition(simulatorContext.regs):
            # Nothing to do, instruction not executed
            self.countExecConditionFalse += 1
            return
        self.countExec += 1
        
        workingFlags = {}
        workingFlags['C'] = 0
        # "On logical operations, if the S bit is set (and Rd is not R15)
        # the V flag in the CPSR will be unaffected"
        # (ARM Reference 4.5.1)
        workingFlags['V'] = simulatorContext.regs.V
        # Get first operand value
        op1 = simulatorContext.regs[self.rn]
        # Get second operand value
        if self.imm:
            op2 = self.shiftedVal
            if self.shift.value != 0:
                # We change the carry flag only if we did a shift
                workingFlags['C'] = self.carryOutImmShift
            else:
                workingFlags['C'] = simulatorContext.regs.C
        else:
            op2 = simulatorContext.regs[self.op2reg]
            if self.op2reg == simulatorContext.PC and not self.shift.immediate and simulatorContext.PCSpecialBehavior:
                op2 += 4    # Special case for PC where we use PC+12 instead of PC+8 (see 4.5.5 of ARM Instr. set)
            carry, op2 = utils.applyShift(op2, self.shift, simulatorContext.regs.C)
            workingFlags['C'] = bool(carry)

        if self.opcode == "MOV":
            res = op2
        elif self.opcode in ("ADD", "CMN"):
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(op1, op2, 0)
        elif self.opcode in ("SUB", "CMP"):
            # For a subtraction, including the comparison instruction CMP, C is set to 0
            # if the subtraction produced a borrow (that is, an unsigned underflow), and to 1 otherwise.
            # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0801a/CIADCDHH.html
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(op1, ~op2, 1)
        elif self.opcode == "MVN":
            res = ~op2
        elif self.opcode in ("AND", "TST"):
            # These instructions do not affect the V flag (ARM Instr. set, 4.5.1)
            # However, C flag "is set to the carry out from the barrel shifter [if the shift is not LSL #0]" (4.5.1)
            # this was already done when we called _shiftVal
            res = op1 & op2
        elif self.opcode == "ORR":
            res = op1 | op2
        elif self.opcode == "BIC":
            res = op1 & ~op2     # Bit clear?
        elif self.opcode in ("EOR", "TEQ"):
            # These instructions do not affect the C and V flags (ARM Instr. set, 4.5.1)
            res = op1 ^ op2
        elif self.opcode == "RSB":
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(~op1, op2, 1)
        elif self.opcode== "ADC":
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(op1, op2, int(simulatorContext.regs.C))
        elif self.opcode == "SBC":
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(op1, ~op2, int(simulatorContext.regs.C))
        elif self.opcode == "RSC":
            res, workingFlags['C'], workingFlags['V'] = utils.addWithCarry(~op1, op2, int(simulatorContext.regs.C))
        else:
            raise ExecutionException("Mnémonique invalide : {}".format(self.opcode))

        # Get the result back to 32 bits, if applicable (else it's just a no-op)
        res &= 0xFFFFFFFF           

        workingFlags['Z'] = res == 0
         # "N flag will be set to the value of bit 31 of the result" (4.5.1)
        workingFlags['N'] = res & 0x80000000

        if self.modifyFlags:
            if self.rd == simulatorContext.PC:
                # Combining writing to PC and the S flag is a special case (see ARM Instr. set, 4.5.5)
                # "When Rd is R15 and the S flag is set the result of the operation is placed in R15 and
                # the SPSR corresponding to the current mode is moved to the CPSR. This allows state
                # changes which atomically restore both PC and CPSR. This form of instruction should
                # not be used in User mode."
                if simulatorContext.regs.mode == "User":
                    raise ExecutionException("L'utilisation de PC comme registre de destination en combinaison avec la mise a jour des drapeaux est interdite en mode User!")
                if (simulatorContext.regs.SPSR & 0x1F) not in simulatorContext.regs.bits2mode:
                    # The mode in SPSR is invalid
                    raise ExecutionException("SPSR devrait ici être copié dans CPSR, mais le mode contenu dans SPSR est invalide!")
                simulatorContext.regs.CPSR = simulatorContext.regs.SPSR        # Put back the saved SPSR in CPSR
            else:
                simulatorContext.regs.setAllFlags(workingFlags)

        if self.opcode not in ("TST", "TEQ", "CMP", "CMN"):
            # We actually write the result
            simulatorContext.regs[self.rd] = res
            if self.rd == simulatorContext.PC:
                self.pcmodified = True
            # We consider writing into LR as stepping out of a function
            # This does not change anything for the emulation, but has consequences
            # for the emulation stopping criterion
            if self.rd == 14 and simulatorContext.stepCondition > 0:
                simulatorContext.stepCondition -= 1
                if len(simulatorContext.callStack) > 0:
                    simulatorContext.callStack.pop()
Пример #6
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

        disassembly = self.mode
        description = "<ol>\n"
        disCond, descCond = self._explainCondition()
        description += descCond
        disassembly += disCond

        self._readregs = utils.registerWithCurrentBank(self.basereg, bank)
        addr = baseval = simulatorContext.regs[self.basereg]

        description += "<li>Utilise la valeur du registre {} comme adresse de base</li>\n".format(
            utils.regSuffixWithBank(self.basereg, bank))
        descoffset = ""
        if self.imm:
            addr += self.sign * self.offsetImm
            if self.offsetImm > 0:
                if self.sign > 0:
                    descoffset = "<li>Additionne la constante {} à l'adresse de base</li>\n".format(
                        self.offsetImm)
                else:
                    descoffset = "<li>Soustrait la constante {} à l'adresse de base</li>\n".format(
                        self.offsetImm)
        else:
            shiftDesc = utils.shiftToDescription(self.offsetRegShift, bank)
            regDesc = utils.regSuffixWithBank(self.offsetReg, bank)
            if self.sign > 0:
                descoffset = "<li>Additionne le registre {} {} à l'adresse de base</li>\n".format(
                    regDesc, shiftDesc)
            else:
                descoffset = "<li>Soustrait le registre {} {} à l'adresse de base</li>\n".format(
                    regDesc, shiftDesc)

            _, sval = utils.applyShift(simulatorContext.regs[self.offsetReg],
                                       self.offsetRegShift,
                                       simulatorContext.regs.C)
            addr += self.sign * sval
            self._readregs |= utils.registerWithCurrentBank(
                self.offsetReg, bank)

        realAddr = addr if self.pre else baseval
        sizeaccess = 1 if self.byte else 4
        sizedesc = "1 octet" if sizeaccess == 1 else "{} octets".format(
            sizeaccess)

        disassembly += "B" if sizeaccess == 1 else ""
        if self.nonprivileged:
            disassembly += "T"
        disassembly += " R{}, [R{}".format(self.rd, self.basereg)

        if self.mode == 'LDR':
            if self.pre:
                description += descoffset
                description += "<li>Lit {} à partir de l'adresse obtenue (pré-incrément) et stocke le résultat dans {} (LDR)</li>\n".format(
                    sizedesc, utils.regSuffixWithBank(self.rd, bank))
            else:
                description += "<li>Lit {} à partir de l'adresse de base et stocke le résultat dans {} (LDR)</li>\n".format(
                    sizedesc, utils.regSuffixWithBank(self.rd, bank))
                description += descoffset

            self._readmem = set(range(realAddr, realAddr + sizeaccess))
            self._writeregs |= utils.registerWithCurrentBank(self.rd, bank)

            if self.rd == simulatorContext.PC:
                try:
                    m = simulatorContext.mem.get(realAddr,
                                                 size=sizeaccess,
                                                 mayTriggerBkpt=False)
                except ExecutionException as ex:
                    # We do not want to handle user errors here;
                    # If there is an issue with the memory access, we simply carry on
                    pass
                else:
                    if m is not None:
                        res = struct.unpack("<B" if self.byte else "<I", m)[0]
                        self._nextInstrAddr = res

        else:  # STR
            if self.pre:
                description += descoffset
                description += "<li>Copie la valeur du registre {} dans la mémoire, à l'adresse obtenue à l'étape précédente (pré-incrément), sur {} (STR)</li>\n".format(
                    utils.regSuffixWithBank(self.rd, bank), sizedesc)
            else:
                description += "<li>Copie la valeur du registre {} dans la mémoire, à l'adresse de base, sur {} (STR)</li>\n".format(
                    utils.regSuffixWithBank(self.rd, bank), sizedesc)
                description += descoffset

            self._writemem = set(range(realAddr, realAddr + sizeaccess))
            self._readregs |= utils.registerWithCurrentBank(self.rd, bank)

        if self.pre:
            if self.imm:
                if self.offsetImm == 0:
                    disassembly += "]"
                else:
                    disassembly += ", #{}]".format(
                        hex(self.sign * self.offsetImm))
            else:
                disassembly += ", R{}".format(self.offsetReg)
                disassembly += utils.shiftToInstruction(
                    self.offsetRegShift) + "]"
        else:
            # Post (a post-incrementation of 0 is useless)
            disassembly += "]"
            if self.imm and self.offsetImm != 0:
                disassembly += ", #{}".format(hex(self.sign * self.offsetImm))
            elif not self.imm:
                disassembly += ", R{}".format(self.offsetReg)
                disassembly += utils.shiftToInstruction(self.offsetRegShift)

        if self.writeback:
            self._writeregs |= utils.registerWithCurrentBank(
                self.basereg, bank)
            description += "<li>Écrit l'adresse effective dans le registre de base {} (mode writeback)</li>\n".format(
                utils.regSuffixWithBank(self.basereg, bank))
            if self.pre:
                disassembly += "!"

        description += "</ol>"

        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description