arm11.c 54.1 KB
Newer Older
1
2
/***************************************************************************
 *   Copyright (C) 2008 digenius technology GmbH.                          *
3
 *   Michael Bruck                                                         *
4
 *                                                                         *
oharboe's avatar
oharboe committed
5
 *   Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com         *
6
 *                                                                         *
7
8
 *   Copyright (C) 2008 Georg Acher <acher@in.tum.de>                      *
 *                                                                         *
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *   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.             *
 ***************************************************************************/
oharboe's avatar
oharboe committed
24

25
26
27
28
29
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "arm11.h"
30
#include "arm11_dbgtap.h"
oharboe's avatar
oharboe committed
31
32
#include "armv4_5.h"
#include "arm_simulator.h"
dbrownell's avatar
dbrownell committed
33
#include "time_support.h"
34
#include "target_type.h"
35
36
37
38
39
40
41


#if 0
#define _DEBUG_INSTRUCTION_EXECUTION_
#endif

#if 0
42
#define FNC_INFO	LOG_DEBUG("-")
43
44
45
46
47
#else
#define FNC_INFO
#endif

#if 1
48
#define FNC_INFO_NOTIMPLEMENTED do { LOG_DEBUG("NOT IMPLEMENTED"); /*exit(-1);*/ } while (0)
49
50
51
52
#else
#define FNC_INFO_NOTIMPLEMENTED
#endif

53
54
55
56
57
static bool arm11_config_memwrite_burst = true;
static bool arm11_config_memwrite_error_fatal = true;
static uint32_t arm11_vcr = 0;
static bool arm11_config_step_irq_enable = false;
static bool arm11_config_hardware_step = false;
58

59
static int arm11_regs_arch_type = -1;
60
61
62

enum arm11_regtype
{
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	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,
87
88
89
90
91
};


typedef struct arm11_reg_defs_s
{
92
	char *					name;
93
	uint32_t						num;
94
	int						gdb_num;
95
	enum arm11_regtype		type;
96
97
98
99
100
} arm11_reg_defs_t;

