Sunday, 15 April 2012

c - GCC: Why is const data filled inside my function and not at the beginning? -


I want to benchmark the number of cycles used by various machine instructions on my system (for this example ARM is Cortex-M4). That's why I use a macro, which repeats the target instruction many times before and after it, I read the cycle counter of my controller. In ASM-dump, I see that const data (address of my circle-counter register) has been filled in some conditions (marked from 8003140 to 8003150, marked with ">"):

 < Code> 08002d58 & lt; TestThis>: 8002d58: 48fa ldr r0, [pc, # 1000]; (8003144 & lt; testThis + 0x3ec & gt;) 8002d5a: 49fb ldr r1, [pc, # 1004]; (8003148 & lt; testThis + 0x3f0>) 8002d5c: 4bfb ldr r3, [pc, # 1004]; (800314c & lt; testThis + 0x3f4 & gt;) 8002d5e: 4afc ldr r2, [pc, # 1008]; (8003150 & LT; testThis + 0x3f8 & gt;) 8002d60: 6800 LDR r0, [r0, # 0] 8002d62: 6008 str r0, [r1, # 0] 8002d64: 681b Leader R3, [R3, # 0] 8002d66: 6812 leader r2, [r2, # 0] 8002d68: fa82 f183 qadd r1, R3, r2 8002d6c: fa82 f183 qadd r1, R3, r2 .. 8,003,138: fa82 f183 qadd r1, R3, r2 800313c: fa82 f183 qadd r1, R3 , R2 & gt; 8003140: E 2008 Bn 8003154 & lt; TestThis + 0x3fc & gt; & Gt; 8003142: BFX NOP & gt; 8003144: e0001004.word 0xe0001004 & gt; 8003148: 20000598 Word 0x20000598 & gt; 800314c: 20000594 .word 0x20000594 & gt; 8003150: 200002e4 .word 0x200002e4 8,003,154: fa82 f183 qadd r1, r3, r2 8,003,158: fa82 f183 qadd r1, r3, r2 .. 8003b84: fa82 f183 qadd r1, r3, r2 8003b88: fa82 f383 qadd r3, r3, r2 8003b8c: 4803 L R R, [PC, # 12]; (8003b9c & lt; testThis + 0xe44 & gt;) 8003b8e: 4904 liter R1, [PC, # 16]; (8003ba0 & lt; testThis + 0xe48 & gt;) 8003b90: 6003 str r3, [r0, # 0] 8003b92: 4b04 ldr r3, [pc, # 16]; (8003ba4 & LT; testThis + 0xe4c & gt;) 8003b94: 680a leader r2, [r1, # 0] 8003b96: 601a str r2, [R3, # 0] 8003b98: 4770 bx LR 8003b9a: bf00 nop 8003b9c: 2000058c .word 0x2000058c 8003ba0: E0001004. Word 0xe0001004 8003ba4: 20000338. Word 0x20000338  

Why is it not filled in the beginning? Am I able to control it?

gcc version:

gcc version 4.8.3 20140228 (release) [ARM / embedded -4_8-branch revision 208322]

C-code:

  #define READCYCCNT () * ((volatile unsigned int *) 0xE0001004) uint32_t cyc_begin, cyc_end; Int c, a, b; Zero test this (Zero * obj) {cyc_begin = READCYCCNT (); REP (90,0, C, __QADD, A, B); Cyc_end = READCYCCNT (); }  

The RP-macro is a bit long. It only adds 900 calls

  c = __QADD (a, b)  

compiler-call:

  hands -atollic-EABI- GCC -c -mthumb -mcpu = Cortex-M4 -mfloat- ABI = softfp -mfpu = fpv4- Spi- D16 -std = gnu90 -DDEBUG = 1 I ../ Inc. I ../ CoreSupport -ai ../ Support of the device - Extension -Section-Section -FDA-class -G -Wall-O application \ Main.O.Check \ Application menu  

The compiler addressing the code relative to the PC, using his code as DDR instructions Has Tpnn. Those instructions contain only 5 bits to store the relative address, so they can use the data within the 0-124 word only from the current program counter position. This is the reason that the compiler has placed your data in the middle of the code. Here's the instructions for thumb.

There are several ways to avoid this. You can replace the macro with a hand written assembly that uses different addressing modes. You can change the variable by stabilizing and can not fully address. You can reduce your macro several times. To generate 32-bit instructions you can remove the -mathamb flag, which are more bits to address. It really depends on what you want to evaluate with your test.


No comments:

Post a Comment