arm7_9_common.c 81.9 KB
Newer Older
1001
1002
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
	}
1003

1004
	/* all register content is now invalid */
1005
1006
1007
1008
	if ((retval = armv4_5_invalidate_core_regs(target)) != ERROR_OK)
	{
		return retval;
	}
1009

1010
1011
1012
1013
	/* SVC, ARM state, IRQ and FIQ disabled */
	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
1014

1015
1016
1017
1018
	/* start fetching from 0x0 */
	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
	armv4_5->core_cache->reg_list[15].dirty = 1;
	armv4_5->core_cache->reg_list[15].valid = 1;
1019

1020
1021
	armv4_5->core_mode = ARMV4_5_MODE_SVC;
	armv4_5->core_state = ARMV4_5_STATE_ARM;
1022
1023
1024

	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1025

1026
1027
	/* reset registers */
	for (i = 0; i <= 14; i++)
1028
	{
1029
1030
1031
1032
		buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, 0xffffffff);
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
	}
1033

1034
1035
1036
1037
	if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
	{
		return retval;
	}
1038

1039
1040
1041
1042
1043
	return ERROR_OK;
}

int arm7_9_halt(target_t *target)
{
1044
	if (target->state==TARGET_RESET)
1045
	{
1046
		LOG_ERROR("BUG: arm7/9 does not support halt during reset. This is handled in arm7_9_assert_reset()");
1047
1048
1049
		return ERROR_OK;
	}

1050
1051
1052
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
1053

oharboe's avatar
oharboe committed
1054
	LOG_DEBUG("target->state: %s",
1055
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);
1056

1057
1058
	if (target->state == TARGET_HALTED)
	{
1059
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
1060
		return ERROR_OK;
1061
	}
1062

1063
1064
	if (target->state == TARGET_UNKNOWN)
	{
1065
		LOG_WARNING("target was in unknown state when halt was requested");
1066
	}
1067

1068
1069
1070
1071
	if (arm7_9->use_dbgrq)
	{
		/* program EmbeddedICE Debug Control Register to assert DBGRQ
		 */
oharboe's avatar
oharboe committed
1072
1073
1074
		if (arm7_9->set_special_dbgrq) {
			arm7_9->set_special_dbgrq(target);
		} else {
1075
			buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 1);
oharboe's avatar
oharboe committed
1076
1077
			embeddedice_store_reg(dbg_ctrl);
		}
1078
1079
1080
1081
1082
1083
1084
	}
	else
	{
		/* program watchpoint unit to match on any address
		 */
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
1085
1086
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
1087
1088
1089
	}

	target->debug_reason = DBG_REASON_DBGRQ;
1090

1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
	return ERROR_OK;
}

int arm7_9_debug_entry(target_t *target)
{
	int i;
	u32 context[16];
	u32* context_p[16];
	u32 r0_thumb, pc_thumb;
	u32 cpsr;
	int retval;
	/* get pointers to arch-specific information */
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];

#ifdef _DEBUG_ARM7_9_
1109
	LOG_DEBUG("-");
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
#endif

	if (arm7_9->pre_debug_entry)
		arm7_9->pre_debug_entry(target);

	/* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
	 * ensure that DBGRQ is cleared
	 */
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
	embeddedice_store_reg(dbg_ctrl);
1122

1123
1124
1125
1126
	if ((retval = arm7_9_clear_halt(target)) != ERROR_OK)
	{
		return retval;
	}
1127

1128
1129
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
1130
		return retval;
1131
1132
1133
1134
1135
1136
1137
1138
	}

	if ((retval = arm7_9->examine_debug_reason(target)) != ERROR_OK)
		return retval;


	if (target->state != TARGET_HALTED)
	{
1139
		LOG_WARNING("target not halted");
1140
1141
		return ERROR_TARGET_NOT_HALTED;
	}
1142

