aboutsummaryrefslogtreecommitdiff
path: root/Debugger
diff options
context:
space:
mode:
authorTC Wan2011-07-06 15:24:11 +0800
committerTC Wan2011-07-06 15:24:11 +0800
commit4a7632650397fa87a5a962bb9e2a02f26099229e (patch)
tree78a070c9f6a0c0dd74fcebffb6f0dda267fc314d /Debugger
parent6351b5a7bf1fc79882767012510b34ff48f902f4 (diff)
updated arm condtion code check algorithm
The previous ARM Condition Code checking algorithm was incorrect due to an error in the LS condition requirements. Revised algorithm with some code optimization
Diffstat (limited to 'Debugger')
-rw-r--r--Debugger/debug_opcodes.S131
1 files changed, 81 insertions, 50 deletions
diff --git a/Debugger/debug_opcodes.S b/Debugger/debug_opcodes.S
index a2693b4..d43991d 100644
--- a/Debugger/debug_opcodes.S
+++ b/Debugger/debug_opcodes.S
@@ -595,37 +595,40 @@ debug_thumbDecodeTable:
* PL: N clr
* VS: V set
* VC: V clr
- * HI: C set AND Z clr
- * LS: C clr AND Z set
*/
debug_armCondCodeTable:
/* EQ, NE, HS/CS, LO/CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV */
- .byte 0x40, 0x04, 0x20, 0x02, 0x80, 0x08, 0x10, 0x01, 0x24, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
+ .byte 0x40, 0x04, 0x20, 0x02, 0x80, 0x08, 0x10, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
/* ARM Complex Condition Code Mapping Table
* Converts Instruction encoding to SPSR Flags.
* b31 b30 b29 b28
* N Z C V
* Indexed according to Instruction Encoding order (pg 30, Table 6, ATMEL ARM7TDMI Data Sheet)
- * for GE, LT, GT and LE instructions only
+ * for HI, LS, GE, LT, GT and LE instructions only
* Condition Code stored in the following order:
- * b7 b6 b5 b4 b3 b2 b1 b0
- * - - - ANDOR - Z set AND N==V (bit set = 1)
- * - - - - - Z clr OR N!=V (bit clr = 0)
+ * b7 b6 b5 b4 b3 b2 b1 b0
+ * AND CHKZ CHKC CHKNV - Z set C set N==V (bit set = 1)
+ * OR - - - - Z clr C clr N!=V (bit clr = 0)
*
+ * HI: C set AND Z clr
+ * LS: C clr OR Z set
* GE: N == V
* LT: N != V
* GT: Z clr AND (N == V)
* LE: Z set OR (N != V)
*/
-#define COMPLEX_CONDCODE_START 0x0A
-#define COMPLEX_CONDCODE_NEQV_MASK 0x01
-#define COMPLEX_CONDCODE_AND_MASK 0x02
-#define COMPLEX_CONDCODE_ZSET_MASK 0x04
-#define COMPLEX_CONDCODE_ANDOR_MASK 0x10
+#define COMPLEX_CONDCODE_START 0x08
+#define COMPLEX_CONDCODE_NEQV_MASK 0x01
+#define COMPLEX_CONDCODE_CSET_MASK 0x02
+#define COMPLEX_CONDCODE_ZSET_MASK 0x04
+#define COMPLEX_CONDCODE_CHKNV_MASK 0x10
+#define COMPLEX_CONDCODE_CHKC_MASK 0x20
+#define COMPLEX_CONDCODE_CHKZ_MASK 0x40
+#define COMPLEX_CONDCODE_ANDOR_MASK 0x80
#define COMPLEX_CONDCODE_NFLAG 0x08
#define COMPLEX_CONDCODE_ZFLAG 0x04
@@ -634,8 +637,8 @@ debug_armCondCodeTable:
debug_armComplexCCTable:
- /* GE, LT, GT, LE */
- .byte 0x01, 0x00, 0x13, 0x14
+ /* HI, LS, GE, LT, GT, LE */
+ .byte 0xE2, 0x64, 0x11, 0x10, 0xD1, 0x54
.code 32
.text
@@ -803,94 +806,122 @@ _exit_eval_thumb_instruction:
*/
_dbg_check_arm_condcode:
- mov r0, #TRUE
- mov r3, r4, lsr #28 /* convert condition code to index (0-F) */
+ mov r0, #TRUE /* Default will_execute value */
+ mov r3, r4, lsr #28 /* convert opcode's condition code to index (0-F) */
ldr r2, =debug_armCondCodeTable
ldrb r1, [r2, r3] /* Get condition code mask */
/*
- * The following check is unnecessary as it is covered by the set/clear checking algorithm
+ * The following check is unnecessary as it is covered by the _dbg_cond_simple_checks checking algorithm
teq r1, #0
beq _dbg_check_arm_condcode_exit
*/
teq r1, #0xFF
- bne _dbg_check_bits_set
+ bne _dbg_cond_simple_checks
/*
* Complex Checks:
+ * We assume that CHKNV and CHKC are mutually exclusive.
+ * In addition, it is possible for CHKNV, CHKC and CHKZ to
+ * be cleared, in which case it'll return True (default)
+ *
*
* will_execute = TRUE [default condition]
- * If (N == V) bit set
- * will_execute = (N == V)
- * else
- * will_execute = (N != V)
+ * If (CHKNV) set
+ * // Only N/V, and Z flags are involved
+ * NEQV_Flag = (N == V)
+ * will_execute = (NEQV_Flag == NEQV_Mask)
+ *
+ * If (CHKC) set
+ * // Only C and Z flags are involved
+ * will_execute = (C_Flag == CSet_Mask)
*
- * If (ANDOR bit) set
- * z_match = ~(Z XOR Z set)
+ * If (CHKZ) set
+ * z_match = (Z_Flag == ZSet_Mask)
* If (AND bit set)
* will_execute = will_execute && z_match
* else
* will_execute = will_execute || z_match
+ *
*/
-_dbg_cond_complex_check:
+_dbg_cond_complex_checks:
sub r3, r3, #COMPLEX_CONDCODE_START /* Convert complex condition code in R3 to new index (0-3) */
ldr r2, =debug_armComplexCCTable
ldrb r1, [r2, r3] /* Get complex condition code bitmap in R1 */
+_cond_check_nv:
+ tst r1, #COMPLEX_CONDCODE_CHKNV_MASK
+ beq _cond_check_c /* CHECKNV not set, so skip */
ands r2, r5, #(COMPLEX_CONDCODE_NFLAG | COMPLEX_CONDCODE_VFLAG) /* Is (N == V == 0)? */
teqne r2, #(COMPLEX_CONDCODE_NFLAG | COMPLEX_CONDCODE_VFLAG) /* No, Is (N == V == 1)? */
+
+ moveq r2, #COMPLEX_CONDCODE_NEQV_MASK /* EQ: Either (N == V == 0) or (N == V == 1), set R2: COMPLEX_CONDCODE_NEQV_MASK */
+ movne r2, #0 /* NE: N != V, clear R2 */
+ and r3, r1, #COMPLEX_CONDCODE_NEQV_MASK /* R3: Extract NEQV Mask Value */
+ teq r2, r3 /* Does N/V Condition match NEQV Mask value? */
+ movne r0, #FALSE /* No, so will_execute = FALSE (for now) */
+ b _cond_check_z
+
+#if 0
bne _cond_nnev /* No, so (N != V) */
/* EQ: Either (N == V == 0) or (N == V == 1) */
_cond_neqv:
tst r1, #COMPLEX_CONDCODE_NEQV_MASK /* Is (N == V) mask set? */
moveq r0, #FALSE /* No, so will_execute = FALSE (for now) */
- b _cond_check_andor
+ b _cond_check_z
/* Else, N != V */
_cond_nnev:
tst r1, #COMPLEX_CONDCODE_NEQV_MASK /* Is (N == V) mask set? */
movne r0, #FALSE /* Yes, so will_execute = FALSE (for now) */
+ b _cond_check_z
+#endif
+
+_cond_check_c:
+ tst r1, #COMPLEX_CONDCODE_CHKC_MASK
+ beq _cond_check_z /* CHECKC not set, so skip */
-_cond_check_andor:
- tst r1, #COMPLEX_CONDCODE_ANDOR_MASK
+ /* Use R2 to store C Flag, R3 to store CSet Mask */
+ and r2, r5, #COMPLEX_CONDCODE_CFLAG /* r2 = C flag */
+ and r3, r1, #COMPLEX_CONDCODE_CSET_MASK /* r3 = CSet mask */
+ teq r2, r3 /* Does C flag == CSet mask */
+ movne r0, #FALSE /* No, so C flag failed match */
+
+_cond_check_z:
+ tst r1, #COMPLEX_CONDCODE_CHKZ_MASK
beq _dbg_check_arm_condcode_exit /* No additional checks needed, exit */
- /* Use R2 to store Z Flag, R3 to store Z set Mask */
+ /* Use R2 to store Z Flag, R3 to store ZSet Mask */
and r2, r5, #COMPLEX_CONDCODE_ZFLAG /* r2 = Z flag */
- and r3, r1, #COMPLEX_CONDCODE_ZSET_MASK /* r3 = Z set */
- eors r2, r2, r3 /* r2 = (Z xor Z set): 0 if matched, non-zero if failed match */
+ and r3, r1, #COMPLEX_CONDCODE_ZSET_MASK /* r3 = ZSet mask */
+ teq r2, r3 /* Does Z flag == ZSet mask */
moveq r3, #TRUE /* Zero, so z flag matched */
movne r3, #FALSE /* Non-zero, so z flag failed match */
- tst r1, #COMPLEX_CONDCODE_AND_MASK /* Is AND mask set? */
+_cond_andor:
+ tst r1, #COMPLEX_CONDCODE_ANDOR_MASK /* Is ANDOR mask set? */
andne r0, r0, r3 /* Yes, so AND with will_execute */
orreq r0, r0, r3 /* No, so OR with will_execute */
b _dbg_check_arm_condcode_exit /* Return will_execute (R0) */
/*
* Simple Checks:
+ * We take advantage of the fact that only 1 bit would be set
+ * in the bitmask, by generating the corresponding actual
+ * CondSet[7:4], CondClr[3:0] value for comparison.
*
* will_execute = TRUE [default condition, equivalent to 0x00 (AL) ]
- * If (SetBitMask is Non-Zero)
- * will_execute = ((cond_code & SetBitMask) == SetBitMask)
- * If will_execute && (ClearBitMask is Non-Zero)
- * will_execute = will_execute && ((cond_code & ClearBitMask) == 0)
+ * Generate CondSetClr[7:0] from CPSR[3:0]
+ * will_execute = ((CondSetClr & BitMask) == BitMask)
+ *
*/
-
-_dbg_check_bits_set:
- movs r2, r1, lsr #4 /* R2: bits set */
- beq _dbg_check_bits_clear /* No bits set mask enabled, skip check */
- and r3, r5, r2 /* Check bits set IF bitmask non-zero */
- teq r2, r3 /* ((cond_code & SetBitMask) == SetBitMask)? */
- movne r0, #FALSE /* No, so will_execute = FALSE */
- bne _dbg_check_arm_condcode_exit /* Check failed (need to be TRUE to check bits clear), return */
-
-_dbg_check_bits_clear:
- ands r1, r1, #NIBBLE0 /* R1: bits clear */
- beq _dbg_check_arm_condcode_exit
- ands r3, r5, r1 /* Check bits clear IF bitmask non-zero */
- movne r0, #FALSE /* (cond_code & ClearBitMask) != 0, so will_execute = FALSE */
+_dbg_cond_simple_checks:
+ xor r2, r5, #NIBBLE0 /* R2: CondClr[3:0] = Invert CPSR[3:0] */
+ orr r2, r2, r5 lsl #4 /* R2: CondSet[7:4] | CondClr[3:0] */
+ and r2, r2, r1 /* R2: CondSetClr[7:0] & Bitmask */
+ teq r2, r1 /* ((cond_code & SetBitMask) == SetBitMask)? */
+ movne r0, #FALSE /* Not equal, check failed */
_dbg_check_arm_condcode_exit:
bx lr /* Return to caller */