/* update arm11_regcache_ids when changing this */
static const arm11_reg_defs_t arm11_reg_defs[] =
{
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	{"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},
117
118

#if ARM11_REGCACHE_FREGS
119
120
121
122
123
124
125
126
127
	{"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},
128
129
#endif

130
	{"cpsr",	0,	25,	ARM11_REGISTER_CPSR},
131
132

#if ARM11_REGCACHE_MODEREGS
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
	{"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},
162
163
#endif

164
165
166
167
	/* Debug Registers */
	{"dscr",	0,	-1,	ARM11_REGISTER_DSCR},
	{"wdtr",	0,	-1,	ARM11_REGISTER_WDTR},
	{"rdtr",	0,	-1,	ARM11_REGISTER_RDTR},
168
169
170
171
};

enum arm11_regcache_ids
{
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	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,
193
194

#if ARM11_REGCACHE_FREGS
195
196
197
198
199
200
201
202
203
204
	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,
205
206
#endif

207
	ARM11_RC_CPSR,
208
209

#if ARM11_REGCACHE_MODEREGS
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
	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,
238
239
#endif

240
241
242
	ARM11_RC_DSCR,
	ARM11_RC_WDTR,
	ARM11_RC_RDTR,
243

244
	ARM11_RC_MAX,
245
246
247
248
};

#define ARM11_GDB_REGISTER_COUNT	26

249
static uint8_t arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
250

251
static reg_t arm11_gdb_dummy_fp_reg =
252
{
253
	"GDB dummy floating-point register", arm11_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
254
255
};

256
static uint8_t arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};
257

258
static reg_t arm11_gdb_dummy_fps_reg =
259
{
260
	"GDB dummy floating-point status register", arm11_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
261
262
263
};


264
265
266
267
268
269
270
271
272
273
274
static int arm11_on_enter_debug_state(arm11_common_t *arm11);
static int arm11_step(struct target_s *target, int current,
		uint32_t address, int handle_breakpoints);
/* helpers */
static int arm11_build_reg_cache(target_t *target);
static int arm11_set_reg(reg_t *reg, uint8_t *buf);
static int arm11_get_reg(reg_t *reg);

static void arm11_record_register_history(arm11_common_t * arm11);
static void arm11_dump_reg_changes(arm11_common_t * arm11);

275
276
277
278
279

/** Check and if necessary take control of the system
 *
 * \param arm11		Target state variable.
 * \param dscr		If the current DSCR content is
280
281
 *					available a pointer to a word holding the
 *					DSCR can be passed. Otherwise use NULL.
282
 */
283
static int arm11_check_init(arm11_common_t *arm11, uint32_t *dscr)
284
{
285
	FNC_INFO;
286

287
	uint32_t			dscr_local_tmp_copy;
288

289
290
	if (!dscr)
	{
291
		dscr = &dscr_local_tmp_copy;
292

293
		CHECK_RETVAL(arm11_read_DSCR(arm11, dscr));
294
	}
295

296
297
	if (!(*dscr & ARM11_DSCR_MODE_SELECT))
	{
298
		LOG_DEBUG("Bringing target into debug mode");
299

300
301
		*dscr |= ARM11_DSCR_MODE_SELECT;		/* Halt debug-mode */
		arm11_write_DSCR(arm11, *dscr);
302

303
		/* add further reset initialization here */
304

305
		arm11->simulate_reset_on_next_halt = true;
oharboe's avatar
oharboe committed
306

307
308
309
		if (*dscr & ARM11_DSCR_CORE_HALTED)
		{
			/** \todo TODO: this needs further scrutiny because
310
311
312
			  * arm11_on_enter_debug_state() never gets properly called.
			  * As a result we don't read the actual register states from
			  * the target.
313
			  */
oharboe's avatar
oharboe committed
314

315
316
317
318
319
320
321
322
			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;
		}
323

324
		arm11_sc7_clear_vbw(arm11);
325
	}
326
327

	return ERROR_OK;
328
329
330
331
332
}



#define R(x) \
333
	(arm11->reg_values[ARM11_RC_##x])
334
335
336
337
338
339
340

/** Save processor state.
  *
  * This is called when the HALT instruction has succeeded
  * or on other occasions that stop the processor.
  *
  */
341
static int arm11_on_enter_debug_state(arm11_common_t *arm11)
342
{
oharboe's avatar
oharboe committed
343
	int retval;
344
	FNC_INFO;
345

346
	for (size_t i = 0; i < asizeof(arm11->reg_values); i++)
347
	{
348
349
		arm11->reg_list[i].valid	= 1;
		arm11->reg_list[i].dirty	= 0;
350
	}
351

352
	/* Save DSCR */
353
	CHECK_RETVAL(arm11_read_DSCR(arm11, &R(DSCR)));
354

355
	/* Save wDTR */
356

357
358
	if (R(DSCR) & ARM11_DSCR_WDTR_FULL)
	{
359
		arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
360

361
		arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
362

363
		struct scan_field	chain5_fields[3];
364

365
		arm11_setup_field(arm11, 32, NULL, &R(WDTR),	chain5_fields + 0);
366
367
		arm11_setup_field(arm11,  1, NULL, NULL,		chain5_fields + 1);
		arm11_setup_field(arm11,  1, NULL, NULL,		chain5_fields + 2);
368

369
		arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_DRPAUSE);
370
371
372
	}
	else
	{
373
		arm11->reg_list[ARM11_RC_WDTR].valid	= 0;
374
	}
375
376


377
378
379
	/* 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 */
380

381
	uint32_t new_dscr = R(DSCR) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;
382

383
	/* this executes JTAG queue: */
384

385
	arm11_write_DSCR(arm11, new_dscr);
386
387


388
	/* From the spec:
389
390
	   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:*/
391

392
	/** \todo TODO: Test drain write buffer. */
393
394

#if 0
395
396
	while (1)
	{
397
398
		/* MRC p14,0,R0,c5,c10,0 */
		//	arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);
399

400
401
		/* mcr	   15, 0, r0, cr7, cr10, {4} */
		arm11_run_instr_no_data1(arm11, 0xee070f9a);
402

403
		uint32_t dscr = arm11_read_DSCR(arm11);
404

405
		LOG_DEBUG("DRAIN, DSCR %08x", dscr);
406

407
408
409
		if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT)
		{
			arm11_run_instr_no_data1(arm11, 0xe320f000);
410

411
			dscr = arm11_read_DSCR(arm11);
412

413
			LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr);
414

415
416
			break;
		}
417
418
419
	}
#endif

Øyvind Harboe's avatar
Øyvind Harboe committed
420
421
422
	retval = arm11_run_instr_data_prepare(arm11);
	if (retval != ERROR_OK)
		return retval;
423

424
	/* save r0 - r14 */
425

426
	/** \todo TODO: handle other mode registers */
427

428
	for (size_t i = 0; i < 15; i++)
429
	{
430
		/* MCR p14,0,R?,c0,c5,0 */
oharboe's avatar
oharboe committed
431
432
433
		retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
		if (retval != ERROR_OK)
			return retval;
434
	}
435

436
	/* save rDTR */
437

438
	/* check rDTRfull in DSCR */
439

440
441
	if (R(DSCR) & ARM11_DSCR_RDTR_FULL)
	{
442
		/* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
Øyvind Harboe's avatar
Øyvind Harboe committed
443
444
445
		retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
		if (retval != ERROR_OK)
			return retval;
446
447
448
	}
	else
	{
449
		arm11->reg_list[ARM11_RC_RDTR].valid	= 0;
450
	}
451

452
	/* save CPSR */
453

454
	/* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
Øyvind Harboe's avatar
Øyvind Harboe committed
455
456
457
	retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
	if (retval != ERROR_OK)
		return retval;
458

459
	/* save PC */
460

461
	/* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */
oharboe's avatar
oharboe committed
462
463
464
	retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
	if (retval != ERROR_OK)
		return retval;
465

466
	/* adjust PC depending on ARM state */
467

468
469
	if (R(CPSR) & ARM11_CPSR_J)	/* Java state */
	{
470
		arm11->reg_values[ARM11_RC_PC] -= 0;
471
472
473
	}
	else if (R(CPSR) & ARM11_CPSR_T)	/* Thumb state */
	{
474
		arm11->reg_values[ARM11_RC_PC] -= 4;
475
476
477
	}
	else					/* ARM state */
	{
478
		arm11->reg_values[ARM11_RC_PC] -= 8;
479
	}
480

481
482
	if (arm11->simulate_reset_on_next_halt)
	{
483
		arm11->simulate_reset_on_next_halt = false;
oharboe's avatar
oharboe committed
484

485
		LOG_DEBUG("Reset c1 Control Register");
oharboe's avatar
oharboe committed
486

487
		/* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */
oharboe's avatar
oharboe committed
488

489
		/* MCR p15,0,R0,c1,c0,0 */
Øyvind Harboe's avatar
Øyvind Harboe committed
490
491
492
		retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
		if (retval != ERROR_OK)
			return retval;
oharboe's avatar
oharboe committed
493

494
	}
oharboe's avatar
oharboe committed
495

Øyvind Harboe's avatar
Øyvind Harboe committed
496
497
498
	retval = arm11_run_instr_data_finish(arm11);
	if (retval != ERROR_OK)
		return retval;
499

500
	arm11_dump_reg_changes(arm11);
501
502

	return ERROR_OK;
oharboe's avatar
oharboe committed
503
}
504

oharboe's avatar
oharboe committed
505
506
void arm11_dump_reg_changes(arm11_common_t * arm11)
{
507
508
509
510
511
512

	if (!(debug_level >= LOG_LVL_DEBUG))
	{
		return;
	}

513
	for (size_t i = 0; i < ARM11_REGCACHE_COUNT; i++)
514
	{
515
		if (!arm11->reg_list[i].valid)
516
		{
517
			if (arm11->reg_history[i].valid)
duane's avatar
duane committed
518
				LOG_DEBUG("%8s INVALID	 (%08" PRIx32 ")", arm11_reg_defs[i].name, arm11->reg_history[i].value);
519
520
521
		}
		else
		{
522
523
524
			if (arm11->reg_history[i].valid)
			{
				if (arm11->reg_history[i].value != arm11->reg_values[i])
duane's avatar
duane committed
525
					LOG_DEBUG("%8s %08" PRIx32 " (%08" PRIx32 ")", arm11_reg_defs[i].name, arm11->reg_values[i], arm11->reg_history[i].value);
526
527
528
			}
			else
			{
duane's avatar
duane committed
529
				LOG_DEBUG("%8s %08" PRIx32 " (INVALID)", arm11_reg_defs[i].name, arm11->reg_values[i]);
530
			}
531
		}
532
	}
533
534
535
536
537
538
539
}

/** Restore processor state
  *
  * This is called in preparation for the RESTART function.
  *
  */
540
static int arm11_leave_debug_state(arm11_common_t *arm11)
541
{
542
	FNC_INFO;
Øyvind Harboe's avatar
Øyvind Harboe committed
543
	int retval;
544

Øyvind Harboe's avatar
Øyvind Harboe committed
545
546
547
	retval = arm11_run_instr_data_prepare(arm11);
	if (retval != ERROR_OK)
		return retval;
548

549
	/** \todo TODO: handle other mode registers */
550

551
	/* restore R1 - R14 */
552
553

	for (size_t i = 1; i < 15; i++)
554
	{
555
556
		if (!arm11->reg_list[ARM11_RC_RX + i].dirty)
			continue;
557

558
559
		/* MRC p14,0,r?,c0,c5,0 */
		arm11_run_instr_data_to_core1(arm11, 0xee100e15 | (i << 12), R(RX + i));
560

561
		//	LOG_DEBUG("RESTORE R" ZU " %08x", i, R(RX + i));
562
	}
563

Øyvind Harboe's avatar
Øyvind Harboe committed
564
565
566
	retval = arm11_run_instr_data_finish(arm11);
	if (retval != ERROR_OK)
		return retval;
567

568
569
570
	/* spec says clear wDTR and rDTR; we assume they are clear as
	   otherwise our programming would be sloppy */
	{
571
		uint32_t DSCR;
572
573

		CHECK_RETVAL(arm11_read_DSCR(arm11, &DSCR));
574

575
576
		if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
		{
577
578
579
580
581
582
583
			/*
			The wDTR/rDTR two registers that are used to send/receive data to/from
			the core in tandem with corresponding instruction codes that are
			written into the core. The RDTR FULL/WDTR FULL flag indicates that the
			registers hold data that was written by one side (CPU or JTAG) and not
			read out by the other side.
			*/
duane's avatar
duane committed
584
			LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", DSCR);
585
			return ERROR_FAIL;
586
		}
587
588
	}

Øyvind Harboe's avatar
Øyvind Harboe committed
589
590
591
	retval = arm11_run_instr_data_prepare(arm11);
	if (retval != ERROR_OK)
		return retval;
592

593
	/* restore original wDTR */
594

595
596
	if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)
	{
597
		/* MCR p14,0,R0,c0,c5,0 */
Øyvind Harboe's avatar
Øyvind Harboe committed
598
599
600
		retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
		if (retval != ERROR_OK)
			return retval;
601
	}
602

603
	/* restore CPSR */
604

605
	/* MSR CPSR,R0*/
Øyvind Harboe's avatar
Øyvind Harboe committed
606
607
608
609
	retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
	if (retval != ERROR_OK)
		return retval;

610

611
	/* restore PC */
612

613
	/* MOV PC,R0 */
Øyvind Harboe's avatar
Øyvind Harboe committed
614
615
616
617
	retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
	if (retval != ERROR_OK)
		return retval;

618

619
	/* restore R0 */
620

621
622
	/* MRC p14,0,r0,c0,c5,0 */
	arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0));