1143
1144
1145
	/* if the target is in Thumb state, change to ARM state */
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1))
	{
1146
		LOG_DEBUG("target entered debug from Thumb state");
1147
1148
1149
		/* Entered debug from Thumb mode */
		armv4_5->core_state = ARMV4_5_STATE_THUMB;
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
1150
		LOG_DEBUG("r0_thumb: 0x%8.8x, pc_thumb: 0x%8.8x", r0_thumb, pc_thumb);
1151
1152
1153
	}
	else
	{
1154
		LOG_DEBUG("target entered debug from ARM state");
1155
1156
1157
		/* Entered debug from ARM mode */
		armv4_5->core_state = ARMV4_5_STATE_ARM;
	}
1158

1159
1160
1161
1162
1163
1164
	for (i = 0; i < 16; i++)
		context_p[i] = &context[i];
	/* save core registers (r0 - r15 of current core mode) */
	arm7_9->read_core_regs(target, 0xffff, context_p);

	arm7_9->read_xpsr(target, &cpsr, 0);
1165

1166
1167
	if ((retval = jtag_execute_queue()) != ERROR_OK)
		return retval;
1168

1169
1170
	/* if the core has been executing in Thumb state, set the T bit */
	if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
1171
1172
		cpsr |= 0x20;

1173
1174
1175
	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
1176

1177
	armv4_5->core_mode = cpsr & 0x1f;
1178

1179
1180
1181
	if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
	{
		target->state = TARGET_UNKNOWN;
1182
		LOG_ERROR("cpsr contains invalid mode value - communication failure");
1183
1184
		return ERROR_TARGET_FAILURE;
	}
1185

1186
	LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
1187

1188
1189
	if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
	{
1190
		LOG_DEBUG("thumb state, applying fixups");
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
		context[0] = r0_thumb;
		context[15] = pc_thumb;
	} else if (armv4_5->core_state == ARMV4_5_STATE_ARM)
	{
		/* adjust value stored by STM */
		context[15] -= 3 * 4;
	}

	if ((target->debug_reason == DBG_REASON_BREAKPOINT)
			|| (target->debug_reason == DBG_REASON_SINGLESTEP)
			|| (target->debug_reason == DBG_REASON_WATCHPOINT)
			|| (target->debug_reason == DBG_REASON_WPTANDBKPT)
			|| ((target->debug_reason == DBG_REASON_DBGRQ) && (arm7_9->use_dbgrq == 0)))
		context[15] -= 3 * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2);
	else if (target->debug_reason == DBG_REASON_DBGRQ)
		context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2);
	else
	{
1209
		LOG_ERROR("unknown debug reason: %i", target->debug_reason);
1210
1211
	}

1212
1213
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1214

1215
1216
	for (i=0; i<=15; i++)
	{
1217
		LOG_DEBUG("r%i: 0x%8.8x", i, context[i]);
1218
1219
1220
1221
		buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, context[i]);
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
	}
1222

1223
	LOG_DEBUG("entered debug state at PC 0x%x", context[15]);
1224

1225
1226
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1227
1228

	/* exceptions other than USR & SYS have a saved program status register */
1229
	if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS))
1230
1231
1232
	{
		u32 spsr;
		arm7_9->read_xpsr(target, &spsr, 1);
1233
1234
1235
1236
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
1237
1238
1239
1240
1241
1242
		buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, spsr);
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;
	}

	/* r0 and r15 (pc) have to be restored later */
1243
1244
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).valid;
1245

1246
	if ((retval = jtag_execute_queue()) != ERROR_OK)
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
		return retval;

	if (arm7_9->post_debug_entry)
		arm7_9->post_debug_entry(target);

	return ERROR_OK;
}

