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
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
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
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
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
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
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
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