def execute_mtc0( s, inst ): if inst.rd == reg_map['status']: if s.testbin: val = s.rf[inst.rt] if val == 0: print " [ passed ] %s" % s.exe_name else: line_num = 0x7fffffff & val print " [ FAILED ] %s (line %s)" % (s.exe_name, line_num) s.running = False else: print 'SETTING STATUS' s.status = s.rf[inst.rt] elif inst.rd == reg_map['statsen']: s.stats_en = s.rf[inst.rt] elif inst.rd == reg_map['c0_staten']: s.stats_en = s.rf[inst.rt] #elif inst.rd == 2: pass # if sink[ s.sink_ptr ] != s.rf[ inst.rt ]: # print 'sink:', sink[ s.sink_ptr ], 's.rf:', s.rf[ inst.rt ] # raise Exception('Instruction: mtc0 failed!') # print 'SUCCESS: s.rf[' + str( inst.rt ) + '] == ' + str( sink[ s.sink_ptr ] ) # s.sink_ptr += 1 else: raise FatalError('Invalid mtc0 destination: %d!' % inst.rd ) s.pc += 4
def execute_mul(s, inst): if condition_passed(s, inst.cond()): Rm, Rs = s.rf[inst.rm()], s.rf[inst.rs()] result = trim_32(Rm * Rs) s.rf[inst.rn()] = result if inst.S(): if inst.rn() == 15: raise FatalError('UNPREDICTABLE') if inst.rm() == 15: raise FatalError('UNPREDICTABLE') if inst.rs() == 15: raise FatalError('UNPREDICTABLE') s.N = (result >> 31) & 1 s.Z = result == 0 if inst.rd() == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_sret(s, inst): if s.prv == PRV_M: s.pc = s.mepc elif s.prv == PRV_S: s.pc = s.sepc else: raise FatalError("sret encountered on privilege level %d" % s.prv)
def execute_mla(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') Rm, Rs, Rd = s.rf[inst.rm], s.rf[inst.rs], s.rf[inst.rd] result = trim_32(Rm * Rs + Rd) s.rf[inst.rn] = result if inst.S: s.N = (result >> 31) & 1 s.Z = result == 0 s.rf[PC] = s.fetch_pc() + 4
def execute_mrs(s, inst): if condition_passed(s, inst.cond): if inst.R: raise FatalError('Cannot read SPSR in "mrs"') else: s.rf[inst.rd] = s.cpsr() s.rf[PC] = s.fetch_pc() + 4
def execute_bx(s, inst): if condition_passed(s, inst.cond()): s.T = s.rf[inst.rm()] & 0x00000001 s.rf[PC] = s.rf[inst.rm()] & 0xFFFFFFFE if s.T: raise FatalError("Entering THUMB mode! Unsupported!") # no pc + 4 on success else: s.rf[PC] = s.fetch_pc() + 4
def execute_smull(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = signed(s.rf[inst.rm]), signed(s.rf[inst.rs]) result = Rm * Rs if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[RdHi] = trim_32(result >> 32) s.rf[RdLo] = trim_32(result) if inst.S: s.N = (result >> 63) & 1 s.Z = result == 0 s.rf[PC] = s.fetch_pc() + 4
def execute_umull(s, inst): if condition_passed(s, inst.cond()): if inst.rd() == 15: raise FatalError('UNPREDICTABLE') if inst.rm() == 15: raise FatalError('UNPREDICTABLE') if inst.rs() == 15: raise FatalError('UNPREDICTABLE') if inst.rn() == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn(), inst.rd() Rm, Rs = s.rf[inst.rm()], s.rf[inst.rs()] result = Rm * Rs if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[RdHi] = trim_32(result >> 32) s.rf[RdLo] = trim_32(result) if inst.S(): s.N = (result >> 63) & 1 s.Z = (s.rf[RdHi] == s.rf[RdLo] == 0) s.rf[PC] = s.fetch_pc() + 4
def execute_umlal(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = s.rf[inst.rm], s.rf[inst.rs] accumulate = (s.rf[RdHi] << 32) | s.rf[RdLo] result = (Rm * Rs) + accumulate if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[RdHi] = trim_32(result >> 32) s.rf[RdLo] = trim_32(result) if inst.S: s.N = (result >> 63) & 1 s.Z = (s.rf[RdHi] == s.rf[RdLo] == 0) s.rf[PC] = s.fetch_pc() + 4
def execute_ldrb(s, inst): if condition_passed(s, inst.cond()): if inst.rd() == 15: raise FatalError('UNPREDICTABLE') addr = addressing_mode_2(s, inst) # TODO: support multiple memory accessing modes? # MemoryAccess( s.B, s.E ) s.rf[inst.rd()] = s.mem.read(addr, 1) s.rf[PC] = s.fetch_pc() + 4
def do_syscall(s, syscall_num): if syscall_num not in syscall_funcs: raise FatalError("Syscall %d not implemented!" % syscall_num) if s.debug.enabled('syscalls'): print syscall_num, syscall_names[syscall_num], print '%s %s %s %s' % (hex(s.rf[0]), hex(s.rf[1]), hex( s.rf[2]), hex(s.rf[3])), syscall_funcs[syscall_num](s) if s.debug.enabled('syscalls'): if s.debug.enabled('insts'): print ' = ', hex(s.rf[a0]), else: print ' = ', hex(s.rf[a0])
def execute_ldrsh(s, inst): if condition_passed(s, inst.cond()): if inst.rd() == 15: raise FatalError('UNPREDICTABLE') addr = addressing_mode_3(s, inst) # TODO: support multiple memory accessing modes? # MemoryAccess( s.B, s.E ) # TODO: alignment fault checking? # if (CP15_reg1_Ubit == 0) and address[0] == 0b1: # UNPREDICTABLE s.rf[inst.rd()] = sign_extend_half(s.mem.read(addr, 2)) s.rf[PC] = s.fetch_pc() + 4
def execute_bic(s, inst): if condition_passed(s, inst.cond): a, (b, cout) = s.rf[inst.rn], shifter_operand(s, inst) result = a & trim_32(~b) s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def get_mcpuid(self): if self.state.xlen == 32: base = 0b00 # TODO: not currently representing RV32E elif self.state.xlen == 64: base = 0b10 elif self.state.xlen == 128: base = 0b11 else: raise FatalError("XLEN=%d not supported" % self.state.xlen) extensions = 0 for e in self.state.extensions: extensions |= 1 << (ord(e) - ord("a")) return r_uint((base << (self.state.xlen - 2)) | extensions)
def execute_sbc(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = intmask(a - b - (not s.C)) s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not_borrow_from(result) s.V = overflow_from_sub(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_mvn(s, inst): if condition_passed(s, inst.cond): a, cout = shifter_operand(s, inst) result = trim_32(~a) s.rf[inst.rd] = result if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout s.V = s.V if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_adc(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = a + b + s.C s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = carry_from(result) s.V = overflow_from_add(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_orr(s, inst): if condition_passed(s, inst.cond()): a, (b, cout) = s.rf[inst.rn()], shifter_operand(s, inst) result = a | b s.rf[inst.rd()] = trim_32(result) if inst.S(): if inst.rd() == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout s.V = s.V if inst.rd() == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_rsc(s, inst): if condition_passed(s, inst.cond()): a, (b, _) = s.rf[inst.rn()], shifter_operand(s, inst) result = b - a - (not s.C) s.rf[inst.rd()] = trim_32(result) if inst.S(): if inst.rd() == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not borrow_from(result) s.V = overflow_from_sub(b, a, result) if inst.rd() == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_mov(s, inst): if condition_passed(s, inst.cond()): if inst.rd() == 15 and inst.S(): # if not CurrentModeHasSPSR(): CPSR = SPSR # else: UNPREDICTABLE raise FatalError('UNPREDICTABLE in user and system mode!') result, cout = shifter_operand(s, inst) s.rf[inst.rd()] = trim_32(result) if inst.S(): s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout s.V = s.V if inst.rd() == 15: return s.rf[PC] = s.fetch_pc() + 4
def addressing_mode_3(s, inst): if inst.SH == 0b00: raise FatalError('Not a load/store instruction!') # Immediate vs. Register Offset if inst.B: index = (inst.imm_H << 4) | inst.imm_L else: index = s.rf[inst.rm] Rn = s.rf[inst.rn] offset_addr = Rn + index if inst.U else Rn - index # Offset Addressing/Pre-Indexed Addressing vs. Post-Indexed Addressing if inst.P: addr = offset_addr else: addr = Rn # Offset Addressing vs. Pre-/Post-Indexed Addressing if not (inst.P ^ inst.W): s.rf[inst.rn] = trim_32(offset_addr) return trim_32(addr)
def shifter_operand_reg(s, inst): shift_op = inst.shift Rm = s.rf[inst.rm] Rs = s.rf[inst.rs] & 0xFF out = cout = 0 if shift_op == LOGIC_SHIFT_LEFT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm << Rs, (Rm >> 32 - Rs) & 1 elif Rs == 32: out, cout = 0, (Rm) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == LOGIC_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm >> Rs, (Rm >> (Rs - 1)) & 1 elif Rs == 32: out, cout = 0, (Rm >> 31) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == ARITH_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out = arith_shift(Rm, Rs) cout = (Rm >> (Rs - 1)) & 1 elif Rs >= 32: out = 0 if ((Rm >> 31) == 0) else 0xFFFFFFFF cout = (Rm >> 31) & 1 elif shift_op == ROTATE_RIGHT: Rs4 = Rs & 0b1111 if Rs == 0: out, cout = Rm, s.C elif Rs4 == 0: out, cout = Rm, (Rm >> 31) & 1 elif Rs4 > 0: out, cout = rotate_right(Rm, Rs4), (Rm >> Rs4 - 1) & 1 else: raise FatalError('Impossible shift_op!') return trim_32(out), cout
def execute_mfc0( s, inst ): #if inst.rd == 1: pass # s.rf[ inst.rt ] = src[ s.src_ptr ] # s.src_ptr += 1 # return actual core id (this is actually thread id) if inst.rd == reg_map['c0_coreid']: s.rf[inst.rt] = 0 elif inst.rd == reg_map['c0_count']: s.rf[inst.rt] = s.num_insts elif inst.rd == reg_map['c0_fromsysc0']: # return actual core id s.rf[inst.rt] = 0 elif inst.rd == reg_map['c0_fromsysc5']: # return core type (always 0 since pydgin has no core type) s.rf[inst.rt] = 0 elif inst.rd == reg_map['c0_numcores']: s.rf[inst.rt] = 1 elif inst.rd == reg_map['c0_counthi']: # print "WARNING: counthi always returns 0..." s.rf[inst.rt] = 0 else: raise FatalError('Invalid mfc0 destination: %d!' % inst.rd ) s.pc += 4
def shifter_operand(s, inst): # 32-bit immediate # http://stackoverflow.com/a/2835503 if inst.I == 1: rotate_imm = inst.rotate operand = rotate_right(inst.imm_8, rotate_imm * 2) if rotate_imm == 0: cout = s.C else: cout = (operand >> 31) & 1 return operand, cout # 32-bit register shifted by 5-bit immediate elif (inst.bits >> 4 & 0b1) == 0: return shifter_operand_imm(s, inst) # 32-bit register shifted by 32-bit register elif (inst.bits >> 7 & 0b1) == 0: return shifter_operand_reg(s, inst) # Arithmetic or Load/Store instruction extension space else: raise FatalError('Not a data-processing instruction! PC: %x' % s.fetch_pc())
def shifter_operand_imm(s, inst): shift_op = inst.shift Rm = s.rf[inst.rm] shift_imm = inst.shift_amt assert 0 <= shift_imm <= 31 if shift_op == LOGIC_SHIFT_LEFT: out = Rm if (shift_imm == 0) else Rm << shift_imm cout = s.C if (shift_imm == 0) else (Rm >> 32 - shift_imm) & 1 elif shift_op == LOGIC_SHIFT_RIGHT: # NOTE: shift_imm == 0 signifies a shift by 32 out = 0 if (shift_imm == 0) else Rm >> shift_imm cout = Rm >> 31 if (shift_imm == 0) else (Rm >> shift_imm - 1) & 1 elif shift_op == ARITH_SHIFT_RIGHT: # NOTE: shift_imm == 0 signifies a shift by 32 if shift_imm == 0: if (Rm >> 31) == 0: out, cout = 0, Rm >> 31 else: out, cout = 0xFFFFFFFF, Rm >> 31 else: out = arith_shift(Rm, shift_imm) cout = (Rm >> shift_imm - 1) & 1 elif shift_op == ROTATE_RIGHT: # NOTE: shift_imm == 0 signifies a rotate right with extend (RRX) if shift_imm == 0: out = (r_uint(s.C) << 31) | (Rm >> 1) cout = Rm & 1 else: out = rotate_right(Rm, shift_imm) cout = (Rm >> shift_imm - 1) & 1 else: raise FatalError('Impossible shift_op!') return trim_32(out), cout
def execute_ldm1(s, inst): if condition_passed(s, inst.cond()): addr, end_addr = addressing_mode_4(s, inst) register_mask = inst.register_list() # TODO: support multiple memory accessing modes? # MemoryAccess( s.B, s.E ) for i in range(15): if register_mask & 0b1: s.rf[i] = s.mem.read(addr, 4) addr += 4 register_mask >>= 1 if register_mask & 0b1: # reg 15 s.rf[PC] = s.mem.read(addr, 4) & 0xFFFFFFFE s.T = s.rf[PC] & 0b1 if s.T: raise FatalError("Entering THUMB mode! Unsupported!") assert end_addr == addr return assert end_addr == addr - 4 s.rf[PC] = s.fetch_pc() + 4
def execute_mrc2(s, inst): raise FatalError('"mrc2" instruction unimplemented!') s.rf[PC] = s.fetch_pc() + 4
def execute_msr(s, inst): raise FatalError('"msr" instruction unimplemented!') if condition_passed(s, inst.cond()): pass s.rf[PC] = s.fetch_pc() + 4
def execute_mfuts( s, inst ): raise FatalError('mfuts is unsupported!') s.pc += 4
def execute_blx1(s, inst): raise FatalError('Called blx1: Entering THUMB mode! Unsupported') s.rf[PC] = s.fetch_pc() + 4