int arm7_9_full_context(target_t *target)
{
	int i;
	int retval;
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;

1262
	LOG_DEBUG("-");
1263

1264
1265
	if (target->state != TARGET_HALTED)
	{
1266
		LOG_WARNING("target not halted");
1267
1268
		return ERROR_TARGET_NOT_HALTED;
	}
1269

1270
1271
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281

	/* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND)
	 * SYS shares registers with User, so we don't touch SYS
	 */
	for(i = 0; i < 6; i++)
	{
		u32 mask = 0;
		u32* reg_p[16];
		int j;
		int valid = 1;
1282
1283

		/* check if there are invalid registers in the current mode
1284
1285
1286
1287
1288
1289
		 */
		for (j = 0; j <= 16; j++)
		{
			if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
				valid = 0;
		}
1290

1291
1292
1293
		if (!valid)
		{
			u32 tmp_cpsr;
1294

1295
			/* change processor mode (and mask T bit) */
1296
1297
			tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
			tmp_cpsr |= armv4_5_number_to_mode(i);
1298
			tmp_cpsr &= ~0x20;
1299
1300
1301
1302
1303
			arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);

			for (j = 0; j < 15; j++)
			{
				if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
1304
				{
1305
1306
1307
1308
1309
1310
					reg_p[j] = (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).value;
					mask |= 1 << j;
					ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid = 1;
					ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
				}
			}
1311

1312
1313
1314
			/* if only the PSR is invalid, mask is all zeroes */
			if (mask)
				arm7_9->read_core_regs(target, mask, reg_p);
1315

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
			/* check if the PSR has to be read */
			if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid == 0)
			{
				arm7_9->read_xpsr(target, (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).value, 1);
				ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid = 1;
				ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
			}
		}
	}

1326
1327
	/* restore processor mode (mask T bit) */
	arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
1328

1329
1330
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
1331
		return retval;
1332
1333
1334
1335
1336
1337
1338
1339
	}
	return ERROR_OK;
}

int arm7_9_restore_context(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1340
	reg_t *reg;
1341
1342
1343
1344
1345
	armv4_5_core_reg_t *reg_arch_info;
	enum armv4_5_mode current_mode = armv4_5->core_mode;
	int i, j;
	int dirty;
	int mode_change;
1346

1347
	LOG_DEBUG("-");
1348

1349
1350
	if (target->state != TARGET_HALTED)
	{
1351
		LOG_WARNING("target not halted");
1352
1353
		return ERROR_TARGET_NOT_HALTED;
	}
1354

1355
1356
	if (arm7_9->pre_restore_context)
		arm7_9->pre_restore_context(target);
1357

1358
1359
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1360

1361
1362
1363
1364
1365
	/* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND)
	 * SYS shares registers with User, so we don't touch SYS
	 */
	for (i = 0; i < 6; i++)
	{
1366
		LOG_DEBUG("examining %s mode", armv4_5_mode_strings[i]);
1367
1368
		dirty = 0;
		mode_change = 0;
1369
		/* check if there are dirty registers in the current mode
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
		*/
		for (j = 0; j <= 16; j++)
		{
			reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j);
			reg_arch_info = reg->arch_info;
			if (reg->dirty == 1)
			{
				if (reg->valid == 1)
				{
					dirty = 1;
1380
					LOG_DEBUG("examining dirty reg: %s", reg->name);
1381
1382
					if ((reg_arch_info->mode != ARMV4_5_MODE_ANY)
						&& (reg_arch_info->mode != current_mode)
1383
						&& !((reg_arch_info->mode == ARMV4_5_MODE_USR) && (armv4_5->core_mode == ARMV4_5_MODE_SYS))
1384
1385
1386
						&& !((reg_arch_info->mode == ARMV4_5_MODE_SYS) && (armv4_5->core_mode == ARMV4_5_MODE_USR)))
					{
						mode_change = 1;
1387
						LOG_DEBUG("require mode change");
1388
1389
1390
1391
					}
				}
				else
				{
1392
					LOG_ERROR("BUG: dirty register '%s', but no valid data", reg->name);
1393
1394
1395
				}
			}
		}
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
		if (dirty)
		{
			u32 mask = 0x0;
			int num_regs = 0;
			u32 regs[16];

			if (mode_change)
			{
				u32 tmp_cpsr;
1406

1407
				/* change processor mode (mask T bit) */
1408
1409
				tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
				tmp_cpsr |= armv4_5_number_to_mode(i);
1410
				tmp_cpsr &= ~0x20;
1411
1412
1413
				arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
				current_mode = armv4_5_number_to_mode(i);
			}
1414

1415
1416
1417
1418
			for (j = 0; j <= 14; j++)
			{
				reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j);
				reg_arch_info = reg->arch_info;
1419
1420


1421
1422
1423
1424
1425
1426
1427
				if (reg->dirty == 1)
				{
					regs[j] = buf_get_u32(reg->value, 0, 32);
					mask |= 1 << j;
					num_regs++;
					reg->dirty = 0;
					reg->valid = 1;
1428
					LOG_DEBUG("writing register %i of mode %s with value 0x%8.8x", j, armv4_5_mode_strings[i], regs[j]);
1429
1430
				}
			}
1431

1432
1433
1434
1435
			if (mask)
			{
				arm7_9->write_core_regs(target, mask, regs);
			}
1436

1437
1438
1439
1440
			reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16);
			reg_arch_info = reg->arch_info;
			if ((reg->dirty) && (reg_arch_info->mode != ARMV4_5_MODE_ANY))
			{
1441
				LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8x", i, buf_get_u32(reg->value, 0, 32));
1442
1443
1444
1445
				arm7_9->write_xpsr(target, buf_get_u32(reg->value, 0, 32), 1);
			}
		}
	}