623

Øyvind Harboe's avatar
Øyvind Harboe committed
624
625
626
	retval = arm11_run_instr_data_finish(arm11);
	if (retval != ERROR_OK)
		return retval;
627

628
	/* restore DSCR */
629

630
	arm11_write_DSCR(arm11, R(DSCR));
631

632
	/* restore rDTR */
633

634
635
	if (R(DSCR) & ARM11_DSCR_RDTR_FULL || arm11->reg_list[ARM11_RC_RDTR].dirty)
	{
636
		arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
637

638
		arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
639

640
		struct scan_field	chain5_fields[3];
641

642
643
		uint8_t			Ready		= 0;	/* ignored */
		uint8_t			Valid		= 0;	/* ignored */
644

645
646
647
		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);
648

649
		arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_DRPAUSE);
650
	}
651

652
	arm11_record_register_history(arm11);
653
654

	return ERROR_OK;
oharboe's avatar
oharboe committed
655
}
656

657
static void arm11_record_register_history(arm11_common_t *arm11)
oharboe's avatar
oharboe committed
658
{
659
	for (size_t i = 0; i < ARM11_REGCACHE_COUNT; i++)
660
	{
661
662
		arm11->reg_history[i].value	= arm11->reg_values[i];
		arm11->reg_history[i].valid	= arm11->reg_list[i].valid;
663

664
665
		arm11->reg_list[i].valid	= 0;
		arm11->reg_list[i].dirty	= 0;
666
	}
667
668
669
670
}


