From 83eeaa6280af46448fbc0eb56a274f01cc1f096a Mon Sep 17 00:00:00 2001
From: drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Sat, 9 Sep 2006 11:26:15 +0000
Subject: [PATCH] - set the T bit in the CPSR when the core was executing in
 Thumb state. Mask the T bit from the CPSR for all CPSR-writing operations

git-svn-id: svn://svn.berlios.de/openocd/trunk@97 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 src/target/arm7_9_common.c | 53 ++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index 40049e6b4..e58765877 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -930,12 +930,16 @@ int arm7_9_debug_entry(target_t *target)
 	
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
 		return retval;
+	
+	/* if the core has been executing in Thumb state, set the T bit */
+	if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
+		cpsr |= 0x20;	
+	
 	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;
 	
 	armv4_5->core_mode = cpsr & 0x1f;
-	DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
 	
 	if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
 	{
@@ -943,6 +947,8 @@ int arm7_9_debug_entry(target_t *target)
 		ERROR("cpsr contains invalid mode value - communication failure");
 		return ERROR_TARGET_FAILURE;
 	}
+
+	DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
 	
 	if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
 	{
@@ -1040,9 +1046,10 @@ int arm7_9_full_context(target_t *target)
 		{
 			u32 tmp_cpsr;
 			
-			/* change processor mode */
+			/* change processor mode (and mask T bit) */
 			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);
+			tmp_cpsr &= ~0x20;
 			arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 
 			for (j = 0; j < 15; j++)
@@ -1070,8 +1077,8 @@ int arm7_9_full_context(target_t *target)
 		}
 	}
 
-	/* restore processor mode */
-	arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+	/* 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);
 	
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
 	{
@@ -1150,9 +1157,10 @@ int arm7_9_restore_context(target_t *target)
 			{
 				u32 tmp_cpsr;
 			
-				/* change processor mode */
+				/* change processor mode (mask T bit) */
 				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);
+				tmp_cpsr &= ~0x20;
 				arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 				current_mode = armv4_5_number_to_mode(i);
 			}
@@ -1191,19 +1199,20 @@ int arm7_9_restore_context(target_t *target)
 	
 	if ((armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 0) && (armv4_5->core_mode != current_mode))
 	{
-		/* restore processor mode */
+		/* restore processor mode (mask T bit) */
 		u32 tmp_cpsr;
 			
 		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);
+		tmp_cpsr &= ~0x20;
 		DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", tmp_cpsr);
 		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 	}
 	else if (armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 1)
 	{
-		/* CPSR has been changed, full restore necessary */
+		/* CPSR has been changed, full restore necessary (mask T bit) */
 		DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
-		arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), 0);
+		arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32) & ~0x20, 0);
 		armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
 		armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
 	}
@@ -1514,9 +1523,10 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
 	{
 		u32 tmp_cpsr;
 			
-		/* change processor mode */
+		/* change processor mode (mask T bit) */
 		tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
 		tmp_cpsr |= mode;
+		tmp_cpsr &= ~0x20;
 		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 	}
 	
@@ -1544,8 +1554,8 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
 	if ((mode != ARMV4_5_MODE_ANY)
 			&& (mode != armv4_5->core_mode)
 			&& (reg_mode != ARMV4_5_MODE_ANY))	{
-		/* restore processor mode */
-		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+		/* 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);
 	}
 	
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
@@ -1574,9 +1584,10 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
 			&& (reg_mode != ARMV4_5_MODE_ANY))	{
 		u32 tmp_cpsr;
 			
-		/* change processor mode */
+		/* change processor mode (mask T bit) */
 		tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
 		tmp_cpsr |= mode;
+		tmp_cpsr &= ~0x20;
 		arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 	}
 	
@@ -1595,6 +1606,10 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
 		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;
 		
+		/* if we're writing the CPSR, mask the T bit */
+		if (!spsr)
+			value &= ~0x20;
+		
 		arm7_9->write_xpsr(target, value, spsr);
 	}
 	
@@ -1604,8 +1619,8 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
 	if ((mode != ARMV4_5_MODE_ANY)
 			&& (mode != armv4_5->core_mode)
 			&& (reg_mode != ARMV4_5_MODE_ANY))	{
-		/* restore processor mode */
-		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+		/* 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);
 	}
 	
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
@@ -1755,7 +1770,7 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 	{
 		ERROR("memory read caused data abort");
 
-		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
 
 		return ERROR_TARGET_DATA_ABORT;
 	}
@@ -1920,7 +1935,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 	{
 		ERROR("memory write caused data abort");
 
-		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+		arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
 
 		return ERROR_TARGET_DATA_ABORT;
 	}
@@ -2059,6 +2074,10 @@ int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cm
 	value = strtoul(args[0], NULL, 0);
 	spsr = strtol(args[1], NULL, 0);
 	
+	/* if we're writing the CPSR, mask the T bit */
+	if (!spsr)
+		value &= ~0x20;
+	
 	arm7_9->write_xpsr(target, value, spsr);
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
 	{
@@ -2100,7 +2119,7 @@ int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char
 	value = strtoul(args[0], NULL, 0);
 	rotate = strtol(args[1], NULL, 0);
 	spsr = strtol(args[2], NULL, 0);
-	
+		
 	arm7_9->write_xpsr_im8(target, value, rotate, spsr);
 	if ((retval = jtag_execute_queue()) != ERROR_OK)
 	{
-- 
GitLab