1446

1447
1448
	if ((armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 0) && (armv4_5->core_mode != current_mode))
	{
1449
		/* restore processor mode (mask T bit) */
1450
		u32 tmp_cpsr;
1451

1452
1453
		tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
		tmp_cpsr |= armv4_5_number_to_mode(i);
1454
		tmp_cpsr &= ~0x20;
1455
		LOG_DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", tmp_cpsr);
1456
1457
1458
1459
		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
	}
	else if (armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 1)
	{
1460
		/* CPSR has been changed, full restore necessary (mask T bit) */
1461
		LOG_DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
1462
		arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32) & ~0x20, 0);
1463
1464
1465
		armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
		armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
	}
1466

1467
	/* restore PC */
1468
	LOG_DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
1469
1470
	arm7_9->write_pc(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
	armv4_5->core_cache->reg_list[15].dirty = 0;
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
	if (arm7_9->post_restore_context)
		arm7_9->post_restore_context(target);

	return ERROR_OK;
}

int arm7_9_restart_core(struct target_s *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
1483

1484
	/* set RESTART instruction */
1485
	jtag_add_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
1486
1487
1488
1489
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
1490
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
1491

1492
	jtag_add_runtest(1, TAP_IDLE);
1493
	return jtag_execute_queue();
1494
1495
1496
1497
1498
}

void arm7_9_enable_watchpoints(struct target_s *target)
{
	watchpoint_t *watchpoint = target->watchpoints;
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
	while (watchpoint)
	{
		if (watchpoint->set == 0)
			arm7_9_set_watchpoint(target, watchpoint);
		watchpoint = watchpoint->next;
	}
}

void arm7_9_enable_breakpoints(struct target_s *target)
{
	breakpoint_t *breakpoint = target->breakpoints;
1511

1512
1513
1514
	/* set any pending breakpoints */
	while (breakpoint)
	{
1515
		arm7_9_set_breakpoint(target, breakpoint);
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
		breakpoint = breakpoint->next;
	}
}

int arm7_9_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	breakpoint_t *breakpoint = target->breakpoints;
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
1526
	int err, retval = ERROR_OK;
1527

1528
	LOG_DEBUG("-");
1529

1530
1531
	if (target->state != TARGET_HALTED)
	{
1532
		LOG_WARNING("target not halted");
1533
1534
		return ERROR_TARGET_NOT_HALTED;
	}
1535

1536
1537
1538
1539
	if (!debug_execution)
	{
		target_free_all_working_areas(target);
	}
1540

1541
1542
1543
	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
		buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
1544

oharboe's avatar
oharboe committed
1545
1546
1547
	u32 current_pc;
	current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);