/* poll current target status */
671
static int arm11_poll(struct target_s *target)
672
{
673
	FNC_INFO;
oharboe's avatar
oharboe committed
674
	int retval;
675

676
	arm11_common_t * arm11 = target->arch_info;
677

678
	uint32_t	dscr;
679

680
	CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
681

duane's avatar
duane committed
682
	LOG_DEBUG("DSCR %08" PRIx32 "", dscr);
683

684
	CHECK_RETVAL(arm11_check_init(arm11, &dscr));
685

686
687
	if (dscr & ARM11_DSCR_CORE_HALTED)
	{
688
689
690
		if (target->state != TARGET_HALTED)
		{
			enum target_state old_state = target->state;
oharboe's avatar
oharboe committed
691

692
			LOG_DEBUG("enter TARGET_HALTED");
693
			target->state			= TARGET_HALTED;
694
			target->debug_reason	= arm11_get_DSCR_debug_reason(dscr);
oharboe's avatar
oharboe committed
695
696
697
			retval = arm11_on_enter_debug_state(arm11);
			if (retval != ERROR_OK)
				return retval;
oharboe's avatar
oharboe committed
698

699
700
701
			target_call_event_callbacks(target,
				old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED);
		}
702
703
704
	}
	else
	{
705
706
707
		if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING)
		{
			LOG_DEBUG("enter TARGET_RUNNING");
708
			target->state			= TARGET_RUNNING;
709
710
			target->debug_reason	= DBG_REASON_NOTHALTED;
		}
711
712
	}

