Пример #1
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

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

        self._readregs |= utils.registerWithCurrentBank(self.rm, bank)
        self._readregs |= utils.registerWithCurrentBank(self.rs, bank)

        if self.accumulate:
            disassembly = "MLA"
            description += "<li>Effectue une multiplication suivie d'une addition (A*B+C) entre :\n"
            description += "<ol type=\"A\"><li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rm, bank))
            description += "<li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rs, bank))
            description += "<li>Le registre {}</li></ol>\n".format(
                utils.regSuffixWithBank(self.rn, bank))
            if self.modifyFlags:
                disassembly += "S"
                description += "<li>Met à jour les drapeaux de l'ALU en fonction du résultat de l'opération</li>\n"
            disassembly += disCond + " R{}, R{}, R{}, R{} ".format(
                self.rd, self.rm, self.rs, self.rn)
            self._readregs |= utils.registerWithCurrentBank(self.rn, bank)
        else:
            disassembly = "MUL"
            description += "<li>Effectue une multiplication (A*B) entre :\n"
            description += "<ol type=\"A\"><li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rm, bank))
            description += "<li>Le registre {}</li></ol>\n".format(
                utils.regSuffixWithBank(self.rs, bank))
            if self.modifyFlags:
                disassembly += "S"
                description += "<li>Met à jour les drapeaux de l'ALU en fonction du résultat de l'opération</li>\n"
            disassembly += disCond + " R{}, R{}, R{} ".format(
                self.rd, self.rm, self.rs)

        description += "<li>Écrit le résultat dans R{}</li>".format(self.rd)
        self._writeregs |= utils.registerWithCurrentBank(self.rd, bank)

        if self.modifyFlags:
            self._writeflags = {'c', 'z', 'n'}

        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #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 explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

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

        if self.link:
            self._nextInstrAddr = simulatorContext.regs[
                15] - simulatorContext.pcoffset + 4
            disassembly += "L"
            self._writeregs = utils.registerWithCurrentBank(
                14, bank) | utils.registerWithCurrentBank(15, bank)
            self._readregs = utils.registerWithCurrentBank(15, bank)
            description += "<li>Copie la valeur de {}-4 (l'adresse de la prochaine instruction) dans {}</li>\n".format(
                utils.regSuffixWithBank(15, bank),
                utils.regSuffixWithBank(14, bank))

        if self.imm:
            self._nextInstrAddr = simulatorContext.regs[15] + self.offsetImm
            self._writeregs = utils.registerWithCurrentBank(15, bank)
            self._readregs = utils.registerWithCurrentBank(15, bank)
            valAdd = self.offsetImm
            if valAdd < 0:
                description += "<li>Soustrait la valeur {} à {}</li>\n".format(
                    -valAdd, utils.regSuffixWithBank(15, bank))
            else:
                description += "<li>Additionne la valeur {} à {}</li>\n".format(
                    valAdd, utils.regSuffixWithBank(15, bank))
        else:  # BX
            disassembly += "X"
            self._nextInstrAddr = simulatorContext.regs[self.addrReg]
            self._writeregs = utils.registerWithCurrentBank(15, bank)
            self._readregs = utils.registerWithCurrentBank(self.addrReg, bank)
            description += "<li>Copie la valeur de {} dans {}</li>\n".format(
                utils.regSuffixWithBank(self.addrReg, bank),
                utils.regSuffixWithBank(15, bank))

        disassembly += disCond
        disassembly += " {}".format(hex(valAdd)) if self.imm else " {}".format(
            utils.regSuffixWithBank(self.addrReg, bank))

        if not self._checkCondition(simulatorContext.regs):
            self._nextInstrAddr = simulatorContext.regs[
                15] + 4 - simulatorContext.pcoffset

        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #4
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()
        modifiedFlags = {'Z', 'N'}

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

        if self.modifyFlags and self.opcode not in ("TST", "TEQ", "CMP", "CMN"):
            disassembly += "S"

        if self.opcode not in ("MOV", "MVN"):
            self._readregs |= utils.registerWithCurrentBank(self.rn, bank)

        op2desc = ""
        op2dis = ""
        # Get second operand value
        if self.imm:
            op2 = self.shiftedVal
            op2desc = "La constante {}".format(op2)
            op2dis = "#{}".format(hex(op2))
        else:
            self._readregs |= utils.registerWithCurrentBank(self.op2reg, bank)
            
            if self.shift.type != "LSL" or self.shift.value > 0 or not self.shift.immediate:
                modifiedFlags.add('C')

            shiftDesc = utils.shiftToDescription(self.shift, bank)
            shiftinstr = utils.shiftToInstruction(self.shift)
            op2desc = "Le registre {} {}".format(utils.regSuffixWithBank(self.op2reg, bank), shiftDesc)
            op2dis = "R{}{}".format(self.op2reg, shiftinstr)
            if not self.shift.immediate:
                self._readregs |= utils.registerWithCurrentBank(self.shift.value, bank)
            op2 = simulatorContext.regs[self.op2reg]

        if 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
            description += "<li>Effectue une opération ET entre:\n"
        elif self.opcode in ("EOR", "TEQ"):
            # These instructions do not affect the C and V flags (ARM Instr. set, 4.5.1)
            description += "<li>Effectue une opération OU EXCLUSIF (XOR) entre:\n"
        elif self.opcode in ("SUB", "CMP"):
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une soustraction (A-B) entre:\n"
            if self.opcode == "SUB" and self.rd == simulatorContext.PC:
                # We change PC, we show it in the editor
                self._nextInstrAddr = simulatorContext.regs[self.rn] - op2
        elif self.opcode == "RSB":
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une soustraction inverse (B-A) entre:\n"
        elif self.opcode in ("ADD", "CMN"):
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une addition (A+B) entre:\n"
            if self.opcode == "ADD" and self.rd == simulatorContext.PC:
                # We change PC, we show it in the editor
                self._nextInstrAddr = simulatorContext.regs[self.rn] + op2
        elif self.opcode == "ADC":
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une addition avec retenue (A+B+carry) entre:\n"
        elif self.opcode == "SBC":
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une soustraction avec emprunt (A-B+carry) entre:\n"
        elif self.opcode == "RSC":
            modifiedFlags.update(('C', 'V'))
            description += "<li>Effectue une soustraction inverse avec emprunt (B-A+carry) entre:\n"
        elif self.opcode == "ORR":
            description += "<li>Effectue une opération OU entre:\n"
        elif self.opcode == "MOV":
            description += "<li>Lit la valeur de :\n"
            if self.rd == simulatorContext.PC:
                # We change PC, we show it in the editor
                self._nextInstrAddr = op2
        elif self.opcode == "BIC":
            description += "<li>Effectue une opération ET NON entre:\n"
        elif self.opcode == "MVN":
            description += "<li>Effectue une opération NOT sur :\n"
            if self.rd == simulatorContext.PC:
                # We change PC, we show it in the editor
                self._nextInstrAddr = ~op2
        else:
            raise ExecutionException("Mnémonique invalide : {}".format(self.opcode))

        if self.opcode in ("MOV", "MVN"):
            description += "<ol type=\"A\"><li>{}</li></ol>\n".format(op2desc)
            disassembly += " R{}, ".format(self.rd)
        elif self.opcode in ("TST", "TEQ", "CMP", "CMN"):
            description += "<ol type=\"A\"><li>Le registre {}</li><li>{}</li></ol>\n".format(utils.regSuffixWithBank(self.rn, bank), op2desc)
            disassembly += " R{}, ".format(self.rn)
        else:
            description += "<ol type=\"A\"><li>Le registre {}</li>\n".format(utils.regSuffixWithBank(self.rn, bank))
            description += "<li>{}</li></ol>\n".format(op2desc)
            disassembly += " R{}, R{}, ".format(self.rd, self.rn)
        disassembly += op2dis

        description += "</li>\n"

        if self.modifyFlags:
            if self.rd == simulatorContext.PC:
                description += "<li>Copie le SPSR courant dans CPSR</li>\n"
            else:
                self._writeflags = modifiedFlags
                description += "<li>Met à jour les drapeaux de l'ALU en fonction du résultat de l'opération</li>\n"
        if self.opcode not in ("TST", "TEQ", "CMP", "CMN"):
            description += "<li>Écrit le résultat dans {}</li>".format(utils.regSuffixWithBank(self.rd, bank))
            self._writeregs |= utils.registerWithCurrentBank(self.rd, bank)

        description += "</ol>"

        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #5
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

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

        baseAddr = simulatorContext.regs[self.basereg]
        lenAccess = len(self.reglist)

        if self.mode == 'LDR':
            disassembly = "POP" if self.basereg == 13 and self.writeback else "LDM"
        else:
            disassembly = "PUSH" if self.basereg == 13 and self.writeback else "STM"

        if disassembly not in ("PUSH", "POP"):
            if self.pre:
                disassembly += "IB" if self.sign > 0 else "DB"
            else:
                disassembly += "IA" if self.sign > 0 else "DA"

        disassembly += disCond

        # See the explanations in execute() for this line
        transferToUserBank = bank != "User" and self.sbit and (
            self.mode == "STR" or 15 not in self.reglist)
        bankToUse = "User" if transferToUserBank else bank
        incmode = "incrémente" if self.sign > 0 else "décrémente"

        if disassembly[:3] == 'POP':
            description += "<li>Lit la valeur de SP</li>\n"
            description += "<li>Pour chaque registre de la liste suivante, stocke la valeur contenue à l'adresse pointée par SP dans le registre, puis incrémente SP de 4.</li>\n"
        elif disassembly[:4] == 'PUSH':
            description += "<li>Lit la valeur de SP</li>\n"
            description += "<li>Pour chaque registre de la liste suivante, décrémente SP de 4, puis stocke la valeur du registre à l'adresse pointée par SP.</li>\n"
        elif self.mode == "LDR":
            description += "<li>Lit la valeur de {}</li>\n".format(
                utils.regSuffixWithBank(self.basereg, bank))
            description += "<li>Pour chaque registre de la liste suivante, stocke la valeur contenue à l'adresse pointée par {reg} dans le registre, puis {incmode} {reg} de 4.</li>\n".format(
                reg=utils.regSuffixWithBank(self.basereg, bank),
                incmode=incmode)
        else:
            description += "<li>Lit la valeur de {}</li>\n".format(
                utils.regSuffixWithBank(self.basereg, bank))
            description += "<li>Pour chaque registre de la liste suivante, {incmode} {reg} de 4, puis stocke la valeur du registre à l'adresse pointée par {reg}.</li>\n".format(
                reg=utils.regSuffixWithBank(self.basereg, bank),
                incmode=incmode)

        if disassembly[:3] not in ("PUS", "POP"):
            disassembly += " R{}{},".format(self.basereg,
                                            "!" if self.writeback else "")

        listregstxt = " {"
        beginReg, currentReg = None, None
        for reg in self.reglist:
            if beginReg is None:
                beginReg = reg
            elif reg != currentReg + 1:
                listregstxt += "R{}".format(beginReg)
                if currentReg == beginReg:
                    listregstxt += ", "
                elif currentReg - beginReg == 1:
                    listregstxt += ", R{}, ".format(currentReg)
                else:
                    listregstxt += "-R{}, ".format(currentReg)
                beginReg = reg
            currentReg = reg

        if currentReg is None:
            # No register (the last 16 bits are all zeros)
            listregstxt = ""
        else:
            listregstxt += "R{}".format(beginReg)
            if currentReg - beginReg == 1:
                listregstxt += ", R{}".format(currentReg)
            elif currentReg != beginReg:
                listregstxt += "-R{}".format(currentReg)
            listregstxt += "}"

        disassembly += listregstxt
        description += "<li>{}</li>\n".format(listregstxt)
        if self.sbit:
            disassembly += "^"
            if self.mode == "LDR" and 15 in self.reglist:
                description += "<li>Copie du SPSR courant dans le CPSR</li>\n"

        self._readregs |= utils.registerWithCurrentBank(self.basereg, bank)

        # Compute the affected memory areas
        if self.sign > 0:
            if self.pre:
                baseAddr += 4
            endAddr = lenAccess * 4 + baseAddr - 4
        else:
            endAddr = baseAddr
            if self.pre:
                endAddr -= 4
            baseAddr = endAddr - (lenAccess - 1) * 4
        endAddr += 4
        if self.mode == "LDR":
            self._writeregs |= reduce(operator.or_, [
                utils.registerWithCurrentBank(reg, bankToUse)
                for reg in self.reglist
            ])
            self._readmem = set(range(baseAddr, endAddr))
            if simulatorContext.PC in self.reglist:
                try:
                    addrPC = baseAddr + (self.sign *
                                         (len(self.reglist) - 1) * 4)
                    if self.pre:
                        addrPC += self.sign * 4
                    m = simulatorContext.mem.get(addrPC,
                                                 size=4,
                                                 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("<I", m)[0]
                        self._nextInstrAddr = res
        else:
            self._readregs |= reduce(operator.or_, [
                utils.registerWithCurrentBank(reg, bankToUse)
                for reg in self.reglist
            ])
            self._writemem = set(range(baseAddr, endAddr))

        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #6
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()

        self._nextInstrAddr = -1

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

        if self.signed:
            disassembly = "S"
        else:
            disassembly = "U"

        self._readregs |= utils.registerWithCurrentBank(self.rm, bank)
        self._readregs |= utils.registerWithCurrentBank(self.rs, bank)

        if self.accumulate:
            # MLAL
            disassembly += "MLAL" + disCond
            description += "<li>Effectue une multiplication et une addition {} sur 64 bits (A*B+[C,D]) entre :\n".format(
                "signées" if self.signed else "non signées")
            description += "<ol type=\"A\"><li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rm, bank))
            description += "<li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rs, bank))
            description += "<li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rdHi, bank))
            description += "<li>Le registre {}</li></ol>\n".format(
                utils.regSuffixWithBank(self.rdLo, bank))
            self._readregs |= utils.registerWithCurrentBank(self.rdLo, bank)
            self._readregs |= utils.registerWithCurrentBank(self.rdHi, bank)
        else:
            # MULL
            disassembly += "MULL" + disCond
            description += "<li>Effectue une multiplication {} (A*B) entre :\n".format(
                "signée" if self.signed else "non signée")
            description += "<ol type=\"A\"><li>Le registre {}</li>\n".format(
                utils.regSuffixWithBank(self.rm, bank))
            description += "<li>Le registre {}</li></ol>\n".format(
                utils.regSuffixWithBank(self.rs, bank))

        if self.modifyFlags:
            disassembly += "S"
            description += "<li>Met à jour les drapeaux de l'ALU en fonction du résultat de l'opération</li>\n"
        disassembly += " R{}, R{}, R{}, R{} ".format(self.rdLo, self.rdHi,
                                                     self.rm, self.rs)
        description += "<li>Écrit les 32 MSB du résultat dans R{} et les 32 LSB dans R{}</li>".format(
            self.rdHi, self.rdLo)
        self._writeregs |= utils.registerWithCurrentBank(self.rdLo, bank)
        self._writeregs |= utils.registerWithCurrentBank(self.rdHi, bank)

        if self.modifyFlags:
            self._writeflags = set(('z', 'c', 'n'))

        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #7
0
    def explain(self, simulatorContext):
        self.resetAccessStates()
        bank = simulatorContext.regs.mode
        simulatorContext.regs.deactivateBreakpoints()
        
        self._nextInstrAddr = -1

        addr = simulatorContext.regs[self.rn]
        
        disassembly = "SWP"
        description = "<ol>\n"
        disCond, descCond = self._explainCondition()
        description += descCond
        disassembly += disCond
        sizedesc = "1 octet" if self.byte else "4 octets"

        self._readregs |= utils.registerWithCurrentBank(self.rn, bank)
        self._readregs |= utils.registerWithCurrentBank(self.rm, bank)
        self._writeregs |= utils.registerWithCurrentBank(self.rd, bank)

        description += "<li>Lit {} à partir de l'adresse contenue dans {}</li>\n".format(sizedesc, utils.regSuffixWithBank(self.rn, bank))
        if self.byte:
            disassembly += "B"
            description += "<li>Écrit l'octet le moins significatif du registre {} à l'adresse contenue dans {}</li>\n".format(utils.regSuffixWithBank(self.rm, bank), utils.regSuffixWithBank(self.rn, bank))
            description += "<li>Écrit l'octet le moins significatif de la valeur originale en mémoire dans {}</li>\n".format(utils.regSuffixWithBank(self.rd, bank))
            self._readmem = set([addr])
            self._writemem = set([addr])
        else:
            description += "<li>Écrit la valeur du registre {} à l'adresse contenue dans {}</li>\n".format(utils.regSuffixWithBank(self.rm, bank), utils.regSuffixWithBank(self.rn, bank))
            description += "<li>Écrit dans {} la valeur originale de l'adresse contenue dans {}</li>\n".format(utils.regSuffixWithBank(self.rd, bank), utils.regSuffixWithBank(self.rn, bank))
            self._readmem = set(range(addr, addr+4))
            self._writemem = set(range(addr, addr+4))

        disassembly += " R{}, R{}, [R{}]".format(self.rd, self.rm, self.rn)
        description += "</ol>"
        simulatorContext.regs.reactivateBreakpoints()
        return disassembly, description
Пример #8
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