1548
1549
1550
1551
1552
	/* the front-end may request us not to handle breakpoints */
	if (handle_breakpoints)
	{
		if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
		{
1553
			LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
1554
1555
1556
1557
			if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
			{
				return retval;
			}
1558

oharboe's avatar
oharboe committed
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
			/* calculate PC of next instruction */
			u32 next_pc;
			if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
			{
				u32 current_opcode;
				target_read_u32(target, current_pc, &current_opcode);
				LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
				return retval;
			}

1569
			LOG_DEBUG("enable single-step");
oharboe's avatar
oharboe committed
1570
			arm7_9->enable_single_step(target, next_pc);
1571

1572
1573
			target->debug_reason = DBG_REASON_SINGLESTEP;

1574
1575
1576
1577
			if ((retval = arm7_9_restore_context(target)) != ERROR_OK)
			{
				return retval;
			}
1578

1579
1580
1581
1582
1583
1584
1585
1586
			if (armv4_5->core_state == ARMV4_5_STATE_ARM)
				arm7_9->branch_resume(target);
			else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
			{
				arm7_9->branch_resume_thumb(target);
			}
			else
			{
1587
				LOG_ERROR("unhandled core state");
1588
				return ERROR_FAIL;
1589
			}
1590

1591
1592
			buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
			embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size));
1593
			err = arm7_9_execute_sys_speed(target);
1594

1595
			LOG_DEBUG("disable single-step");
1596
			arm7_9->disable_single_step(target);
1597
1598
1599

			if (err != ERROR_OK)
			{
1600
1601
1602
1603
				if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK)
				{
					return retval;
				}
1604
1605
1606
1607
				target->state = TARGET_UNKNOWN;
				return err;
			}

1608
			arm7_9_debug_entry(target);
1609
			LOG_DEBUG("new PC after step: 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
1610

1611
			LOG_DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);
1612
1613
1614
1615
			if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK)
			{
				return retval;
			}
1616
1617
		}
	}
1618

1619
1620
1621
	/* enable any pending breakpoints and watchpoints */
	arm7_9_enable_breakpoints(target);
	arm7_9_enable_watchpoints(target);
1622

1623
1624
1625
1626
	if ((retval = arm7_9_restore_context(target)) != ERROR_OK)
	{
		return retval;
	}
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
	if (armv4_5->core_state == ARMV4_5_STATE_ARM)
	{
		arm7_9->branch_resume(target);
	}
	else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
	{
		arm7_9->branch_resume_thumb(target);
	}
	else
	{
1638
		LOG_ERROR("unhandled core state");
1639
		return ERROR_FAIL;
1640
	}
1641

1642
1643
1644
1645
1646
1647
	/* deassert DBGACK and INTDIS */
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
	/* INTDIS only when we really resume, not during debug execution */
	if (!debug_execution)
		buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 0);
	embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size));
1648

1649
1650
1651
1652
	if ((retval = arm7_9_restart_core(target)) != ERROR_OK)
	{
		return retval;
	}
1653

1654
	target->debug_reason = DBG_REASON_NOTHALTED;
1655

1656
1657
1658
1659
1660
	if (!debug_execution)
	{
		/* registers are now invalid */
		armv4_5_invalidate_core_regs(target);
		target->state = TARGET_RUNNING;
1661
1662
1663
1664
		if ((retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED)) != ERROR_OK)
		{
			return retval;
		}
1665
1666
1667
1668
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
1669
1670
1671
1672
		if ((retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED)) != ERROR_OK)
		{
			return retval;
		}
1673
	}
1674

1675
	LOG_DEBUG("target resumed");
1676

1677
1678
1679
	return ERROR_OK;
}

