2008-02-25 11:48:04 -06:00
/***************************************************************************
* Copyright ( C ) 2008 digenius technology GmbH . *
2008-09-20 05:50:53 -05:00
* *
2008-08-19 04:31:51 -05:00
* Copyright ( C ) 2008 Oyvind Harboe oyvind . harboe @ zylin . com *
2008-02-25 11:48:04 -06:00
* *
2008-10-07 06:08:57 -05:00
* Copyright ( C ) 2008 Georg Acher < acher @ in . tum . de > *
* *
2008-02-25 11:48:04 -06:00
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-04 00:46:44 -06:00
2008-02-25 11:48:04 -06:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "arm11.h"
# include "jtag.h"
# include "log.h"
# include <stdlib.h>
# include <string.h>
#if 0
# define _DEBUG_INSTRUCTION_EXECUTION_
# endif
#if 0
2008-10-08 15:16:51 -05:00
# define FNC_INFO LOG_DEBUG("-")
2008-02-25 11:48:04 -06:00
# else
# define FNC_INFO
# endif
# if 1
2008-10-08 15:16:51 -05:00
# define FNC_INFO_NOTIMPLEMENTED do { LOG_DEBUG("NOT IMPLEMENTED"); /*exit(-1);*/ } while (0)
2008-02-25 11:48:04 -06:00
# else
# define FNC_INFO_NOTIMPLEMENTED
# endif
2009-04-27 06:24:01 -05:00
static int arm11_on_enter_debug_state ( arm11_common_t * arm11 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
bool arm11_config_memwrite_burst = true ;
bool arm11_config_memwrite_error_fatal = true ;
u32 arm11_vcr = 0 ;
bool arm11_config_memrw_no_increment = false ;
bool arm11_config_step_irq_enable = false ;
2008-02-29 01:03:28 -06:00
2008-02-25 11:48:04 -06:00
# define ARM11_HANDLER(x) \
2008-10-08 15:16:51 -05:00
. x = arm11_ # # x
2008-02-25 11:48:04 -06:00
target_type_t arm11_target =
{
2008-10-08 15:16:51 -05:00
. name = " arm11 " ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( poll ) ,
ARM11_HANDLER ( arch_state ) ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( target_request_data ) ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( halt ) ,
ARM11_HANDLER ( resume ) ,
ARM11_HANDLER ( step ) ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( assert_reset ) ,
ARM11_HANDLER ( deassert_reset ) ,
ARM11_HANDLER ( soft_reset_halt ) ,
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( get_gdb_reg_list ) ,
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( read_memory ) ,
ARM11_HANDLER ( write_memory ) ,
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( bulk_write_memory ) ,
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( checksum_memory ) ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( add_breakpoint ) ,
ARM11_HANDLER ( remove_breakpoint ) ,
ARM11_HANDLER ( add_watchpoint ) ,
ARM11_HANDLER ( remove_watchpoint ) ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( run_algorithm ) ,
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
ARM11_HANDLER ( register_commands ) ,
ARM11_HANDLER ( target_create ) ,
ARM11_HANDLER ( init_target ) ,
ARM11_HANDLER ( examine ) ,
ARM11_HANDLER ( quit ) ,
2008-02-25 11:48:04 -06:00
} ;
int arm11_regs_arch_type = - 1 ;
enum arm11_regtype
{
2008-10-08 15:16:51 -05:00
ARM11_REGISTER_CORE ,
ARM11_REGISTER_CPSR ,
ARM11_REGISTER_FX ,
ARM11_REGISTER_FPS ,
ARM11_REGISTER_FIQ ,
ARM11_REGISTER_SVC ,
ARM11_REGISTER_ABT ,
ARM11_REGISTER_IRQ ,
ARM11_REGISTER_UND ,
ARM11_REGISTER_MON ,
ARM11_REGISTER_SPSR_FIQ ,
ARM11_REGISTER_SPSR_SVC ,
ARM11_REGISTER_SPSR_ABT ,
ARM11_REGISTER_SPSR_IRQ ,
ARM11_REGISTER_SPSR_UND ,
ARM11_REGISTER_SPSR_MON ,
/* debug regs */
ARM11_REGISTER_DSCR ,
ARM11_REGISTER_WDTR ,
ARM11_REGISTER_RDTR ,
2008-02-25 11:48:04 -06:00
} ;
typedef struct arm11_reg_defs_s
{
2009-04-22 13:39:59 -05:00
char * name ;
u32 num ;
int gdb_num ;
2008-10-08 15:16:51 -05:00
enum arm11_regtype type ;
2008-02-25 11:48:04 -06:00
} arm11_reg_defs_t ;
/* update arm11_regcache_ids when changing this */
static const arm11_reg_defs_t arm11_reg_defs [ ] =
{
2008-10-08 15:16:51 -05:00
{ " r0 " , 0 , 0 , ARM11_REGISTER_CORE } ,
{ " r1 " , 1 , 1 , ARM11_REGISTER_CORE } ,
{ " r2 " , 2 , 2 , ARM11_REGISTER_CORE } ,
{ " r3 " , 3 , 3 , ARM11_REGISTER_CORE } ,
{ " r4 " , 4 , 4 , ARM11_REGISTER_CORE } ,
{ " r5 " , 5 , 5 , ARM11_REGISTER_CORE } ,
{ " r6 " , 6 , 6 , ARM11_REGISTER_CORE } ,
{ " r7 " , 7 , 7 , ARM11_REGISTER_CORE } ,
{ " r8 " , 8 , 8 , ARM11_REGISTER_CORE } ,
{ " r9 " , 9 , 9 , ARM11_REGISTER_CORE } ,
{ " r10 " , 10 , 10 , ARM11_REGISTER_CORE } ,
{ " r11 " , 11 , 11 , ARM11_REGISTER_CORE } ,
{ " r12 " , 12 , 12 , ARM11_REGISTER_CORE } ,
{ " sp " , 13 , 13 , ARM11_REGISTER_CORE } ,
{ " lr " , 14 , 14 , ARM11_REGISTER_CORE } ,
{ " pc " , 15 , 15 , ARM11_REGISTER_CORE } ,
2008-02-25 11:48:04 -06:00
# if ARM11_REGCACHE_FREGS
2008-10-08 15:16:51 -05:00
{ " f0 " , 0 , 16 , ARM11_REGISTER_FX } ,
{ " f1 " , 1 , 17 , ARM11_REGISTER_FX } ,
{ " f2 " , 2 , 18 , ARM11_REGISTER_FX } ,
{ " f3 " , 3 , 19 , ARM11_REGISTER_FX } ,
{ " f4 " , 4 , 20 , ARM11_REGISTER_FX } ,
{ " f5 " , 5 , 21 , ARM11_REGISTER_FX } ,
{ " f6 " , 6 , 22 , ARM11_REGISTER_FX } ,
{ " f7 " , 7 , 23 , ARM11_REGISTER_FX } ,
{ " fps " , 0 , 24 , ARM11_REGISTER_FPS } ,
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
{ " cpsr " , 0 , 25 , ARM11_REGISTER_CPSR } ,
2008-02-25 11:48:04 -06:00
# if ARM11_REGCACHE_MODEREGS
2008-10-08 15:16:51 -05:00
{ " r8_fiq " , 8 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r9_fiq " , 9 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r10_fiq " , 10 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r11_fiq " , 11 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r12_fiq " , 12 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r13_fiq " , 13 , - 1 , ARM11_REGISTER_FIQ } ,
{ " r14_fiq " , 14 , - 1 , ARM11_REGISTER_FIQ } ,
{ " spsr_fiq " , 0 , - 1 , ARM11_REGISTER_SPSR_FIQ } ,
{ " r13_svc " , 13 , - 1 , ARM11_REGISTER_SVC } ,
{ " r14_svc " , 14 , - 1 , ARM11_REGISTER_SVC } ,
{ " spsr_svc " , 0 , - 1 , ARM11_REGISTER_SPSR_SVC } ,
{ " r13_abt " , 13 , - 1 , ARM11_REGISTER_ABT } ,
{ " r14_abt " , 14 , - 1 , ARM11_REGISTER_ABT } ,
{ " spsr_abt " , 0 , - 1 , ARM11_REGISTER_SPSR_ABT } ,
{ " r13_irq " , 13 , - 1 , ARM11_REGISTER_IRQ } ,
{ " r14_irq " , 14 , - 1 , ARM11_REGISTER_IRQ } ,
{ " spsr_irq " , 0 , - 1 , ARM11_REGISTER_SPSR_IRQ } ,
{ " r13_und " , 13 , - 1 , ARM11_REGISTER_UND } ,
{ " r14_und " , 14 , - 1 , ARM11_REGISTER_UND } ,
{ " spsr_und " , 0 , - 1 , ARM11_REGISTER_SPSR_UND } ,
/* ARM1176 only */
{ " r13_mon " , 13 , - 1 , ARM11_REGISTER_MON } ,
{ " r14_mon " , 14 , - 1 , ARM11_REGISTER_MON } ,
{ " spsr_mon " , 0 , - 1 , ARM11_REGISTER_SPSR_MON } ,
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
/* Debug Registers */
{ " dscr " , 0 , - 1 , ARM11_REGISTER_DSCR } ,
{ " wdtr " , 0 , - 1 , ARM11_REGISTER_WDTR } ,
{ " rdtr " , 0 , - 1 , ARM11_REGISTER_RDTR } ,
2008-02-25 11:48:04 -06:00
} ;
enum arm11_regcache_ids
{
2008-10-08 15:16:51 -05:00
ARM11_RC_R0 ,
ARM11_RC_RX = ARM11_RC_R0 ,
ARM11_RC_R1 ,
ARM11_RC_R2 ,
ARM11_RC_R3 ,
ARM11_RC_R4 ,
ARM11_RC_R5 ,
ARM11_RC_R6 ,
ARM11_RC_R7 ,
ARM11_RC_R8 ,
ARM11_RC_R9 ,
ARM11_RC_R10 ,
ARM11_RC_R11 ,
ARM11_RC_R12 ,
ARM11_RC_R13 ,
ARM11_RC_SP = ARM11_RC_R13 ,
ARM11_RC_R14 ,
ARM11_RC_LR = ARM11_RC_R14 ,
ARM11_RC_R15 ,
ARM11_RC_PC = ARM11_RC_R15 ,
2008-02-25 11:48:04 -06:00
# if ARM11_REGCACHE_FREGS
2008-10-08 15:16:51 -05:00
ARM11_RC_F0 ,
ARM11_RC_FX = ARM11_RC_F0 ,
ARM11_RC_F1 ,
ARM11_RC_F2 ,
ARM11_RC_F3 ,
ARM11_RC_F4 ,
ARM11_RC_F5 ,
ARM11_RC_F6 ,
ARM11_RC_F7 ,
ARM11_RC_FPS ,
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
ARM11_RC_CPSR ,
2008-02-25 11:48:04 -06:00
# if ARM11_REGCACHE_MODEREGS
2008-10-08 15:16:51 -05:00
ARM11_RC_R8_FIQ ,
ARM11_RC_R9_FIQ ,
ARM11_RC_R10_FIQ ,
ARM11_RC_R11_FIQ ,
ARM11_RC_R12_FIQ ,
ARM11_RC_R13_FIQ ,
ARM11_RC_R14_FIQ ,
ARM11_RC_SPSR_FIQ ,
ARM11_RC_R13_SVC ,
ARM11_RC_R14_SVC ,
ARM11_RC_SPSR_SVC ,
ARM11_RC_R13_ABT ,
ARM11_RC_R14_ABT ,
ARM11_RC_SPSR_ABT ,
ARM11_RC_R13_IRQ ,
ARM11_RC_R14_IRQ ,
ARM11_RC_SPSR_IRQ ,
ARM11_RC_R13_UND ,
ARM11_RC_R14_UND ,
ARM11_RC_SPSR_UND ,
ARM11_RC_R13_MON ,
ARM11_RC_R14_MON ,
ARM11_RC_SPSR_MON ,
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
ARM11_RC_DSCR ,
ARM11_RC_WDTR ,
ARM11_RC_RDTR ,
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
ARM11_RC_MAX ,
2008-02-25 11:48:04 -06:00
} ;
# define ARM11_GDB_REGISTER_COUNT 26
u8 arm11_gdb_dummy_fp_value [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
reg_t arm11_gdb_dummy_fp_reg =
{
2008-10-08 15:16:51 -05:00
" GDB dummy floating-point register " , arm11_gdb_dummy_fp_value , 0 , 1 , 96 , NULL , 0 , NULL , 0
2008-02-25 11:48:04 -06:00
} ;
u8 arm11_gdb_dummy_fps_value [ ] = { 0 , 0 , 0 , 0 } ;
reg_t arm11_gdb_dummy_fps_reg =
{
2008-10-08 15:16:51 -05:00
" GDB dummy floating-point status register " , arm11_gdb_dummy_fps_value , 0 , 1 , 32 , NULL , 0 , NULL , 0
2008-02-25 11:48:04 -06:00
} ;
/** Check and if necessary take control of the system
*
* \ param arm11 Target state variable .
* \ param dscr If the current DSCR content is
2009-04-22 13:39:59 -05:00
* available a pointer to a word holding the
* DSCR can be passed . Otherwise use NULL .
2008-02-25 11:48:04 -06:00
*/
2009-04-27 06:24:01 -05:00
int arm11_check_init ( arm11_common_t * arm11 , u32 * dscr )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
u32 dscr_local_tmp_copy ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ! dscr )
{
2009-04-22 13:39:59 -05:00
dscr = & dscr_local_tmp_copy ;
2009-04-28 02:33:50 -05:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , dscr ) ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ! ( * dscr & ARM11_DSCR_MODE_SELECT ) )
{
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " Bringing target into debug mode " ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
* dscr | = ARM11_DSCR_MODE_SELECT ; /* Halt debug-mode */
arm11_write_DSCR ( arm11 , * dscr ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* add further reset initialization here */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11 - > simulate_reset_on_next_halt = true ;
2008-03-06 06:01:52 -06:00
2009-04-22 13:39:59 -05:00
if ( * dscr & ARM11_DSCR_CORE_HALTED )
{
/** \todo TODO: this needs further scrutiny because
* arm11_on_enter_debug_state ( ) never gets properly called
*/
2008-03-06 06:01:52 -06:00
2009-04-22 13:39:59 -05:00
arm11 - > target - > state = TARGET_HALTED ;
arm11 - > target - > debug_reason = arm11_get_DSCR_debug_reason ( * dscr ) ;
}
else
{
arm11 - > target - > state = TARGET_RUNNING ;
arm11 - > target - > debug_reason = DBG_REASON_NOTHALTED ;
}
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_sc7_clear_vbw ( arm11 ) ;
2008-10-08 15:16:51 -05:00
}
2009-04-27 06:24:01 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
# define R(x) \
2008-10-08 15:16:51 -05:00
( arm11 - > reg_values [ ARM11_RC_ # # x ] )
2008-02-25 11:48:04 -06:00
/** Save processor state.
*
* This is called when the HALT instruction has succeeded
* or on other occasions that stop the processor .
*
*/
2009-04-27 06:24:01 -05:00
static int arm11_on_enter_debug_state ( arm11_common_t * arm11 )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < asizeof ( arm11 - > reg_values ) ; i + + )
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_list [ i ] . valid = 1 ;
arm11 - > reg_list [ i ] . dirty = 0 ;
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* Save DSCR */
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & R ( DSCR ) ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* Save wDTR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( R ( DSCR ) & ARM11_DSCR_WDTR_FULL )
{
2009-04-22 13:39:59 -05:00
arm11_add_debug_SCAN_N ( arm11 , 0x05 , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_IR ( arm11 , ARM11_INTEST , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
scan_field_t chain5_fields [ 3 ] ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_setup_field ( arm11 , 32 , NULL , & R ( WDTR ) , chain5_fields + 0 ) ;
arm11_setup_field ( arm11 , 1 , NULL , NULL , chain5_fields + 1 ) ;
arm11_setup_field ( arm11 , 1 , NULL , NULL , chain5_fields + 2 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_dr_scan_vc ( asizeof ( chain5_fields ) , chain5_fields , TAP_DRPAUSE ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_list [ ARM11_RC_WDTR ] . valid = 0 ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE */
/* ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", but not to issue ITRs
ARM1136 seems to require this to issue ITR ' s as well */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
u32 new_dscr = R ( DSCR ) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* this executes JTAG queue: */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_write_DSCR ( arm11 , new_dscr ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* From the spec:
2009-04-22 13:39:59 -05:00
Before executing any instruction in debug state you have to drain the write buffer .
This ensures that no imprecise Data Aborts can return at a later point : */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: Test drain write buffer. */
2008-02-25 11:48:04 -06:00
#if 0
2008-10-08 15:16:51 -05:00
while ( 1 )
{
2009-04-22 13:39:59 -05:00
/* MRC p14,0,R0,c5,c10,0 */
// arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* mcr 15, 0, r0, cr7, cr10, {4} */
arm11_run_instr_no_data1 ( arm11 , 0xee070f9a ) ;
2008-10-07 06:08:57 -05:00
2009-04-22 13:39:59 -05:00
u32 dscr = arm11_read_DSCR ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " DRAIN, DSCR %08x " , dscr ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT )
{
arm11_run_instr_no_data1 ( arm11 , 0xe320f000 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
dscr = arm11_read_DSCR ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " DRAIN, DSCR %08x (DONE) " , dscr ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
break ;
}
2008-02-25 11:48:04 -06:00
}
# endif
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* save r0 - r14 */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: handle other mode registers */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < 15 ; i + + )
{
2009-04-22 13:39:59 -05:00
/* MCR p14,0,R?,c0,c5,0 */
arm11_run_instr_data_from_core ( arm11 , 0xEE000E15 | ( i < < 12 ) , & R ( RX + i ) , 1 ) ;
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* save rDTR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* check rDTRfull in DSCR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( R ( DSCR ) & ARM11_DSCR_RDTR_FULL )
{
2009-04-22 13:39:59 -05:00
/* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
arm11_run_instr_data_from_core_via_r0 ( arm11 , 0xEE100E15 , & R ( RDTR ) ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_list [ ARM11_RC_RDTR ] . valid = 0 ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* save CPSR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
arm11_run_instr_data_from_core_via_r0 ( arm11 , 0xE10F0000 , & R ( CPSR ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* save PC */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */
arm11_run_instr_data_from_core_via_r0 ( arm11 , 0xE1A0000F , & R ( PC ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* adjust PC depending on ARM state */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( R ( CPSR ) & ARM11_CPSR_J ) /* Java state */
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_values [ ARM11_RC_PC ] - = 0 ;
2008-10-08 15:16:51 -05:00
}
else if ( R ( CPSR ) & ARM11_CPSR_T ) /* Thumb state */
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_values [ ARM11_RC_PC ] - = 4 ;
2008-10-08 15:16:51 -05:00
}
else /* ARM state */
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_values [ ARM11_RC_PC ] - = 8 ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > simulate_reset_on_next_halt )
{
2009-04-22 13:39:59 -05:00
arm11 - > simulate_reset_on_next_halt = false ;
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " Reset c1 Control Register " ) ;
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
/* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
/* MCR p15,0,R0,c1,c0,0 */
arm11_run_instr_data_to_core_via_r0 ( arm11 , 0xee010f10 , 0 ) ;
2008-03-04 00:46:44 -06:00
2008-10-08 15:16:51 -05:00
}
2008-03-04 00:46:44 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_dump_reg_changes ( arm11 ) ;
2009-04-27 06:24:01 -05:00
return ERROR_OK ;
2008-02-29 01:03:28 -06:00
}
2008-02-25 11:48:04 -06:00
2008-02-29 01:03:28 -06:00
void arm11_dump_reg_changes ( arm11_common_t * arm11 )
{
2009-04-27 07:12:44 -05:00
if ( ! ( debug_level > = LOG_LVL_DEBUG ) )
{
return ;
}
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < ARM11_REGCACHE_COUNT ; i + + )
{
2009-04-22 13:39:59 -05:00
if ( ! arm11 - > reg_list [ i ] . valid )
2008-10-08 15:16:51 -05:00
{
2009-04-22 13:39:59 -05:00
if ( arm11 - > reg_history [ i ] . valid )
2009-04-27 07:12:44 -05:00
LOG_DEBUG ( " %8s INVALID (%08x) " , arm11_reg_defs [ i ] . name , arm11 - > reg_history [ i ] . value ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
if ( arm11 - > reg_history [ i ] . valid )
{
if ( arm11 - > reg_history [ i ] . value ! = arm11 - > reg_values [ i ] )
2009-04-27 07:12:44 -05:00
LOG_DEBUG ( " %8s %08x (%08x) " , arm11_reg_defs [ i ] . name , arm11 - > reg_values [ i ] , arm11 - > reg_history [ i ] . value ) ;
2009-04-22 13:39:59 -05:00
}
else
{
2009-04-27 07:12:44 -05:00
LOG_DEBUG ( " %8s %08x (INVALID) " , arm11_reg_defs [ i ] . name , arm11 - > reg_values [ i ] ) ;
2009-04-22 13:39:59 -05:00
}
2008-10-08 15:16:51 -05:00
}
} }
2008-02-25 11:48:04 -06:00
}
/** Restore processor state
*
* This is called in preparation for the RESTART function .
*
*/
2009-04-27 06:24:01 -05:00
int arm11_leave_debug_state ( arm11_common_t * arm11 )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: handle other mode registers */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore R1 - R14 */
{ size_t i ;
for ( i = 1 ; i < 15 ; i + + )
{
2009-04-22 13:39:59 -05:00
if ( ! arm11 - > reg_list [ ARM11_RC_RX + i ] . dirty )
continue ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* MRC p14,0,r?,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee100e15 | ( i < < 12 ) , R ( RX + i ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
// LOG_DEBUG("RESTORE R" ZU " %08x", i, R(RX + i));
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* spec says clear wDTR and rDTR; we assume they are clear as
otherwise our programming would be sloppy */
{
2009-04-27 06:24:01 -05:00
u32 DSCR ;
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & DSCR ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( DSCR & ( ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL ) )
{
LOG_ERROR ( " wDTR/rDTR inconsistent (DSCR %08x) " , DSCR ) ;
}
2008-02-25 11:48:04 -06:00
}
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore original wDTR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ( R ( DSCR ) & ARM11_DSCR_WDTR_FULL ) | | arm11 - > reg_list [ ARM11_RC_WDTR ] . dirty )
{
2009-04-22 13:39:59 -05:00
/* MCR p14,0,R0,c0,c5,0 */
arm11_run_instr_data_to_core_via_r0 ( arm11 , 0xee000e15 , R ( WDTR ) ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore CPSR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MSR CPSR,R0*/
arm11_run_instr_data_to_core_via_r0 ( arm11 , 0xe129f000 , R ( CPSR ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore PC */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MOV PC,R0 */
arm11_run_instr_data_to_core_via_r0 ( arm11 , 0xe1a0f000 , R ( PC ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore R0 */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MRC p14,0,r0,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee100e15 , R ( R0 ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore DSCR */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_write_DSCR ( arm11 , R ( DSCR ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* restore rDTR */
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
if ( R ( DSCR ) & ARM11_DSCR_RDTR_FULL | | arm11 - > reg_list [ ARM11_RC_RDTR ] . dirty )
{
2009-04-22 13:39:59 -05:00
arm11_add_debug_SCAN_N ( arm11 , 0x05 , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_IR ( arm11 , ARM11_EXTEST , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
scan_field_t chain5_fields [ 3 ] ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
u8 Ready = 0 ; /* ignored */
u8 Valid = 0 ; /* ignored */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_setup_field ( arm11 , 32 , & R ( RDTR ) , NULL , chain5_fields + 0 ) ;
arm11_setup_field ( arm11 , 1 , & Ready , NULL , chain5_fields + 1 ) ;
arm11_setup_field ( arm11 , 1 , & Valid , NULL , chain5_fields + 2 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_dr_scan_vc ( asizeof ( chain5_fields ) , chain5_fields , TAP_DRPAUSE ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_record_register_history ( arm11 ) ;
2009-04-27 06:24:01 -05:00
return ERROR_OK ;
2008-02-29 01:03:28 -06:00
}
2008-02-25 11:48:04 -06:00
2008-02-29 01:03:28 -06:00
void arm11_record_register_history ( arm11_common_t * arm11 )
{
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < ARM11_REGCACHE_COUNT ; i + + )
{
2009-04-22 13:39:59 -05:00
arm11 - > reg_history [ i ] . value = arm11 - > reg_values [ i ] ;
arm11 - > reg_history [ i ] . valid = arm11 - > reg_list [ i ] . valid ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11 - > reg_list [ i ] . valid = 0 ;
arm11 - > reg_list [ i ] . dirty = 0 ;
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
}
/* poll current target status */
int arm11_poll ( struct target_s * target )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > trst_active )
2009-04-22 13:39:59 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
2009-04-27 06:24:01 -05:00
u32 dscr ;
2009-04-28 02:33:50 -05:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & dscr ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " DSCR %08x " , dscr ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_check_init ( arm11 , & dscr ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( dscr & ARM11_DSCR_CORE_HALTED )
{
2009-04-22 13:39:59 -05:00
if ( target - > state ! = TARGET_HALTED )
{
enum target_state old_state = target - > state ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " enter TARGET_HALTED " ) ;
target - > state = TARGET_HALTED ;
target - > debug_reason = arm11_get_DSCR_debug_reason ( dscr ) ;
arm11_on_enter_debug_state ( arm11 ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
target_call_event_callbacks ( target ,
old_state = = TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED ) ;
}
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
if ( target - > state ! = TARGET_RUNNING & & target - > state ! = TARGET_DEBUG_RUNNING )
{
LOG_DEBUG ( " enter TARGET_RUNNING " ) ;
target - > state = TARGET_RUNNING ;
target - > debug_reason = DBG_REASON_NOTHALTED ;
}
2008-02-25 11:48:04 -06:00
}
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* architecture specific status reply */
int arm11_arch_state ( struct target_s * target )
{
2009-04-27 07:12:44 -05:00
arm11_common_t * arm11 = target - > arch_info ;
LOG_USER ( " target halted due to %s \n cpsr: 0x%8.8x pc: 0x%8.8x " ,
Jim_Nvp_value2name_simple ( nvp_target_debug_reason , target - > debug_reason ) - > name ,
R ( CPSR ) ,
R ( PC ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* target request support */
int arm11_target_request_data ( struct target_s * target , u32 size , u8 * buffer )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* target execution control */
int arm11_halt ( struct target_s * target )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " target->state: %s " ,
2009-04-22 13:39:59 -05:00
Jim_Nvp_value2name_simple ( nvp_target_state , target - > state ) - > name ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state = = TARGET_UNKNOWN )
{
2009-04-22 13:39:59 -05:00
arm11 - > simulate_reset_on_next_halt = true ;
2008-10-08 15:16:51 -05:00
}
2008-03-04 00:46:44 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state = = TARGET_HALTED )
{
2008-04-04 08:47:38 -05:00
LOG_DEBUG ( " target was already halted " ) ;
return ERROR_OK ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > trst_active )
{
2009-04-22 13:39:59 -05:00
arm11 - > halt_requested = true ;
return ERROR_OK ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-12-13 00:25:50 -06:00
arm11_add_IR ( arm11 , ARM11_HALT , TAP_IDLE ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( jtag_execute_queue ( ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
u32 dscr ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
while ( 1 )
{
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & dscr ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( dscr & ARM11_DSCR_CORE_HALTED )
break ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_on_enter_debug_state ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
enum target_state old_state = target - > state ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
target - > state = TARGET_HALTED ;
target - > debug_reason = arm11_get_DSCR_debug_reason ( dscr ) ;
2008-02-29 01:03:28 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL (
target_call_event_callbacks ( target ,
old_state = = TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED ) ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_resume ( struct target_s * target , int current , u32 address , int handle_breakpoints , int debug_execution )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2009-04-27 06:24:01 -05:00
2009-04-22 13:39:59 -05:00
// LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d",
// current, address, handle_breakpoints, debug_execution);
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " target->state: %s " ,
2009-04-22 13:39:59 -05:00
Jim_Nvp_value2name_simple ( nvp_target_state , target - > state ) - > name ) ;
2008-08-24 13:20:49 -05:00
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
2008-08-17 14:40:17 -05:00
{
LOG_ERROR ( " Target not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ! current )
2009-04-22 13:39:59 -05:00
R ( PC ) = address ;
2008-02-25 11:48:04 -06:00
2009-04-27 07:12:44 -05:00
LOG_DEBUG ( " RESUME PC %08x%s " , R ( PC ) , ! current ? " ! " : " " ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
/* clear breakpoints/watchpoints and VCR*/
arm11_sc7_clear_vbw ( arm11 ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
/* Set up breakpoints */
if ( ! debug_execution )
{
2009-04-22 13:39:59 -05:00
/* check if one matches PC and step over it if necessary */
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
breakpoint_t * bp ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
for ( bp = target - > breakpoints ; bp ; bp = bp - > next )
2008-10-08 15:16:51 -05:00
{
2009-04-22 13:39:59 -05:00
if ( bp - > address = = R ( PC ) )
{
LOG_DEBUG ( " must step over %08x " , bp - > address ) ;
arm11_step ( target , 1 , 0 , 0 ) ;
break ;
}
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
/* set all breakpoints */
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
size_t brp_num = 0 ;
2008-10-07 06:08:57 -05:00
2009-04-22 13:39:59 -05:00
for ( bp = target - > breakpoints ; bp ; bp = bp - > next )
{
arm11_sc7_action_t brp [ 2 ] ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
brp [ 0 ] . write = 1 ;
brp [ 0 ] . address = ARM11_SC7_BVR0 + brp_num ;
brp [ 0 ] . value = bp - > address ;
brp [ 1 ] . write = 1 ;
brp [ 1 ] . address = ARM11_SC7_BCR0 + brp_num ;
brp [ 1 ] . value = 0x1 | ( 3 < < 1 ) | ( 0x0F < < 5 ) | ( 0 < < 14 ) | ( 0 < < 16 ) | ( 0 < < 20 ) | ( 0 < < 21 ) ;
2008-10-07 06:08:57 -05:00
2009-04-22 13:39:59 -05:00
arm11_sc7_run ( arm11 , brp , asizeof ( brp ) ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " Add BP " ZU " at %08x " , brp_num , bp - > address ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
brp_num + + ;
}
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
arm11_sc7_set_vcr ( arm11 , arm11_vcr ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_leave_debug_state ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-12-13 00:25:50 -06:00
arm11_add_IR ( arm11 , ARM11_RESTART , TAP_IDLE ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( jtag_execute_queue ( ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
while ( 1 )
{
2009-04-27 06:24:01 -05:00
u32 dscr ;
2009-04-28 02:33:50 -05:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & dscr ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " DSCR %08x " , dscr ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( dscr & ARM11_DSCR_CORE_RESTARTED )
break ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ! debug_execution )
{
2009-04-22 13:39:59 -05:00
target - > state = TARGET_RUNNING ;
2008-10-14 06:06:30 -05:00
target - > debug_reason = DBG_REASON_NOTHALTED ;
2009-04-22 13:39:59 -05:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_call_event_callbacks ( target , TARGET_EVENT_RESUMED ) ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
target - > state = TARGET_DEBUG_RUNNING ;
2008-10-14 06:06:30 -05:00
target - > debug_reason = DBG_REASON_NOTHALTED ;
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_call_event_callbacks ( target , TARGET_EVENT_RESUMED ) ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_step ( struct target_s * target , int current , u32 address , int handle_breakpoints )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " target->state: %s " ,
2009-04-22 13:39:59 -05:00
Jim_Nvp_value2name_simple ( nvp_target_state , target - > state ) - > name ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( ! current )
2009-04-22 13:39:59 -05:00
R ( PC ) = address ;
2008-02-29 01:03:28 -06:00
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " STEP PC %08x%s " , R ( PC ) , ! current ? " ! " : " " ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: Thumb not supported here */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
u32 next_instruction ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_memory_word ( arm11 , R ( PC ) , & next_instruction ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* skip over BKPT */
if ( ( next_instruction & 0xFFF00070 ) = = 0xe1200070 )
{
2009-04-22 13:39:59 -05:00
R ( PC ) + = 4 ;
arm11 - > reg_list [ ARM11_RC_PC ] . valid = 1 ;
arm11 - > reg_list [ ARM11_RC_PC ] . dirty = 0 ;
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " Skipping BKPT " ) ;
2008-10-08 15:16:51 -05:00
}
/* skip over Wait for interrupt / Standby */
/* mcr 15, 0, r?, cr7, cr0, {4} */
else if ( ( next_instruction & 0xFFFF0FFF ) = = 0xee070f90 )
{
2009-04-22 13:39:59 -05:00
R ( PC ) + = 4 ;
arm11 - > reg_list [ ARM11_RC_PC ] . valid = 1 ;
arm11 - > reg_list [ ARM11_RC_PC ] . dirty = 0 ;
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " Skipping WFI " ) ;
2008-10-08 15:16:51 -05:00
}
/* ignore B to self */
else if ( ( next_instruction & 0xFEFFFFFF ) = = 0xeafffffe )
{
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " Not stepping jump to self " ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
/** \todo TODO: check if break-/watchpoints make any sense at all in combination
* with this . */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively
* the VCR might be something worth looking into . */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* Set up breakpoint for stepping */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_sc7_action_t brp [ 2 ] ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
brp [ 0 ] . write = 1 ;
brp [ 0 ] . address = ARM11_SC7_BVR0 ;
brp [ 0 ] . value = R ( PC ) ;
brp [ 1 ] . write = 1 ;
brp [ 1 ] . address = ARM11_SC7_BCR0 ;
brp [ 1 ] . value = 0x1 | ( 3 < < 1 ) | ( 0x0F < < 5 ) | ( 0 < < 14 ) | ( 0 < < 16 ) | ( 0 < < 20 ) | ( 2 < < 21 ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_sc7_run ( arm11 , brp , asizeof ( brp ) ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* resume */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( arm11_config_step_irq_enable )
R ( DSCR ) & = ~ ARM11_DSCR_INTERRUPTS_DISABLE ; /* should be redundant */
else
R ( DSCR ) | = ARM11_DSCR_INTERRUPTS_DISABLE ;
2009-04-27 06:24:01 -05:00
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_leave_debug_state ( arm11 ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_IR ( arm11 , ARM11_RESTART , TAP_IDLE ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( jtag_execute_queue ( ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/** \todo TODO: add a timeout */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* wait for halt */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
while ( 1 )
{
2009-04-27 06:24:01 -05:00
u32 dscr ;
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_read_DSCR ( arm11 , & dscr ) ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
LOG_DEBUG ( " DSCR %08x " , dscr ) ;
if ( ( dscr & ( ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED ) ) = =
( ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED ) )
break ;
}
/* clear breakpoint */
arm11_sc7_clear_vbw ( arm11 ) ;
/* save state */
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm11_on_enter_debug_state ( arm11 ) ) ;
2009-04-22 13:39:59 -05:00
/* restore default state */
R ( DSCR ) & = ~ ARM11_DSCR_INTERRUPTS_DISABLE ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
// target->state = TARGET_HALTED;
2008-10-08 15:16:51 -05:00
target - > debug_reason = DBG_REASON_SINGLESTEP ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_call_event_callbacks ( target , TARGET_EVENT_HALTED ) ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* target reset control */
int arm11_assert_reset ( struct target_s * target )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
#if 0
2008-10-08 15:16:51 -05:00
/* assert reset lines */
/* resets only the DBGTAP, not the ARM */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
jtag_add_reset ( 1 , 0 ) ;
jtag_add_sleep ( 5000 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
arm11 - > trst_active = true ;
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
if ( target - > reset_halt )
{
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_halt ( target ) ) ;
2008-10-08 15:16:51 -05:00
}
2008-08-05 02:11:12 -05:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_deassert_reset ( struct target_s * target )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
#if 0
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " target->state: %s " ,
2009-04-22 13:39:59 -05:00
Jim_Nvp_value2name_simple ( nvp_target_state , target - > state ) - > name ) ;
2008-08-24 13:20:49 -05:00
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* deassert reset lines */
jtag_add_reset ( 0 , 0 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
arm11 - > trst_active = false ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > halt_requested )
2009-04-22 13:39:59 -05:00
return arm11_halt ( target ) ;
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_soft_reset_halt ( struct target_s * target )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* target register access for gdb */
int arm11_get_gdb_reg_list ( struct target_s * target , struct reg_s * * reg_list [ ] , int * reg_list_size )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
* reg_list_size = ARM11_GDB_REGISTER_COUNT ;
* reg_list = malloc ( sizeof ( reg_t * ) * ARM11_GDB_REGISTER_COUNT ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 16 ; i < 24 ; i + + )
{
2009-04-22 13:39:59 -05:00
( * reg_list ) [ i ] = & arm11_gdb_dummy_fp_reg ;
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
( * reg_list ) [ 24 ] = & arm11_gdb_dummy_fps_reg ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < ARM11_REGCACHE_COUNT ; i + + )
{
2009-04-22 13:39:59 -05:00
if ( arm11_reg_defs [ i ] . gdb_num = = - 1 )
continue ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
( * reg_list ) [ arm11_reg_defs [ i ] . gdb_num ] = arm11 - > reg_list + i ;
2008-10-08 15:16:51 -05:00
} }
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
2008-10-07 06:08:57 -05:00
/* target memory access
2009-04-22 13:39:59 -05:00
* size : 1 = byte ( 8 bit ) , 2 = half - word ( 16 bit ) , 4 = word ( 32 bit )
* count : number of items of < size >
*/
2008-02-25 11:48:04 -06:00
int arm11_read_memory ( struct target_s * target , u32 address , u32 size , u32 count , u8 * buffer )
{
2008-10-08 15:16:51 -05:00
/** \todo TODO: check if buffer cast to u32* and u16* might cause alignment problems */
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " ADDR %08x SIZE %08x COUNT %08x " , address , size , count ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MRC p14,0,r0,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee100e15 , address ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
switch ( size )
{
case 1 :
2009-04-22 13:39:59 -05:00
/** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */
arm11 - > reg_list [ ARM11_RC_R1 ] . dirty = 1 ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
{ size_t i ;
for ( i = 0 ; i < count ; i + + )
{
/* ldrb r1, [r0], #1 */
/* ldrb r1, [r0] */
arm11_run_instr_no_data1 ( arm11 ,
! arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
u32 res ;
/* MCR p14,0,R1,c0,c5,0 */
arm11_run_instr_data_from_core ( arm11 , 0xEE001E15 , & res , 1 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
* buffer + + = res ;
} }
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
break ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
case 2 :
2009-04-22 13:39:59 -05:00
{
arm11 - > reg_list [ ARM11_RC_R1 ] . dirty = 1 ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
u16 * buf16 = ( u16 * ) buffer ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
{ size_t i ;
for ( i = 0 ; i < count ; i + + )
{
/* ldrh r1, [r0], #2 */
arm11_run_instr_no_data1 ( arm11 ,
! arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
u32 res ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* MCR p14,0,R1,c0,c5,0 */
arm11_run_instr_data_from_core ( arm11 , 0xEE001E15 , & res , 1 ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
* buf16 + + = res ;
} }
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
break ;
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
case 4 :
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* LDC p14,c5,[R0],#4 */
/* LDC p14,c5,[R0] */
arm11_run_instr_data_from_core ( arm11 ,
( ! arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00 ) ,
( u32 * ) buffer , count ) ;
break ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_write_memory ( struct target_s * target , u32 address , u32 size , u32 count , u8 * buffer )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " ADDR %08x SIZE %08x COUNT %08x " , address , size , count ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* MRC p14,0,r0,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee100e15 , address ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
switch ( size )
{
case 1 :
2009-04-22 13:39:59 -05:00
{
arm11 - > reg_list [ ARM11_RC_R1 ] . dirty = 1 ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
{ size_t i ;
for ( i = 0 ; i < count ; i + + )
{
/* MRC p14,0,r1,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee101e15 , * buffer + + ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* strb r1, [r0], #1 */
/* strb r1, [r0] */
arm11_run_instr_no_data1 ( arm11 ,
! arm11_config_memrw_no_increment ? 0xe4c01001 : 0xe5c01000 ) ;
} }
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
break ;
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
case 2 :
2009-04-22 13:39:59 -05:00
{
arm11 - > reg_list [ ARM11_RC_R1 ] . dirty = 1 ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
u16 * buf16 = ( u16 * ) buffer ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
{ size_t i ;
for ( i = 0 ; i < count ; i + + )
{
/* MRC p14,0,r1,c0,c5,0 */
arm11_run_instr_data_to_core1 ( arm11 , 0xee101e15 , * buf16 + + ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
/* strh r1, [r0], #2 */
/* strh r1, [r0] */
arm11_run_instr_no_data1 ( arm11 ,
! arm11_config_memrw_no_increment ? 0xe0c010b2 : 0xe1c010b0 ) ;
} }
2008-03-04 00:46:44 -06:00
2009-04-22 13:39:59 -05:00
break ;
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
case 4 :
2009-04-22 13:39:59 -05:00
/** \todo TODO: check if buffer cast to u32* might cause alignment problems */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
if ( ! arm11_config_memwrite_burst )
{
/* STC p14,c5,[R0],#4 */
/* STC p14,c5,[R0]*/
arm11_run_instr_data_to_core ( arm11 ,
( ! arm11_config_memrw_no_increment ? 0xeca05e01 : 0xed805e00 ) ,
( u32 * ) buffer , count ) ;
}
else
{
/* STC p14,c5,[R0],#4 */
/* STC p14,c5,[R0]*/
arm11_run_instr_data_to_core_noack ( arm11 ,
( ! arm11_config_memrw_no_increment ? 0xeca05e01 : 0xed805e00 ) ,
( u32 * ) buffer , count ) ;
}
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
break ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-02-29 01:03:28 -06:00
# if 1
2008-10-08 15:16:51 -05:00
/* r0 verification */
2009-04-22 13:39:59 -05:00
if ( ! arm11_config_memrw_no_increment )
2008-10-08 15:16:51 -05:00
{
2009-04-22 13:39:59 -05:00
u32 r0 ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
/* MCR p14,0,R0,c0,c5,0 */
arm11_run_instr_data_from_core ( arm11 , 0xEE000E15 , & r0 , 1 ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
if ( address + size * count ! = r0 )
{
LOG_ERROR ( " Data transfer failed. (%d) " , ( r0 - address ) - size * count ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
if ( arm11_config_memwrite_burst )
LOG_ERROR ( " use 'arm11 memwrite burst disable' to disable fast burst mode " ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
if ( arm11_config_memwrite_error_fatal )
return ERROR_FAIL ;
}
2008-02-29 01:03:28 -06:00
}
# endif
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
int arm11_bulk_write_memory ( struct target_s * target , u32 address , u32 count , u8 * buffer )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
return arm11_write_memory ( target , address , 4 , count , buffer ) ;
2008-02-25 11:48:04 -06:00
}
int arm11_checksum_memory ( struct target_s * target , u32 address , u32 count , u32 * checksum )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
2008-10-07 06:08:57 -05:00
/* target break-/watchpoint control
2008-02-25 11:48:04 -06:00
* rw : 0 = write , 1 = read , 2 = access
*/
int arm11_add_breakpoint ( struct target_s * target , breakpoint_t * breakpoint )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-29 01:03:28 -06:00
#if 0
2008-10-08 15:16:51 -05:00
if ( breakpoint - > type = = BKPT_SOFT )
{
2009-04-22 13:39:59 -05:00
LOG_INFO ( " sw breakpoint requested, but software breakpoints not enabled " ) ;
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
# endif
2008-10-08 15:16:51 -05:00
if ( ! arm11 - > free_brps )
{
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " no breakpoint unit available for hardware breakpoint " ) ;
2009-04-22 13:39:59 -05:00
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
if ( breakpoint - > length ! = 4 )
{
2009-04-28 02:33:50 -05:00
LOG_DEBUG ( " only breakpoints of four bytes length supported " ) ;
2009-04-22 13:39:59 -05:00
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > free_brps - - ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_remove_breakpoint ( struct target_s * target , breakpoint_t * breakpoint )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
arm11 - > free_brps + + ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_add_watchpoint ( struct target_s * target , watchpoint_t * watchpoint )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_remove_watchpoint ( struct target_s * target , watchpoint_t * watchpoint )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
2008-10-07 06:08:57 -05:00
// HACKHACKHACK - FIXME mode/state
2008-02-25 11:48:04 -06:00
/* target algorithm support */
2008-10-07 06:08:57 -05:00
int arm11_run_algorithm ( struct target_s * target , int num_mem_params , mem_param_t * mem_params ,
int num_reg_params , reg_param_t * reg_params , u32 entry_point , u32 exit_point ,
int timeout_ms , void * arch_info )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-10-07 06:08:57 -05:00
armv4_5_algorithm_t * arm11_algorithm_info = arch_info ;
// enum armv4_5_state core_state = arm11->core_state;
// enum armv4_5_mode core_mode = arm11->core_mode;
u32 context [ 16 ] ;
u32 cpsr ;
int exit_breakpoint_size = 0 ;
int i ;
int retval = ERROR_OK ;
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " Running algorithm " ) ;
2008-10-07 06:08:57 -05:00
if ( arm11_algorithm_info - > common_magic ! = ARMV4_5_COMMON_MAGIC )
{
LOG_ERROR ( " current target isn't an ARMV4/5 target " ) ;
return ERROR_TARGET_INVALID ;
}
2008-02-25 11:48:04 -06:00
2008-10-07 06:08:57 -05:00
if ( target - > state ! = TARGET_HALTED )
{
LOG_WARNING ( " target not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
}
// FIXME
// if (armv4_5_mode_to_number(arm11->core_mode)==-1)
// return ERROR_FAIL;
// Save regs
for ( i = 0 ; i < 16 ; i + + )
{
context [ i ] = buf_get_u32 ( ( u8 * ) ( & arm11 - > reg_values [ i ] ) , 0 , 32 ) ;
LOG_DEBUG ( " Save %i: 0x%x " , i , context [ i ] ) ;
}
cpsr = buf_get_u32 ( ( u8 * ) ( arm11 - > reg_values + ARM11_RC_CPSR ) , 0 , 32 ) ;
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " Save CPSR: 0x%x " , cpsr ) ;
2008-10-07 06:08:57 -05:00
for ( i = 0 ; i < num_mem_params ; i + + )
{
target_write_buffer ( target , mem_params [ i ] . address , mem_params [ i ] . size , mem_params [ i ] . value ) ;
}
// Set register parameters
for ( i = 0 ; i < num_reg_params ; i + + )
{
reg_t * reg = register_get_by_name ( arm11 - > core_cache , reg_params [ i ] . reg_name , 0 ) ;
if ( ! reg )
{
LOG_ERROR ( " BUG: register '%s' not found " , reg_params [ i ] . reg_name ) ;
exit ( - 1 ) ;
}
if ( reg - > size ! = reg_params [ i ] . size )
{
LOG_ERROR ( " BUG: register '%s' size doesn't match reg_params[i].size " , reg_params [ i ] . reg_name ) ;
exit ( - 1 ) ;
}
arm11_set_reg ( reg , reg_params [ i ] . value ) ;
// printf("%i: Set %s =%08x\n", i, reg_params[i].reg_name,val);
}
exit_breakpoint_size = 4 ;
/* arm11->core_state = arm11_algorithm_info->core_state;
if ( arm11 - > core_state = = ARMV4_5_STATE_ARM )
2008-10-08 15:16:51 -05:00
exit_breakpoint_size = 4 ;
2008-10-07 06:08:57 -05:00
else if ( arm11 - > core_state = = ARMV4_5_STATE_THUMB )
exit_breakpoint_size = 2 ;
else
{
LOG_ERROR ( " BUG: can't execute algorithms when not in ARM or Thumb state " ) ;
exit ( - 1 ) ;
}
*/
if ( arm11_algorithm_info - > core_mode ! = ARMV4_5_MODE_ANY )
{
LOG_DEBUG ( " setting core_mode: 0x%2.2x " , arm11_algorithm_info - > core_mode ) ;
buf_set_u32 ( arm11 - > reg_list [ ARM11_RC_CPSR ] . value , 0 , 5 , arm11_algorithm_info - > core_mode ) ;
arm11 - > reg_list [ ARM11_RC_CPSR ] . dirty = 1 ;
arm11 - > reg_list [ ARM11_RC_CPSR ] . valid = 1 ;
}
if ( ( retval = breakpoint_add ( target , exit_point , exit_breakpoint_size , BKPT_HARD ) ) ! = ERROR_OK )
{
LOG_ERROR ( " can't add breakpoint to finish algorithm execution " ) ;
retval = ERROR_TARGET_FAILURE ;
goto restore ;
}
2008-10-14 06:06:30 -05:00
// no debug, otherwise breakpoint is not set
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_resume ( target , 0 , entry_point , 1 , 0 ) ) ;
2008-10-14 06:06:30 -05:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_wait_state ( target , TARGET_HALTED , timeout_ms ) ) ;
2008-10-07 06:08:57 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( target_halt ( target ) ) ;
CHECK_RETVAL ( target_wait_state ( target , TARGET_HALTED , 500 ) ) ;
2008-10-07 06:08:57 -05:00
retval = ERROR_TARGET_TIMEOUT ;
2009-04-28 02:29:18 -05:00
2008-10-07 06:08:57 -05:00
goto del_breakpoint ;
}
if ( buf_get_u32 ( arm11 - > reg_list [ 15 ] . value , 0 , 32 ) ! = exit_point )
{
LOG_WARNING ( " target reentered debug state, but not at the desired exit point: 0x%4.4x " ,
buf_get_u32 ( arm11 - > reg_list [ 15 ] . value , 0 , 32 ) ) ;
retval = ERROR_TARGET_TIMEOUT ;
goto del_breakpoint ;
}
for ( i = 0 ; i < num_mem_params ; i + + )
{
if ( mem_params [ i ] . direction ! = PARAM_OUT )
target_read_buffer ( target , mem_params [ i ] . address , mem_params [ i ] . size , mem_params [ i ] . value ) ;
}
for ( i = 0 ; i < num_reg_params ; i + + )
{
if ( reg_params [ i ] . direction ! = PARAM_OUT )
{
reg_t * reg = register_get_by_name ( arm11 - > core_cache , reg_params [ i ] . reg_name , 0 ) ;
if ( ! reg )
{
LOG_ERROR ( " BUG: register '%s' not found " , reg_params [ i ] . reg_name ) ;
exit ( - 1 ) ;
}
if ( reg - > size ! = reg_params [ i ] . size )
{
LOG_ERROR ( " BUG: register '%s' size doesn't match reg_params[i].size " , reg_params [ i ] . reg_name ) ;
exit ( - 1 ) ;
}
buf_set_u32 ( reg_params [ i ] . value , 0 , 32 , buf_get_u32 ( reg - > value , 0 , 32 ) ) ;
}
}
del_breakpoint :
breakpoint_remove ( target , exit_point ) ;
restore :
// Restore context
for ( i = 0 ; i < 16 ; i + + )
{
LOG_DEBUG ( " restoring register %s with value 0x%8.8x " ,
arm11 - > reg_list [ i ] . name , context [ i ] ) ;
2008-10-08 15:16:51 -05:00
arm11_set_reg ( & arm11 - > reg_list [ i ] , ( u8 * ) & context [ i ] ) ;
2008-10-07 06:08:57 -05:00
}
LOG_DEBUG ( " restoring CPSR with value 0x%8.8x " , cpsr ) ;
2008-10-08 15:16:51 -05:00
arm11_set_reg ( & arm11 - > reg_list [ ARM11_RC_CPSR ] , ( u8 * ) & cpsr ) ;
2008-10-07 06:08:57 -05:00
// arm11->core_state = core_state;
// arm11->core_mode = core_mode;
return retval ;
2008-02-25 11:48:04 -06:00
}
2008-09-01 02:20:21 -05:00
int arm11_target_create ( struct target_s * target , Jim_Interp * interp )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
NEW ( arm11_common_t , arm11 , 1 ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > target = target ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* prepare JTAG information for the new target */
2008-11-30 16:25:43 -06:00
arm11 - > jtag_info . tap = target - > tap ;
2008-10-08 15:16:51 -05:00
arm11 - > jtag_info . scann_size = 5 ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( arm_jtag_setup_connection ( & arm11 - > jtag_info ) ) ;
2008-02-25 11:48:04 -06:00
2008-11-30 16:25:43 -06:00
if ( target - > tap = = NULL )
2008-11-19 02:22:47 -06:00
return ERROR_FAIL ;
2008-02-25 11:48:04 -06:00
2008-11-30 16:25:43 -06:00
if ( target - > tap - > ir_length ! = 5 )
2008-10-08 15:16:51 -05:00
{
2008-11-30 16:25:43 -06:00
LOG_ERROR ( " 'target arm11' expects IR LENGTH = 5 " ) ;
2008-08-19 04:31:51 -05:00
return ERROR_COMMAND_SYNTAX_ERROR ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
target - > arch_info = arm11 ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_init_target ( struct command_context_s * cmd_ctx , struct target_s * target )
2008-07-04 02:20:43 -05:00
{
/* Initialize anything we can set up without talking to the target */
2008-10-13 07:04:05 -05:00
return arm11_build_reg_cache ( target ) ;
2008-07-04 02:20:43 -05:00
}
/* talk to the target and set things up */
2008-08-05 01:18:26 -05:00
int arm11_examine ( struct target_s * target )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* check IDCODE */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_IR ( arm11 , ARM11_IDCODE , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
scan_field_t idcode_field ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_setup_field ( arm11 , 32 , NULL , & arm11 - > device_id , & idcode_field ) ;
2008-02-25 11:48:04 -06:00
2008-12-13 00:25:50 -06:00
arm11_add_dr_scan_vc ( 1 , & idcode_field , TAP_DRPAUSE ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* check DIDR */
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_debug_SCAN_N ( arm11 , 0x00 , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
arm11_add_IR ( arm11 , ARM11_INTEST , ARM11_TAP_DEFAULT ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
scan_field_t chain0_fields [ 2 ] ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_setup_field ( arm11 , 32 , NULL , & arm11 - > didr , chain0_fields + 0 ) ;
arm11_setup_field ( arm11 , 8 , NULL , & arm11 - > implementor , chain0_fields + 1 ) ;
2008-02-25 11:48:04 -06:00
2008-12-13 00:25:50 -06:00
arm11_add_dr_scan_vc ( asizeof ( chain0_fields ) , chain0_fields , TAP_IDLE ) ;
2008-02-25 11:48:04 -06:00
2009-04-28 02:29:18 -05:00
CHECK_RETVAL ( jtag_execute_queue ( ) ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
switch ( arm11 - > device_id & 0x0FFFF000 )
{
case 0x07B36000 : LOG_INFO ( " found ARM1136 " ) ; break ;
case 0x07B56000 : LOG_INFO ( " found ARM1156 " ) ; break ;
case 0x07B76000 : LOG_INFO ( " found ARM1176 " ) ; break ;
default :
{
2008-08-19 04:31:51 -05:00
LOG_ERROR ( " 'target arm11' expects IDCODE 0x*7B*7**** " ) ;
return ERROR_FAIL ;
2008-10-08 15:16:51 -05:00
}
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > debug_version = ( arm11 - > didr > > 16 ) & 0x0F ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > debug_version ! = ARM11_DEBUG_V6 & &
2009-04-22 13:39:59 -05:00
arm11 - > debug_version ! = ARM11_DEBUG_V61 )
2008-10-08 15:16:51 -05:00
{
2009-04-22 13:39:59 -05:00
LOG_ERROR ( " Only ARMv6 v6 and v6.1 architectures supported. " ) ;
return ERROR_FAIL ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > brp = ( ( arm11 - > didr > > 24 ) & 0x0F ) + 1 ;
arm11 - > wrp = ( ( arm11 - > didr > > 28 ) & 0x0F ) + 1 ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: reserve one brp slot if we allow breakpoints during step */
arm11 - > free_brps = arm11 - > brp ;
arm11 - > free_wrps = arm11 - > wrp ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
LOG_DEBUG ( " IDCODE %08x IMPLEMENTOR %02x DIDR %08x " ,
2009-04-22 13:39:59 -05:00
arm11 - > device_id ,
arm11 - > implementor ,
arm11 - > didr ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* as a side-effect this reads DSCR and thus
* clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
* as suggested by the spec .
*/
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11_check_init ( arm11 , NULL ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
target - > type - > examined = 1 ;
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
int arm11_quit ( void )
{
2008-10-08 15:16:51 -05:00
FNC_INFO_NOTIMPLEMENTED ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/** Load a register that is marked !valid in the register cache */
int arm11_get_reg ( reg_t * reg )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
target_t * target = ( ( arm11_reg_state_t * ) reg - > arch_info ) - > target ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/** \todo TODO: Check this. We assume that all registers are fetched at debug entry. */
2008-02-25 11:48:04 -06:00
#if 0
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ( ( arm11_reg_state_t * ) reg - > arch_info ) - > def_index ;
2008-02-25 11:48:04 -06:00
# endif
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
/** Change a value in the register cache */
int arm11_set_reg ( reg_t * reg , u8 * buf )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
target_t * target = ( ( arm11_reg_state_t * ) reg - > arch_info ) - > target ;
arm11_common_t * arm11 = target - > arch_info ;
// const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > reg_values [ ( ( arm11_reg_state_t * ) reg - > arch_info ) - > def_index ] = buf_get_u32 ( buf , 0 , 32 ) ;
reg - > valid = 1 ;
reg - > dirty = 1 ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
2008-10-13 07:16:44 -05:00
int arm11_build_reg_cache ( target_t * target )
2008-02-25 11:48:04 -06:00
{
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = target - > arch_info ;
2009-04-22 13:39:59 -05:00
NEW ( reg_cache_t , cache , 1 ) ;
NEW ( reg_t , reg_list , ARM11_REGCACHE_COUNT ) ;
2008-10-08 15:16:51 -05:00
NEW ( arm11_reg_state_t , arm11_reg_states , ARM11_REGCACHE_COUNT ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11_regs_arch_type = = - 1 )
arm11_regs_arch_type = register_reg_arch_type ( arm11_get_reg , arm11_set_reg ) ;
2008-02-25 11:48:04 -06:00
2008-10-07 13:04:14 -05:00
register_init_dummy ( & arm11_gdb_dummy_fp_reg ) ;
register_init_dummy ( & arm11_gdb_dummy_fps_reg ) ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > reg_list = reg_list ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* Build the process context cache */
cache - > name = " arm11 registers " ;
cache - > next = NULL ;
cache - > reg_list = reg_list ;
cache - > num_regs = ARM11_REGCACHE_COUNT ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
reg_cache_t * * cache_p = register_get_last_cache_p ( & target - > reg_cache ) ;
( * cache_p ) = cache ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
arm11 - > core_cache = cache ;
// armv7m->process_context = cache;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
size_t i ;
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
/* Not very elegant assertion */
if ( ARM11_REGCACHE_COUNT ! = asizeof ( arm11 - > reg_values ) | |
2009-04-22 13:39:59 -05:00
ARM11_REGCACHE_COUNT ! = asizeof ( arm11_reg_defs ) | |
ARM11_REGCACHE_COUNT ! = ARM11_RC_MAX )
2008-10-08 15:16:51 -05:00
{
2009-04-22 13:39:59 -05:00
LOG_ERROR ( " BUG: arm11->reg_values inconsistent (%d " ZU " " ZU " %d) " , ARM11_REGCACHE_COUNT , asizeof ( arm11 - > reg_values ) , asizeof ( arm11_reg_defs ) , ARM11_RC_MAX ) ;
exit ( - 1 ) ;
2008-10-08 15:16:51 -05:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
for ( i = 0 ; i < ARM11_REGCACHE_COUNT ; i + + )
{
2009-04-22 13:39:59 -05:00
reg_t * r = reg_list + i ;
const arm11_reg_defs_t * rd = arm11_reg_defs + i ;
arm11_reg_state_t * rs = arm11_reg_states + i ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
r - > name = rd - > name ;
r - > size = 32 ;
r - > value = ( u8 * ) ( arm11 - > reg_values + i ) ;
r - > dirty = 0 ;
r - > valid = 0 ;
r - > bitfield_desc = NULL ;
r - > num_bitfields = 0 ;
r - > arch_type = arm11_regs_arch_type ;
r - > arch_info = rs ;
2008-02-25 11:48:04 -06:00
2009-04-22 13:39:59 -05:00
rs - > def_index = i ;
rs - > target = target ;
2008-10-08 15:16:51 -05:00
}
2009-04-22 13:39:59 -05:00
2008-10-13 07:16:44 -05:00
return ERROR_OK ;
2008-02-25 11:48:04 -06:00
}
2008-03-04 00:46:44 -06:00
int arm11_handle_bool ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc , bool * var , char * name )
2008-02-29 01:03:28 -06:00
{
2008-10-08 15:16:51 -05:00
if ( argc = = 0 )
{
2009-04-22 13:39:59 -05:00
LOG_INFO ( " %s is %s. " , name , * var ? " enabled " : " disabled " ) ;
return ERROR_OK ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
if ( argc ! = 1 )
2009-04-22 13:39:59 -05:00
return ERROR_COMMAND_SYNTAX_ERROR ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
switch ( args [ 0 ] [ 0 ] )
{
case ' 0 ' : /* 0 */
case ' f ' : /* false */
case ' F ' :
case ' d ' : /* disable */
case ' D ' :
2009-04-22 13:39:59 -05:00
* var = false ;
break ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
case ' 1 ' : /* 1 */
case ' t ' : /* true */
case ' T ' :
case ' e ' : /* enable */
case ' E ' :
2009-04-22 13:39:59 -05:00
* var = true ;
break ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
LOG_INFO ( " %s %s. " , * var ? " Enabled " : " Disabled " , name ) ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-29 01:03:28 -06:00
}
2008-10-08 15:16:51 -05:00
# define BOOL_WRAPPER(name, print_name) \
2008-02-29 01:03:28 -06:00
int arm11_handle_bool_ # # name ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) \
{ \
2008-10-08 15:16:51 -05:00
return arm11_handle_bool ( cmd_ctx , cmd , args , argc , & arm11_config_ # # name , print_name ) ; \
2008-02-29 01:03:28 -06:00
}
# define RC_TOP(name, descr, more) \
{ \
2008-10-08 15:16:51 -05:00
command_t * new_cmd = register_command ( cmd_ctx , top_cmd , name , NULL , COMMAND_ANY , descr ) ; \
command_t * top_cmd = new_cmd ; \
more \
2008-02-29 01:03:28 -06:00
}
2008-02-25 11:48:04 -06:00
2008-10-08 15:16:51 -05:00
# define RC_FINAL(name, descr, handler) \
register_command ( cmd_ctx , top_cmd , name , handler , COMMAND_ANY , descr ) ;
2008-02-25 11:48:04 -06:00
2008-02-29 01:03:28 -06:00
# define RC_FINAL_BOOL(name, descr, var) \
2008-10-08 15:16:51 -05:00
register_command ( cmd_ctx , top_cmd , name , arm11_handle_bool_ # # var , COMMAND_ANY , descr ) ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
BOOL_WRAPPER ( memwrite_burst , " memory write burst mode " )
BOOL_WRAPPER ( memwrite_error_fatal , " fatal error mode for memory writes " )
BOOL_WRAPPER ( memrw_no_increment , " \" no increment \" mode for memory transfers " )
BOOL_WRAPPER ( step_irq_enable , " IRQs while stepping " )
2008-02-29 01:03:28 -06:00
int arm11_handle_vcr ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
{
2008-10-08 15:16:51 -05:00
if ( argc = = 1 )
{
2009-04-22 13:39:59 -05:00
arm11_vcr = strtoul ( args [ 0 ] , NULL , 0 ) ;
2008-10-08 15:16:51 -05:00
}
else if ( argc ! = 0 )
{
2009-04-22 13:39:59 -05:00
return ERROR_COMMAND_SYNTAX_ERROR ;
2008-10-08 15:16:51 -05:00
}
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
LOG_INFO ( " VCR 0x%08X " , arm11_vcr ) ;
return ERROR_OK ;
2008-02-29 01:03:28 -06:00
}
2008-03-08 11:28:28 -06:00
const u32 arm11_coproc_instruction_limits [ ] =
{
2009-04-22 13:39:59 -05:00
15 , /* coprocessor */
7 , /* opcode 1 */
15 , /* CRn */
15 , /* CRm */
7 , /* opcode 2 */
2008-10-08 15:16:51 -05:00
0xFFFFFFFF , /* value */
2008-03-08 11:28:28 -06:00
} ;
const char arm11_mrc_syntax [ ] = " Syntax: mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only. " ;
const char arm11_mcr_syntax [ ] = " Syntax: mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only. " ;
arm11_common_t * arm11_find_target ( const char * arg )
{
2009-04-22 13:39:59 -05:00
jtag_tap_t * tap ;
target_t * t ;
2008-12-13 00:25:50 -06:00
2009-04-22 13:39:59 -05:00
tap = jtag_TapByString ( arg ) ;
2008-11-30 16:25:43 -06:00
2009-04-22 13:39:59 -05:00
if ( ! tap )
return 0 ;
for ( t = all_targets ; t ; t = t - > next )
{
if ( t - > tap ! = tap )
continue ;
/* if (t->type == arm11_target) */
if ( 0 = = strcmp ( t - > type - > name , " arm11 " ) )
return t - > arch_info ;
2008-11-30 16:25:43 -06:00
}
2009-04-22 13:39:59 -05:00
2008-10-08 15:16:51 -05:00
return 0 ;
2008-03-08 11:28:28 -06:00
}
int arm11_handle_mrc_mcr ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc , bool read )
{
2008-10-08 15:16:51 -05:00
if ( argc ! = ( read ? 6 : 7 ) )
{
2009-04-22 13:39:59 -05:00
LOG_ERROR ( " Invalid number of arguments. %s " , read ? arm11_mrc_syntax : arm11_mcr_syntax ) ;
return - 1 ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_common_t * arm11 = arm11_find_target ( args [ 0 ] ) ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
if ( ! arm11 )
{
2009-04-22 13:39:59 -05:00
LOG_ERROR ( " Parameter 1 is not a the JTAG chain position of an ARM11 device. %s " ,
read ? arm11_mrc_syntax : arm11_mcr_syntax ) ;
2008-03-08 11:28:28 -06:00
2009-04-22 13:39:59 -05:00
return - 1 ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
if ( arm11 - > target - > state ! = TARGET_HALTED )
{
2009-04-22 13:39:59 -05:00
LOG_WARNING ( " target was not halted " ) ;
return ERROR_TARGET_NOT_HALTED ;
2008-10-08 15:16:51 -05:00
}
2008-10-07 06:08:57 -05:00
2008-10-08 15:16:51 -05:00
u32 values [ 6 ] ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
{ size_t i ;
for ( i = 0 ; i < ( read ? 5 : 6 ) ; i + + )
{
2009-04-22 13:39:59 -05:00
values [ i ] = strtoul ( args [ i + 1 ] , NULL , 0 ) ;
2008-03-08 11:28:28 -06:00
2009-04-22 13:39:59 -05:00
if ( values [ i ] > arm11_coproc_instruction_limits [ i ] )
{
LOG_ERROR ( " Parameter %ld out of bounds (%d max). %s " ,
( long ) ( i + 2 ) , arm11_coproc_instruction_limits [ i ] ,
read ? arm11_mrc_syntax : arm11_mcr_syntax ) ;
return - 1 ;
}
2008-10-08 15:16:51 -05:00
} }
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
u32 instr = 0xEE000010 |
2009-04-22 13:39:59 -05:00
( values [ 0 ] < < 8 ) |
( values [ 1 ] < < 21 ) |
( values [ 2 ] < < 16 ) |
( values [ 3 ] < < 0 ) |
( values [ 4 ] < < 5 ) ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
if ( read )
2009-04-22 13:39:59 -05:00
instr | = 0x00100000 ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_prepare ( arm11 ) ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
if ( read )
{
2009-04-22 13:39:59 -05:00
u32 result ;
arm11_run_instr_data_from_core_via_r0 ( arm11 , instr , & result ) ;
2008-03-08 11:28:28 -06:00
2009-04-22 13:39:59 -05:00
LOG_INFO ( " MRC p%d, %d, R0, c%d, c%d, %d = 0x%08x (%d) " ,
values [ 0 ] , values [ 1 ] , values [ 2 ] , values [ 3 ] , values [ 4 ] , result , result ) ;
2008-10-08 15:16:51 -05:00
}
else
{
2009-04-22 13:39:59 -05:00
arm11_run_instr_data_to_core_via_r0 ( arm11 , instr , values [ 5 ] ) ;
2008-03-08 11:28:28 -06:00
2009-04-22 13:39:59 -05:00
LOG_INFO ( " MRC p%d, %d, R0 (#0x%08x), c%d, c%d, %d " ,
values [ 0 ] , values [ 1 ] ,
values [ 5 ] ,
values [ 2 ] , values [ 3 ] , values [ 4 ] ) ;
2008-10-08 15:16:51 -05:00
}
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
arm11_run_instr_data_finish ( arm11 ) ;
2008-03-08 11:28:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-03-08 11:28:28 -06:00
}
int arm11_handle_mrc ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
{
2008-10-08 15:16:51 -05:00
return arm11_handle_mrc_mcr ( cmd_ctx , cmd , args , argc , true ) ;
2008-03-08 11:28:28 -06:00
}
int arm11_handle_mcr ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
{
2008-10-08 15:16:51 -05:00
return arm11_handle_mrc_mcr ( cmd_ctx , cmd , args , argc , false ) ;
2008-03-08 11:28:28 -06:00
}
2008-02-29 01:03:28 -06:00
int arm11_register_commands ( struct command_context_s * cmd_ctx )
{
2008-10-08 15:16:51 -05:00
FNC_INFO ;
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
command_t * top_cmd = NULL ;
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
RC_TOP ( " arm11 " , " arm11 specific commands " ,
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
RC_TOP ( " memwrite " , " Control memory write transfer mode " ,
2008-02-29 01:03:28 -06:00
2009-04-22 13:39:59 -05:00
RC_FINAL_BOOL ( " burst " , " Enable/Disable non-standard but fast burst mode (default: enabled) " ,
2008-02-29 01:03:28 -06:00
memwrite_burst )
2009-04-22 13:39:59 -05:00
RC_FINAL_BOOL ( " error_fatal " , " Terminate program if transfer error was found (default: enabled) " ,
2008-02-29 01:03:28 -06:00
memwrite_error_fatal )
)
2009-04-22 13:39:59 -05:00
RC_FINAL_BOOL ( " no_increment " , " Don't increment address on multi-read/-write (default: disabled) " ,
memrw_no_increment )
2009-04-27 06:24:01 -05:00
2009-04-22 13:39:59 -05:00
RC_FINAL_BOOL ( " step_irq_enable " , " Enable interrupts while stepping (default: disabled) " ,
step_irq_enable )
RC_FINAL ( " vcr " , " Control (Interrupt) Vector Catch Register " ,
2008-02-29 01:03:28 -06:00
arm11_handle_vcr )
2008-03-08 11:28:28 -06:00
2009-04-22 13:39:59 -05:00
RC_FINAL ( " mrc " , " Read Coprocessor register " ,
2008-03-08 11:28:28 -06:00
arm11_handle_mrc )
2009-04-22 13:39:59 -05:00
RC_FINAL ( " mcr " , " Write Coprocessor register " ,
2008-03-08 11:28:28 -06:00
arm11_handle_mcr )
2008-10-08 15:16:51 -05:00
)
2008-02-29 01:03:28 -06:00
2008-10-08 15:16:51 -05:00
return ERROR_OK ;
2008-02-29 01:03:28 -06:00
}