1*** Comments *** 2 3ARM IT test. 4 The IT (If-Then) instruction makes up to four following instructions (the IT block) conditional. 5 The conditions can be all the same, or some of them can be the logical inverse of the others. 6 Syntax 7 IT{x{y{z}}} {cond} 8 where: 9 x - specifies the condition switch for the second instruction in the IT block. 10 y - specifies the condition switch for the third instruction in the IT block. 11 z - specifies the condition switch for the fourth instruction in the IT block. 12 cond - specifies the condition for the first instruction in the IT block. 13 The condition switch for the second, third and fourth instruction in the IT block can be either: 14 T - Then. Applies the condition cond to the instruction. 15 E - Else. Applies the inverse condition of cond to the instruction. 16Test ELF EvaluateConditionCode: 17 .text 18 .global _start 19 _start: 20 .thumb 21 22 MOV r6, #0b01111111 23 CMP r6, #0b10000001 /* Should set: Z=0, C=0, N=1, V=0 */ 24 CMP r6, #0b01111111 /* Should set: Z=1, C=1, N=0, V=0 */ 25 CMP r6, #0b01111110 /* Should set: Z=0, C=1, N=0, V=0 */ 26 MOV r1, #1 27 LSL r2, r1, #31 28 ADD r2, r2, r2 /* Should set: Z=1, C=1, N=0, V=1 */ 29 30Test ELF ITStatus: 31 .irq: 32 .arm 33 NOP 34 NOP 35 NOP 36 NOP 37 NOP 38 NOP 39 NOP 40 NOP 41 NOP 42 NOP 43 NOP 44 NOP 45 NOP 46 NOP 47 NOP 48 NOP 49 .word 0x80000D3 /* IRQ 16 jump address */ 50 .text 51 .global _start 52 _start: 53 .thumb 54 55 CPSIE I 56 MOV r6, #6 /* Sets value to r6 */ 57 CMP r6, #6 /* Compares register value to imm */ 58 59 /* Use of '.inst' is caused by gcc bug : https://bugs.launchpad.net/gcc-arm-embedded/+bug/1620025 */ 60 ITTET EQ 61 .inst 0x2101 /* MOV r1, #1 ; executes */ 62 .inst 0x2202 /* MOV r2, #2 ; executes */ 63 .inst 0x2303 /* MOV r3, #3 ; does not execute */ 64 .inst 0x2404 /* MOV r4, #4 ; executes */ 65 66 LDR r5, =0x20000000 /* Sets address to store register values */ 67 STR r1, [r5] /* Store register r1 value */ 68 ADD r5, r5, #4 /* Add 4 to address */ 69 STR r2, [r5] /* Store register r2 value */ 70 ADD r5, r5, #4 /* Add 4 to address */ 71 STR r3, [r5] /* Store register r3 value */ 72 ADD r5, r5, #4 /* Add 4 to address */ 73 STR r4, [r5] /* Store register r4 value */ 74 75 MOV r1, #0 /* Clear registers */ 76 MOV r2, #0 77 MOV r3, #0 78 MOV r4, #0 79 80 CMP r6, #7 81 82 ITEET GE 83 .inst 0x2101 /* MOV r1, #1 ; does not execute */ 84 .inst 0x2202 /* MOV r2, #2 ; executes */ 85 .inst 0x2303 /* MOV r3, #3 ; executes */ 86 .inst 0x2404 /* MOV r4, #4 ; does not execute*/ 87 88 ADD r5, r5, #4 89 STR r1, [r5] 90 ADD r5, r5, #4 91 STR r2, [r5] 92 ADD r5, r5, #4 93 STR r3, [r5] 94 ADD r5, r5, #4 95 STR r4, [r5] 96 97 /* Same tests but conditions unmet */ 98 99 MOV r1, #0 /* Clear registers */ 100 MOV r2, #0 101 MOV r3, #0 102 MOV r4, #0 103 104 CMP r6, #7 /* Compares register value to imm */ 105 106 /* Use of '.inst' is caused by gcc bug : https://bugs.launchpad.net/gcc-arm-embedded/+bug/1620025 */ 107 ITTET EQ 108 .inst 0x2101 /* MOV r1, #1 ; executes */ 109 .inst 0x2202 /* MOV r2, #2 ; executes */ 110 .inst 0x2303 /* MOV r3, #3 ; does not execute */ 111 .inst 0x2404 /* MOV r4, #4 ; executes */ 112 113 ADD r5, r5, #4 /* Add 4 to address */ 114 STR r1, [r5] /* Store register r1 value */ 115 ADD r5, r5, #4 /* Add 4 to address */ 116 STR r2, [r5] /* Store register r2 value */ 117 ADD r5, r5, #4 /* Add 4 to address */ 118 STR r3, [r5] /* Store register r3 value */ 119 ADD r5, r5, #4 /* Add 4 to address */ 120 STR r4, [r5] /* Store register r4 value */ 121 122 MOV r1, #0 /* Clear registers */ 123 MOV r2, #0 124 MOV r3, #0 125 MOV r4, #0 126 127 CMP r6, #4 128 129 ITEET GE 130 .inst 0x2101 /* MOV r1, #1 ; does not execute */ 131 .inst 0x2202 /* MOV r2, #2 ; executes */ 132 .inst 0x2303 /* MOV r3, #3 ; executes */ 133 .inst 0x2404 /* MOV r4, #4 ; does not execute*/ 134 135 ADD r5, r5, #4 136 STR r1, [r5] 137 ADD r5, r5, #4 138 STR r2, [r5] 139 ADD r5, r5, #4 140 STR r3, [r5] 141 ADD r5, r5, #4 142 STR r4, [r5] 143 144 NOP 145 ADD r1, r1, #1 /* IRQ 16 */ 146 ADD r1, r1, #2 147 ADD r1, r1, #4 148 MOVS PC, R14 149 150 /* Check if using cmp inside IT block changes flow */ 151 152 MOV r1, #0 /* Clear registers */ 153 MOV r2, #0 154 MOV r3, #0 155 MOV r4, #0 156 157 MOV r6, #6 158 CMP r6, #6 159 ITTET EQ 160 .inst 0x2e07 /* CMP 6,7 ; executes, changes flags */ 161 .inst 0x2202 /* MOV r2, #2 ; does not execute */ 162 .inst 0x2e06 /* CMP 6,6 ; executes, changes flags */ 163 .inst 0x2404 /* MOV r4, #4 ; executes */ 164 165 LDR r5, =0x20000000 /* Sets address to store register values */ 166 STR r1, [r5] /* Store register r1 value */ 167 ADD r5, r5, #4 /* Add 4 to address */ 168 STR r2, [r5] /* Store register r2 value */ 169 ADD r5, r5, #4 /* Add 4 to address */ 170 STR r3, [r5] /* Store register r3 value */ 171 ADD r5, r5, #4 /* Add 4 to address */ 172 STR r4, [r5] /* Store register r4 value */ 173 174 175 176IT_state Bits: 177 Name | IT_cond | a | b | c | d | e | 178 Bits | 7-5 | 4 | 3 | 2 | 1 | 0 | 179 The a, b, c, d, and e bits encode the number of instructions that are to be conditionally executed, and whether the condition for each is the base condition code or the inverse of the base condition code. They must contain b00000 when no IT block is active. Value of one means instruction should be skipped. 180 181 When an IT instruction is executed, these bits are set according to the condition in the instruction, and the Then and Else (T and E) parameters in the instruction. 182 During execution of an IT block, the a, b, c, d, and e bits are shifted left after every instruction: 183 - to reduce the number of instructions to be conditionally executed by one 184 - to move the next bit into position `a` basing on whichi the cpu decides if instruction should be executed. 185IT_cond: 186 To encode condition on 3 bits we omit last bit which always means reversing the condition, and negate abcde bits if neccessary. 187 For example: ITTET GT is encoded as IT_COND = 0b110 and abcde= 0b00101 188 ITTET LE is encoded as IT_COND = 0b110 and abcde= 0b11011 189 Bit denoting end of sequence always equals 1. 190 191 192*** Settings *** 193Library ${CURDIR}/../gdb/gdb_library.py 194 195*** Variables *** 196${URI} @https://dl.antmicro.com/projects/renode 197${ITSTATE_BIN} arm-itte-block-test-s_66284-3482e7f2e0d8849841c6ca6cafbf03104d2c4a31 198${CONDITION_BIN} arm-itte-condition-codes-test-s_65976-6ec62f42daaf672789f066bceaf75dc1e7865e6e 199${GDB_REMOTE_PORT} 3333 200*** Keywords *** 201Create Machine 202 [Arguments] ${elf} 203 204 Execute Command using sysbus 205 Execute Command mach create "STM32f4" 206 Execute Command machine LoadPlatformDescriptionFromString "cpu: CPU.CortexM @ sysbus { cpuType: \\"cortex-m4\\"; nvic: nvic }; nvic: IRQControllers.NVIC @ sysbus 0xE000E000 { systickFrequency: 72000000; IRQ -> cpu@0 }" 207 Execute Command machine LoadPlatformDescriptionFromString "flashuu: Memory.MappedMemory @ sysbus 0x08000000 { size: 0x200000 }" 208 Execute Command machine LoadPlatformDescriptionFromString "sram: Memory.MappedMemory @ sysbus 0x20000000 { size: 0x00040000 }" 209 Execute Command cpu MaximumBlockSize 1 210 Execute Command cpu PerformanceInMips 125 211 212 Execute Command sysbus LoadELF ${URI}/${elf} 213 Execute Command cpu PC 0x08000044 214 Execute Command cpu SP 0x08200000 215 216*** Test Cases *** 217Should Return Corrrect IT_STATUS Value 218 219 Create Machine ${ITSTATE_BIN} 220 221 Execute Command cpu Step 4 222 ${it}= Execute Command cpu GetItState 223 Should Contain ${it} 0x00000005 # IT_cond = 0b000; abcde bits = 0b00101 224 225Should Have Correct Condition Code 226 227 Create Machine ${ITSTATE_BIN} 228 229 Execute Command cpu Step 22 230 ${it}= Execute Command cpu GetItState 231 Should Contain ${it} 0x000000AD # IT_cond = 0b101; abcde bits = 0b00101 232 233Should Evaluate Condition Codes Properly 234 235 Create Machine ${CONDITION_BIN} 236 237 Execute Command cpu PC 0x8000000 238 239 #Flags: Z=0, N=1, C=0, V=0 240 Execute Command cpu Step 2 # After CMP 125, 127 241 ${eq1}= Execute Command cpu EvaluateConditionCode 0 # EQ 242 Should Contain ${eq1} False 243 ${cs1}= Execute Command cpu EvaluateConditionCode 2 # CS 244 Should Contain ${cs1} False 245 ${mi1}= Execute Command cpu EvaluateConditionCode 4 # MI 246 Should Contain ${mi1} True 247 ${vs1}= Execute Command cpu EvaluateConditionCode 6 # VS 248 Should Contain ${vs1} False 249 ${hi1}= Execute Command cpu EvaluateConditionCode 8 # HI 250 Should Contain ${hi1} False 251 ${ge1}= Execute Command cpu EvaluateConditionCode 10 # GE 252 Should Contain ${ge1} False 253 ${gt1}= Execute Command cpu EvaluateConditionCode 12 # GT 254 Should Contain ${gt1} False 255 ${al1}= Execute Command cpu EvaluateConditionCode 14 # AL 256 Should Contain ${al1} True 257 258 #NZCV, T=1 259 Register Should Be Equal 25 0x81000000 260 261 #Flags: Z=1, N=0, C=1, V=0 262 Execute Command cpu Step 1 # After CMP 125,125 263 ${eq2}= Execute Command cpu EvaluateConditionCode 0 # EQ 264 Should Contain ${eq2} True 265 ${cs2}= Execute Command cpu EvaluateConditionCode 2 # CS 266 Should Contain ${cs2} True 267 ${mi2}= Execute Command cpu EvaluateConditionCode 4 # MI 268 Should Contain ${mi2} False 269 ${vs2}= Execute Command cpu EvaluateConditionCode 6 # VS 270 Should Contain ${vs2} False 271 ${hi2}= Execute Command cpu EvaluateConditionCode 8 # HI 272 Should Contain ${hi2} False 273 ${ge2}= Execute Command cpu EvaluateConditionCode 10 # GE 274 Should Contain ${ge2} True 275 ${gt2}= Execute Command cpu EvaluateConditionCode 12 # GT 276 Should Contain ${gt2} False 277 ${al2}= Execute Command cpu EvaluateConditionCode 14 # AL 278 Should Contain ${al2} True 279 280 #NZCV, T=1 281 Register Should Be Equal 25 0x61000000 282 283 #Flags: Z=0, N=0, C=1, V=0 284 Execute Command cpu Step 1 # After CMP 125,124 285 ${eq3}= Execute Command cpu EvaluateConditionCode 0 # EQ 286 Should Contain ${eq3} False 287 ${cs3}= Execute Command cpu EvaluateConditionCode 2 # CS 288 Should Contain ${cs3} True 289 ${mi3}= Execute Command cpu EvaluateConditionCode 4 # MI 290 Should Contain ${mi3} False 291 ${vs3}= Execute Command cpu EvaluateConditionCode 6 # VS 292 Should Contain ${vs3} False 293 ${hi3}= Execute Command cpu EvaluateConditionCode 8 # HI 294 Should Contain ${hi3} True 295 ${ge3}= Execute Command cpu EvaluateConditionCode 10 # GE 296 Should Contain ${ge3} True 297 ${gt3}= Execute Command cpu EvaluateConditionCode 12 # GT 298 Should Contain ${gt3} True 299 ${al3}= Execute Command cpu EvaluateConditionCode 14 # AL 300 Should Contain ${al3} True 301 302 #NZCV, T=1 303 Register Should Be Equal 25 0x21000000 304 305 #Flags: Z=1, N=0, C=1, V=1 306 Execute Command cpu Step 3 # After ADD 2^31, 2^31 307 ${eq4}= Execute Command cpu EvaluateConditionCode 0 # EQ 308 Should Contain ${eq4} True 309 ${cs4}= Execute Command cpu EvaluateConditionCode 2 # CS 310 Should Contain ${cs4} True 311 ${mi4}= Execute Command cpu EvaluateConditionCode 4 # MI 312 Should Contain ${mi4} False 313 ${vs4}= Execute Command cpu EvaluateConditionCode 6 # VS 314 Should Contain ${vs4} True 315 ${hi4}= Execute Command cpu EvaluateConditionCode 8 # HI 316 Should Contain ${hi4} False 317 ${ge4}= Execute Command cpu EvaluateConditionCode 10 # GE 318 Should Contain ${ge4} False 319 ${gt4}= Execute Command cpu EvaluateConditionCode 12 # GT 320 Should Contain ${gt4} False 321 ${al4}= Execute Command cpu EvaluateConditionCode 14 # AL 322 Should Contain ${al4} True 323 324 #NZCV, T=1 325 Register Should Be Equal 25 0x71000000 326 327Should Shift State Bits After Every IT Block Instruction 328 329 Create Machine ${ITSTATE_BIN} 330 331 Execute Command cpu Step 4 332 ${it}= Execute Command cpu GetItState 333 ${next}= Execute Command cpu WillNextItInstructionExecute ${it} 334 Should Contain ${it} 0x00000005 # IT_cond = 0b000; abcde bits = 0b00101 335 Should Contain ${next} True 336 337 Execute Command cpu Step 338 ${it}= Execute Command cpu GetItState 339 ${next}= Execute Command cpu WillNextItInstructionExecute ${it} 340 Should Contain ${it} 0x0000000A # IT_cond = 0b000; abcde bits = 0b01010 341 Should Contain ${next} True 342 343 Execute Command cpu Step 344 ${it}= Execute Command cpu GetItState 345 ${next}= Execute Command cpu WillNextItInstructionExecute ${it} 346 Should Contain ${it} 0x00000014 # IT_cond = 0b000; abcde bits = 0b10100 347 Should Contain ${next} False 348 349 Execute Command cpu Step 350 ${it}= Execute Command cpu GetItState 351 ${next}= Execute Command cpu WillNextItInstructionExecute ${it} 352 Should Contain ${it} 0x00000008 # IT_cond = 0b000; abcde bits = 0b01000 353 Should Contain ${next} True 354 355 Execute Command cpu Step 356 ${it}= Execute Command cpu GetItState 357 Should Contain ${it} 0x00000000 # IT_cond = 0b000; abcde bits = 0b00000 358 359Should Execute Only 'Then' Instructions 360 361 Create Machine ${ITSTATE_BIN} 362 363 Execute Command cpu Step 16 # After CMP 6, 6 ; ITTET EQ 364 ${r1}= Execute Command sysbus ReadByte 0x20000000 365 ${r2}= Execute Command sysbus ReadByte 0x20000004 366 ${r3}= Execute Command sysbus ReadByte 0x20000008 367 ${r4}= Execute Command sysbus ReadByte 0x2000000C 368 Should Contain ${r1} 0x01 369 Should Contain ${r2} 0x02 370 Should Contain ${r3} 0x00 371 Should Contain ${r4} 0x04 372 Execute Command cpu Step 18 # After CMP 6, 7 ; ITEET GE 373 ${r1}= Execute Command sysbus ReadByte 0x20000010 374 ${r2}= Execute Command sysbus ReadByte 0x20000014 375 ${r3}= Execute Command sysbus ReadByte 0x20000018 376 ${r4}= Execute Command sysbus ReadByte 0x2000001C 377 Should Contain ${r1} 0x00 378 Should Contain ${r2} 0x02 379 Should Contain ${r3} 0x03 380 Should Contain ${r4} 0x00 381 Execute Command cpu Step 18 # After CMP 6,7 ; ITTET EQ 382 ${r1}= Execute Command sysbus ReadByte 0x20000020 383 ${r2}= Execute Command sysbus ReadByte 0x20000024 384 ${r3}= Execute Command sysbus ReadByte 0x20000028 385 ${r4}= Execute Command sysbus ReadByte 0x2000002C 386 Should Contain ${r1} 0x00 387 Should Contain ${r2} 0x00 388 Should Contain ${r3} 0x03 389 Should Contain ${r4} 0x00 390 Execute Command cpu Step 18 # After CMP 6,4 ; ITEET GE 391 ${r1}= Execute Command sysbus ReadByte 0x20000030 392 ${r2}= Execute Command sysbus ReadByte 0x20000034 393 ${r3}= Execute Command sysbus ReadByte 0x20000038 394 ${r4}= Execute Command sysbus ReadByte 0x2000003C 395 Should Contain ${r1} 0x01 396 Should Contain ${r2} 0x00 397 Should Contain ${r3} 0x00 398 Should Contain ${r4} 0x04 399 400Should Save and Restore State of IT Block Correctly 401 402 Create Machine ${ITSTATE_BIN} 403 404 Execute Command cpu Step 5 405 ${old}= Execute Command cpu GetItState 406 407 ${tmp_file}= Allocate Temporary File 408 Execute Command Save @${tmp_file} 409 Execute Command Load @${tmp_file} 410 Execute Command mach set 0 411 412 ${new}= Execute Command cpu GetItState 413 Should Be Equal ${old} ${new} 414 415 Execute Command cpu Step 416 ${it}= Execute Command cpu GetItState 417 Should Contain ${it} 0x00000014 418 419 Execute Command cpu Step 420 ${it}= Execute Command cpu GetItState 421 Should Contain ${it} 0x00000008 422 423 Execute Command cpu Step 10 424 ${r1}= Execute Command sysbus ReadByte 0x20000000 425 ${r2}= Execute Command sysbus ReadByte 0x20000004 426 ${r3}= Execute Command sysbus ReadByte 0x20000008 427 ${r4}= Execute Command sysbus ReadByte 0x2000000C 428 Should Contain ${r1} 0x01 429 Should Contain ${r2} 0x02 430 Should Contain ${r3} 0x00 431 Should Contain ${r4} 0x04 432 433Should Survive Interrupt 434 435 Create Machine ${ITSTATE_BIN} 436 437 Execute Command nvic WriteDoubleWord 0x100 0x01 438 Execute Command cpu Step 5 439 440 Execute Command nvic OnGPIO 0 true 441 Execute Command nvic OnGPIO 0 false 442 Execute Command cpu Step 443 ${pc}= Execute Command cpu PC 444 Should Contain ${pc} 0x80000d4 # Check if in interrupt 445 ${it}= Execute Command cpu GetItState 446 Should Contain ${it} 0x00 447 Execute Command cpu Step 4 # exit interrupt 448 ${it}= Execute Command cpu GetItState 449 Should Contain ${it} 0x0000000A 450 Execute Command cpu Step 11 451 452 453 ${r1}= Execute Command sysbus ReadByte 0x20000000 454 ${r2}= Execute Command sysbus ReadByte 0x20000004 455 ${r3}= Execute Command sysbus ReadByte 0x20000008 456 ${r4}= Execute Command sysbus ReadByte 0x2000000C 457 Should Contain ${r1} 0x01 458 Should Contain ${r2} 0x02 459 Should Contain ${r3} 0x00 460 Should Contain ${r4} 0x04 461 462Should Allow Condition Flag Change From Inside IT Block 463 464 Create Machine ${ITSTATE_BIN} 465 Execute Command cpu PC 0x080000dc 466 467 Execute Command cpu Step 7 # Inside It block; Before executing CMPEQ r6,#7 468 ${ev}= Execute Command cpu EvaluateConditionCode 0x00 # EQ 469 Should Contain ${ev} True 470 Execute Command cpu Step 1 # Before executing MOVEQ r2,#2 471 ${ev}= Execute Command cpu EvaluateConditionCode 0x00 # EQ 472 Should Contain ${ev} False 473 Execute Command cpu Step 1 # Before executing CMPNE r6,#6 474 ${ev}= Execute Command cpu EvaluateConditionCode 0x00 # EQ 475 Should Contain ${ev} False 476 Execute Command cpu Step 1 # Before executing MOVEQ r4,#4 477 ${ev}= Execute Command cpu EvaluateConditionCode 0x00 # EQ 478 Should Contain ${ev} True 479 ExecuteCommand cpu Step 10 480 ${r1}= Execute Command sysbus ReadByte 0x20000000 481 ${r2}= Execute Command sysbus ReadByte 0x20000004 482 ${r3}= Execute Command sysbus ReadByte 0x20000008 483 ${r4}= Execute Command sysbus ReadByte 0x2000000C 484 Should Contain ${r1} 0x00 485 Should Contain ${r2} 0x00 486 Should Contain ${r3} 0x00 487 Should Contain ${r4} 0x04 488 489 490Should Work in BlockBeginHooks 491 # Value returned in block begin concerns first instruction in current block 492 493 Create Machine ${ITSTATE_BIN} 494 Create Log Tester 5000 495 496 Execute Command cpu Step 3 497 Execute Command cpu SetHookAtBlockBegin "self.DebugLog('PC '+ str(self.PC) + ';IT_state ' + hex(self.GetItState()).rstrip('L'))" 498 Execute Command logLevel 0 499 Execute Command cpu Step 500 Wait For Log Entry Checking IT_STATE, while not in IT block 501 Wait For Log Entry PC 0x800004a;IT_state 0x0 502 Execute Command cpu Step 503 Wait For Log Entry PC 0x800004c;IT_state 0x5 504 Execute Command cpu Step 505 Wait For Log Entry PC 0x800004e;IT_state 0xa 506 Execute Command cpu Step 507 Wait For Log Entry PC 0x8000050;IT_state 0x14 508 Execute Command cpu Step 509 Wait For Log Entry PC 0x8000052;IT_state 0x8 510 Execute Command cpu Step 511 Wait For Log Entry Checking IT_STATE, while not in IT block 512 Wait For Log Entry PC 0x8000054;IT_state 0x0 513 514Should Work in BlockEndHooks 515 # In BlockEnd both PC and It_status concerns first instruction of next block 516 517 Create Machine ${ITSTATE_BIN} #PC = 0x8000044 518 Create Log Tester 5000 519 520 Execute Command cpu Step 3 #PC = 0x8000048 521 Execute Command cpu SetHookAtBlockEnd "self.DebugLog('PC '+ str(self.PC) + ';IT_state ' + hex(self.GetItState()).rstrip('L'))" 522 Execute Command logLevel 0 523 Execute Command cpu Step #PC = 0x800004a 524 Wait For Log Entry PC 0x800004c;IT_state 0x5 525 Execute Command cpu Step 526 Wait For Log Entry PC 0x800004e;IT_state 0xa 527 Execute Command cpu Step 528 Wait For Log Entry PC 0x8000050;IT_state 0x14 529 Execute Command cpu Step 530 Wait For Log Entry PC 0x8000052;IT_state 0x8 531 Execute Command cpu Step 532 Wait For Log Entry Checking IT_STATE, while not in IT block 533 Wait For Log Entry PC 0x8000054;IT_state 0x0 534 535