oharboe's avatar
oharboe committed
1680
void arm7_9_enable_eice_step(target_t *target, u32 next_pc)
1681
1682
1683
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1684

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
	u32 current_pc;
	current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);

	if(next_pc != current_pc)
	{
		/* setup an inverse breakpoint on the current PC
		* - comparator 1 matches the current address
		* - rangeout from comparator 1 is connected to comparator 0 rangein
		* - comparator 0 matches any address, as long as rangein is low */
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~(EICE_W_CTRL_RANGE|EICE_W_CTRL_nOPC) & 0xff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], current_pc);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
	}
	else
	{
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], next_pc);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
	}
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
}

void arm7_9_disable_eice_step(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;

	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK]);
	embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]);
}

int arm7_9_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1738
	breakpoint_t *breakpoint = NULL;
1739
	int err, retval;
1740
1741
1742

	if (target->state != TARGET_HALTED)
	{
1743
		LOG_WARNING("target not halted");
1744
1745
		return ERROR_TARGET_NOT_HALTED;
	}
1746

1747
1748
1749
	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
		buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
1750

oharboe's avatar
oharboe committed
1751
1752
1753
	u32 current_pc;
	current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);

1754
1755
1756
	/* the front-end may request us not to handle breakpoints */
	if (handle_breakpoints)
		if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
1757
1758
1759
1760
			if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
			{
				return retval;
			}
1761

1762
1763
	target->debug_reason = DBG_REASON_SINGLESTEP;

oharboe's avatar
oharboe committed
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
	/* calculate PC of next instruction */
	u32 next_pc;
	if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
	{
		u32 current_opcode;
		target_read_u32(target, current_pc, &current_opcode);
		LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
		return retval;
	}

1774
1775
1776
1777
	if ((retval = arm7_9_restore_context(target)) != ERROR_OK)
	{
		return retval;
	}
1778

oharboe's avatar
oharboe committed
1779
	arm7_9->enable_single_step(target, next_pc);
1780

1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
	if (armv4_5->core_state == ARMV4_5_STATE_ARM)
	{
		arm7_9->branch_resume(target);
	}
	else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
	{
		arm7_9->branch_resume_thumb(target);
	}
	else
	{
1791
		LOG_ERROR("unhandled core state");
1792
		return ERROR_FAIL;
1793
	}
1794

1795
1796
1797
1798
	if ((retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED)) != ERROR_OK)
	{
		return retval;
	}
1799

1800
	err = arm7_9_execute_sys_speed(target);
1801
	arm7_9->disable_single_step(target);
1802

1803
1804
	/* registers are now invalid */
	armv4_5_invalidate_core_regs(target);
1805

1806
1807
1808
1809
1810
	if (err != ERROR_OK)
	{
		target->state = TARGET_UNKNOWN;
	} else {
		arm7_9_debug_entry(target);
1811
1812
1813
1814
		if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
		{
			return retval;
		}
1815
		LOG_DEBUG("target stepped");
1816
	}
1817

1818
	if (breakpoint)
1819
1820
1821
1822
		if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK)
		{
			return retval;
		}
1823

1824
	return err;
1825
1826
1827
1828
1829
}

int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
{
	u32* reg_p[16];
1830
	u32 value;
1831
1832
1833
	int retval;
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1834

1835
1836
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1837

1838
	enum armv4_5_mode reg_mode = ((armv4_5_core_reg_t*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info)->mode;
1839

1840
1841
	if ((num < 0) || (num > 16))
		return ERROR_INVALID_ARGUMENTS;
1842

1843
1844
1845
1846
1847
	if ((mode != ARMV4_5_MODE_ANY)
			&& (mode != armv4_5->core_mode)
			&& (reg_mode != ARMV4_5_MODE_ANY))
	{
		u32 tmp_cpsr;
1848

1849
		/* change processor mode (mask T bit) */
1850
1851
		tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
		tmp_cpsr |= mode;
1852
		tmp_cpsr &= ~0x20;
1853
1854
		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
	}
1855

1856
1857
1858
	if ((num >= 0) && (num <= 15))
	{
		/* read a normal core register */
1859
		reg_p[num] = &value;
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
		arm7_9->read_core_regs(target, 1 << num, reg_p);
	}
	else
	{
		/* read a program status register
		 * if the register mode is MODE_ANY, we read the cpsr, otherwise a spsr
		 */
		armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
		int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
1870

1871
		arm7_9->read_xpsr(target, &value, spsr);
1872
	}
1873

1874
1875
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
1876
		return retval;
1877
	}
1878

1879
1880
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
1881
	buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, 0, 32, value);