713
	return ERROR_OK;
714
715
}
/* architecture specific status reply */
716
static int arm11_arch_state(struct target_s *target)
717
{
718
719
	arm11_common_t * arm11 = target->arch_info;

duane's avatar
duane committed
720
	LOG_USER("target halted due to %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
721
			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
722
723
			 R(CPSR),
			 R(PC));
724

725
	return ERROR_OK;
726
727
728
}

/* target request support */
729
730
static int arm11_target_request_data(struct target_s *target,
		uint32_t size, uint8_t *buffer)
731
{
732
	FNC_INFO_NOTIMPLEMENTED;
733

734
	return ERROR_OK;
735
736
737
}

/* target execution control */
738
static int arm11_halt(struct target_s *target)
739
{
740
	FNC_INFO;
741

742
	arm11_common_t * arm11 = target->arch_info;
743

744
	LOG_DEBUG("target->state: %s",
745
		target_state_name(target));
746

747
748
	if (target->state == TARGET_UNKNOWN)
	{
749
		arm11->simulate_reset_on_next_halt = true;
750
	}
oharboe's avatar
oharboe committed
751

752
753
	if (target->state == TARGET_HALTED)
	{
754
755
		LOG_DEBUG("target was already halted");
		return ERROR_OK;
756
	}
757

758
	arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);
