# * -ancilary/faster- ldm/stm versions of memory access (had trouble in past, possibly also due to haphazard abuse of DCLK)
#
# fixme now stuff:
-# * thumb mode get/set_register
-# * thumb to arm mode
+# * thumb mode get/set_register - DONE!
+# * thumb to arm mode - DONE!
# * rethink the whole python/c trade-off for cross-python session debugging
import sys, binascii, struct, time
ARM_WRITE_MEM = ARM_INSTR_STR_R1_r0_4
ARM_INSTR_MRS_R0_CPSR = 0xe10f0000L
ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
-ARM_INSTR_STMIA_R14_r0_rx = 0xE88E0000L # add up to 65k to indicate which registers...
+ARM_INSTR_STMIA_R14_r0_rx = 0xE88e0000L # add up to 65k to indicate which registers...
+ARM_INSTR_LDMIA_R14_r0_rx = 0xE89e0000L # add up to 65k to indicate which registers...
ARM_STORE_MULTIPLE = ARM_INSTR_STMIA_R14_r0_rx
ARM_INSTR_SKANKREGS = 0xE88F7fffL
ARM_INSTR_CLOBBEREGS = 0xE89F7fffL
1<<ENABLE:'ENABLE',
}
+LDM_BITMASKS = [(1<<x)-1 for x in xrange(16)]
+#### TOTALLY BROKEN, NEED VALIDATION AND TESTING
+PCOFF_DBGRQ = 4 * 4
+PCOFF_WATCH = 4 * 4
+PCOFF_BREAK = 4 * 4
+
def debugstr(strng):
print >>sys.stderr,(strng)
self.storedPC = val
def ARMget_register(self, reg):
"""Get an ARM's Register"""
- self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
+ self.writecmd(0x13,GET_REGISTER,1,[reg&0xf])
retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
return retval
def ARMset_register(self, reg, val):
"""Set ARM Registers"""
for x in xrange(15):
if (1<<x) & mask:
- self.ARMset_register(x,regs.pop())
+ self.ARMset_register(x,regs.pop(0))
if (1<<15) & mask: # make sure we set the "static" version of PC or changes will be lost
- self.ARMsetPC(regs.pop())
+ self.ARMsetPC(regs.pop(0))
def ARMdebuginstr(self,instr,bkpt):
if type (instr) == int or type(instr) == long:
instr = struct.pack("<L", instr)
self.ARMeice_write(EICE_WP1CTRLMASK, ctrlmask); # write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
return self.data
def THUMBgetPC(self):
+ THUMB_INSTR_STR_R0_r0 = 0x60006000L
+ THUMB_INSTR_MOV_R0_PC = 0x46b846b8L
+ THUMB_INSTR_BX_PC = 0x47784778L
+ THUMB_INSTR_NOP = 0x1c001c00L
+
r0 = self.ARMget_register(0)
self.ARMdebuginstr(THUMB_INSTR_MOV_R0_PC, 0)
retval = self.ARMget_register(0)
self.ARMset_register(0,r0)
return retval
+ def ARMcapture_system_state(self, pcoffset):
+ if self.ARMget_dbgstate() & DBG_TBIT:
+ pcoffset += 8
+ else:
+ pcoffset += 4
+ self.storedPC = self.ARMget_register(15) + pcoffset
+ self.last_dbg_state = self.ARMget_dbgstate()
def ARMhaltcpu(self):
"""Halt the CPU."""
if not(self.ARMget_dbgstate()&1):
if (self.ARMwaitDBG() == 0):
raise Exception("Timeout waiting to enter DEBUG mode on HALT")
self.ARMset_dbgctrl(0)
- self.last_dbg_state = self.ARMget_dbgstate()
+ self.ARMcapture_system_state(PCOFF_DBGRQ)
if self.last_dbg_state&0x10:
self.storedPC = self.THUMBgetPC()
else:
print hex(self.storedPC)
print hex(self.ARMget_register(15))
print hex(self.ARMchain0(self.storedPC,self.flags)[0])
- self.ARMdebuginstr(THUMB_INSTR_B_IMM | (0x7fc07fc))
+ self.ARMdebuginstr(THUMB_INSTR_B_IMM | (0x7fc07fc),0)
self.ARM_nop()
self.ARMrestart()
r0 = None
if ((self.current_dbgstate & DBG_TBIT)):
debugstr("=== Switching to ARM mode ===")
- #r0 = self.ARMget_register(0)
self.ARM_nop(0)
- #self.ARMdebuginstr(THUMB_INSTR_NOP,0)
- #self.ARMdebuginstr(THUMB_INSTR_STR_R0_r0,0)
- #self.ARMdebuginstr(THUMB_INSTR_MOV_R0_PC,0)
- #self.ARMdebuginstr(THUMB_INSTR_STR_R0_r0,0)
self.ARMdebuginstr(THUMB_INSTR_BX_PC,0)
self.ARM_nop(0)
self.ARM_nop(0)
debugstr("=== Switching to THUMB mode ===")
if ( not (self.current_dbgstate & DBG_TBIT)):
self.storedPC |= 1
+ r0 = self.ARMget_register(0)
self.ARMset_register(0, self.storedPC)
self.ARM_nop(0)
self.ARMdebuginstr(ARM_INSTR_BX_R0,0)
self.ARM_nop(0)
self.ARM_nop(0)
self.resettap()
+ self.ARMset_register(0,r0)
self.current_dbgstate = self.ARMget_dbgstate();
return self.current_dbgstate
def ARMget_regCPSRstr(self):
self.ARMset_register(1, r1); # restore R0 and R1
self.ARMset_register(0, r0);
return retval
-
+ def ARMreadChunk(self, adr, wordcount):
+ """ Only works in ARM mode currently
+ WARNING: Addresses must be word-aligned!
+ """
+ regs = self.ARMget_registers()
+ output = []
+ count = wordcount
+ while (wordcount > 0):
+ count = (wordcount, 0xe)[wordcount>0xd]
+ bitmask = LDM_BITMASKS[count]
+ self.ARMset_register(14,adr)
+ self.ARM_nop(1)
+ self.ARMdebuginstr(ARM_INSTR_LDMIA_R14_r0_rx | bitmask ,0)
+ #FIXME: do we need the extra nop here?
+ self.ARMrestart()
+ self.ARMwaitDBG()
+ output.extend([self.ARMget_register(x) for x in xrange(count)])
+ wordcount -= count
+ adr += count*4
+ #print hex(adr)
+ # FIXME: handle the rest of the wordcount here.
+ self.ARMset_registers(regs,0xe)
+ return output
+ def ARMwriteChunk(self, adr, wordarray):
+ """ Only works in ARM mode currently
+ WARNING: Addresses must be word-aligned!
+ """
+ regs = self.ARMget_registers()
+ wordcount = len(wordarray)
+ while (wordcount > 0):
+ count = (wordcount, 0xe)[wordcount>0xd]
+ bitmask = LDM_BITMASKS[count]
+ self.ARMset_register(14,adr)
+ print len(wordarray),bin(bitmask)
+ self.ARMset_registers(wordarray[:count],bitmask)
+ self.ARM_nop(1)
+ self.ARMdebuginstr(ARM_INSTR_STMIA_R14_r0_rx | bitmask ,0)
+ #FIXME: do we need the extra nop here?
+ self.ARMrestart()
+ self.ARMwaitDBG()
+ wordarray = wordarray[count:]
+ wordcount -= count
+ adr += count*4
+ print hex(adr)
+ # FIXME: handle the rest of the wordcount here.
def ARMwriteMem(self, adr, wordarray):
r0 = self.ARMget_register(0); # store R0 and R1
r1 = self.ARMget_register(1);