1882

1883
1884
1885
	if ((mode != ARMV4_5_MODE_ANY)
			&& (mode != armv4_5->core_mode)
			&& (reg_mode != ARMV4_5_MODE_ANY))	{
1886
1887
		/* restore processor mode (mask T bit) */
		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
1888
	}
1889

1890
1891
1892
1893
1894
1895
1896
1897
	return ERROR_OK;
}

int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value)
{
	u32 reg[16];
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1898

1899
1900
	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
1901

1902
1903
1904
1905
	enum armv4_5_mode reg_mode = ((armv4_5_core_reg_t*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info)->mode;

	if ((num < 0) || (num > 16))
		return ERROR_INVALID_ARGUMENTS;
1906

1907
1908
1909
1910
	if ((mode != ARMV4_5_MODE_ANY)
			&& (mode != armv4_5->core_mode)
			&& (reg_mode != ARMV4_5_MODE_ANY))	{
		u32 tmp_cpsr;
1911

1912
		/* change processor mode (mask T bit) */
1913
1914
		tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
		tmp_cpsr |= mode;
1915
		tmp_cpsr &= ~0x20;
1916
1917
		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
	}
1918

1919
1920
1921
1922
	if ((num >= 0) && (num <= 15))
	{
		/* write a normal core register */
		reg[num] = value;
1923

1924
1925
1926
1927
1928
1929
1930
1931
1932
		arm7_9->write_core_regs(target, 1 << num, reg);
	}
	else
	{
		/* write a program status register
		* if the register mode is MODE_ANY, we write the cpsr, otherwise a spsr
		*/
		armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
		int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
1933

1934
1935
1936
		/* if we're writing the CPSR, mask the T bit */
		if (!spsr)
			value &= ~0x20;
1937

1938
1939
		arm7_9->write_xpsr(target, value, spsr);
	}
1940

1941
1942
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
1943

1944
1945
1946
	if ((mode != ARMV4_5_MODE_ANY)
			&& (mode != armv4_5->core_mode)
			&& (reg_mode != ARMV4_5_MODE_ANY))	{
1947
1948
		/* restore processor mode (mask T bit) */
		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
1949
	}
1950

1951
	return jtag_execute_queue();
1952
1953
1954
1955
1956
1957
}

int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
1958

1959
	u32 reg[16];
1960
	u32 num_accesses = 0;
1961
1962
1963
1964
1965
	int thisrun_accesses;
	int i;
	u32 cpsr;
	int retval;
	int last_reg = 0;
1966

1967
	LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
1968
1969
1970

	if (target->state != TARGET_HALTED)
	{
1971
		LOG_WARNING("target not halted");
1972
1973
1974
1975
1976
1977
1978
1979
1980
		return ERROR_TARGET_NOT_HALTED;
	}

	/* sanitize arguments */
	if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
		return ERROR_INVALID_ARGUMENTS;

	if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
		return ERROR_TARGET_UNALIGNED_ACCESS;
1981

1982
1983
1984
	/* load the base register with the address of the first word */
	reg[0] = address;
	arm7_9->write_core_regs(target, 0x1, reg);
1985

oharboe's avatar
oharboe committed
1986
1987
	int j=0;

1988
1989
1990
1991
1992
1993
1994
1995
	switch (size)
	{
		case 4:
			while (num_accesses < count)
			{
				u32 reg_list;
				thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
				reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
1996

1997
1998
				if (last_reg <= thisrun_accesses)
					last_reg = thisrun_accesses;
1999

2000
				arm7_9->load_word_regs(target, reg_list);
For faster browsing, not all history is shown. View entire blame