759

760
	CHECK_RETVAL(jtag_execute_queue());
761

762
	uint32_t dscr;
763

764
	int i = 0;
765
766
	while (1)
	{
767
		CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
768

769
770
		if (dscr & ARM11_DSCR_CORE_HALTED)
			break;
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786


		long long then = 0;
		if (i == 1000)
		{
			then = timeval_ms();
		}
		if (i >= 1000)
		{
			if ((timeval_ms()-then) > 1000)
			{
				LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
				return ERROR_FAIL;
			}
		}
		i++;
787
	}
788

789
	arm11_on_enter_debug_state(arm11);
790

791
	enum target_state old_state	= target->state;
oharboe's avatar
oharboe committed
792

793
794
	target->state		= TARGET_HALTED;
	target->debug_reason	= arm11_get_DSCR_debug_reason(dscr);
oharboe's avatar
oharboe committed
795

796
797
798
	CHECK_RETVAL(
		target_call_event_callbacks(target,
			old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED));
oharboe's avatar
oharboe committed
799

800
	return ERROR_OK;
801
802
}

803
804
static int arm11_resume(struct target_s *target, int current,
		uint32_t address, int handle_breakpoints, int debug_execution)
805
{
806
	FNC_INFO;
807

808
809
	//	  LOG_DEBUG("current %d  address %08x  handle_breakpoints %d  debug_execution %d",
	//	current, address, handle_breakpoints, debug_execution);
oharboe's avatar
oharboe committed
810

811
	arm11_common_t * arm11 = target->arch_info;
812

813
	LOG_DEBUG("target->state: %s",
814
		target_state_name(target));
815

816

817
	if (target->state != TARGET_HALTED)
oharboe's avatar
oharboe committed
818
819
820
821
	{
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}
822

823
	if (!current)
824
		R(PC) = address;
825

duane's avatar
duane committed
826
	LOG_DEBUG("RESUME PC %08" PRIx32 "%s", R(PC), !current ? "!" : "");
oharboe's avatar
oharboe committed
827

828
829
	/* clear breakpoints/watchpoints and VCR*/
	arm11_sc7_clear_vbw(arm11);
oharboe's avatar
oharboe committed
830

831
832
833
	/* Set up breakpoints */
	if (!debug_execution)
	{
834
		/* check if one matches PC and step over it if necessary */
oharboe's avatar
oharboe committed
835

836
		breakpoint_t *	bp;
oharboe's avatar
oharboe committed
837

838
		for (bp = target->breakpoints; bp; bp = bp->next)
839
		{
840
841
			if (bp->address == R(PC))
			{
duane's avatar
duane committed
842
				LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
843
844
845
				arm11_step(target, 1, 0, 0);
				break;
			}
846
		}
oharboe's avatar
oharboe committed
847

848
		/* set all breakpoints */
oharboe's avatar
oharboe committed
849

850
		size_t		brp_num = 0;
851

852
853
854
		for (bp = target->breakpoints; bp; bp = bp->next)
		{
			arm11_sc7_action_t	brp[2];
oharboe's avatar
oharboe committed
855

856
857
858
859
860
861
			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);
862

863
			arm11_sc7_run(arm11, brp, asizeof(brp));
oharboe's avatar
oharboe committed
864

duane's avatar
duane committed
865
			LOG_DEBUG("Add BP " ZU " at %08" PRIx32 "", brp_num, bp->address);
oharboe's avatar
oharboe committed
866

867
868
			brp_num++;
		}
oharboe's avatar
oharboe committed
869

870