rendered paste body/* This code reads random values from memory and adds or subtracts one
* depending on the sign of the read value. With branch folding enabled, it
* takes the wrong branch about once every million times.
*
* To run the test, compile and link it like this:
* avr32-gcc -nostdlib -mcpu=ap7000 wrong-branch-test-standalone-interrupts.S -o wrong-branch-test-standalone-interrupts.elf
*/
#include <avr32/io.h>
#include <avr32/intc.h>
#define PLL_MUL 7
#define PLL_DIV 1
#define COUNT_INCREASE 100000
#define LOOP_ALGO 1
.global _start
_start:
mov r0, 0
cache r0[4], 8
cache r0[0], 0
sync 0
mov sp, lo(AVR32_SRAM1_ADDRESS + AVR32_SRAM1_SIZE)
orh sp, hi(AVR32_SRAM1_ADDRESS + AVR32_SRAM1_SIZE)
rcall main
1: breakpoint
rjmp 1b
.balign(0x1000)
_evba:
rjmp unknown_exception /* Unrecoverable exception */
nop
rjmp unknown_exception /* TLB multiple hit */
nop
rjmp unknown_exception /* Bus error data fetch */
nop
rjmp unknown_exception /* Bus error instruction fetch */
nop
rjmp unknown_exception /* NMI */
nop
rjmp unknown_exception /* Instruction address */
nop
rjmp unknown_exception /* ITLB miss */
nop
rjmp unknown_exception /* ITLB protection */
nop
rjmp unknown_exception /* Breakpoint */
nop
rjmp unknown_exception /* Illegal opcode */
nop
rjmp unknown_exception /* Unimplemented instruction */
nop
rjmp unknown_exception /* Privilege violation */
nop
rjmp unknown_exception /* Floating-point */
nop
rjmp unknown_exception /* Coprocessor absent */
nop
rjmp unknown_exception /* Supervisor call */
nop
rjmp unknown_exception /* Data address (read) */
nop
rjmp unknown_exception /* Data address (write) */
nop
rjmp unknown_exception /* DTLB miss (read) */
nop
rjmp unknown_exception /* DTLB miss (write) */
nop
rjmp unknown_exception /* DTLB protection (read) */
nop
rjmp unknown_exception /* DTLB protection (write) */
nop
rjmp unknown_exception /* DTLB modified */
nop
.size _evba, . - _evba
.align(2)
.type int0_handler, %function
.func int0_handler
int0_handler:
/* Increment COMPARE with COUNT_INCREASE variable
* r11 holds the COMPARE value set last time (and during init)
* r12 holds COUNT_INCREASE value
*/
add r11, r12
subeq r11, -1
mtsr AVR32_COMPARE, r11
rete
.endfunc
.align(2)
.type unknown_exception, %function
.func unknown_exception
unknown_exception:
rete
.endfunc
.align(2)
.type main, %function
.func main
main:
setup_smc_cs0_timing:
/* Setup SMC CS0 timings */
mov r6, lo(AVR32_SMC_ADDRESS)
orh r6, hi(AVR32_SMC_ADDRESS)
mov r9, lo(0x00031103)
orh r9, hi(0x00031103)
st.w r6[AVR32_SMC_MODE0], r9
mov r9, lo(0x000c000d)
orh r9, hi(0x000c000d)
st.w r6[AVR32_SMC_CYCLE0], r9
mov r9, lo(0x0b0a0906)
orh r9, hi(0x0b0a0906)
st.w r6[AVR32_SMC_PULSE0], r9
mov r9, lo(0x00010002)
orh r9, hi(0x00010002)
st.w r6[AVR32_SMC_SETUP0], r9
setup_pll_and_lock:
/* Setup PLL to run at 8 x 20 MHz crystal */
mov r6, lo(AVR32_PM_ADDRESS)
orh r6, hi(AVR32_PM_ADDRESS)
mov r9, lo((16 << AVR32_PM_PLLCOUNT_OFFSET) \
| (PLL_MUL << AVR32_PM_PLLMUL_OFFSET) \
| (PLL_DIV << AVR32_PM_PLLDIV_OFFSET) \
| (0x4 << AVR32_PM_PLLOPT_OFFSET) \
| AVR32_PM_PLLEN_MASK)
orh r9, hi((16 << AVR32_PM_PLLCOUNT_OFFSET) \
| (PLL_MUL << AVR32_PM_PLLMUL_OFFSET) \
| (PLL_DIV << AVR32_PM_PLLDIV_OFFSET) \
| (0x4 << AVR32_PM_PLLOPT_OFFSET) \
| AVR32_PM_PLLEN_MASK)
st.w r6[AVR32_PM_PLL0], r9
mov r10, AVR32_PM_LOCK0_MASK
wait_pll_lock:
ld.w r9, r6[AVR32_PM_ISR]
bld r9, AVR32_PM_LOCK0
brne wait_pll_lock
setup_cpu_hsb_pbx_dividers:
/* Bus speeds: CPU HSB/2 PBA/4 PBB/2 */
mov r9, lo(AVR32_PM_PBBDIV_MASK \
| AVR32_PM_PBADIV_MASK \
| (1 << AVR32_PM_PBASEL_OFFSET) \
| AVR32_PM_HSBDIV_MASK)
orh r9, hi(AVR32_PM_PBBDIV_MASK \
| AVR32_PM_PBADIV_MASK \
| (1 << AVR32_PM_PBASEL_OFFSET) \
| AVR32_PM_HSBDIV_MASK)
st.w r6[AVR32_PM_CKSEL], r9
switch_to_pll0:
mov r9, AVR32_PM_PLLSEL_MASK
st.w r6[AVR32_PM_MCCTRL], r9
setup_evba:
mov r9, lo(_evba)
orh r9, hi(_evba)
mtsr AVR32_EVBA, r9
setup_intc_int0:
/* Setup autovector for interrupt 0 at level 0 */
mov r6, lo(AVR32_INTC_ADDRESS)
orh r6, hi(AVR32_INTC_ADDRESS)
mov r9, int0_handler - _evba
st.w r6[AVR32_INTC_IPR * 0], r9
setup_gpio_leds:
/* Setup GPIO to control LEDs on PA16 (SYS) and PA19 (A) */
mov r9, 0xff
mov r6, lo(AVR32_PIOB_ADDRESS)
orh r6, hi(AVR32_PIOB_ADDRESS)
st.w r6[AVR32_PIO_PER], r9
st.w r6[AVR32_PIO_OER], r9
st.w r6[AVR32_PIO_OWER], r9
mov r9, 1
st.w r6[AVR32_PIO_ODSR], r9
/* Set COUNT-COMPARE on fire and enable global interrupts */
set_count_compare:
mov r11, 0
mov r12, lo(COUNT_INCREASE)
orh r12, hi(COUNT_INCREASE)
mtsr AVR32_COUNT, r11
add r11, r12
mtsr AVR32_COMPARE, r11
enable_interrupts:
csrf AVR32_SR_GM_OFFSET
#if 0 /* enable to turn off branch folding */
mfsr r0, 12
cbr r0, 2
mtsr 12, r0
#endif
/* Algorithm triggering branch folding issue */
branch_folding_issue_algorithm:
lda.w r0, random
lda.w r4, ref
mov r1, 0
mov r5, 0
rjmp 2f
4: mul r8, r1, r2
sub r2, 1
3: ld.sh r7, r4[r1<<1]
cp.w r2, r7
brne 6f
sub r5, -1
5: sub r1, -1
bfextu r1, r1, 0, 5
2: ld.sh r2, r0[r1<<1]
cp.w r2, 0
/* XXX: changed from mul to div to get more cycles to get an interrupt */
divs r8, r1, r2
/* XXX: this one happens to fail, probably due to context switching
* and branch folding */
brle 4b
sub r2, -1
rjmp 3b
6: sub r8, r2, r7
/* r1 = index
* r7 = expected result
* r2 = actual result
* r8 = error
* r5 = iterations since last error
*/
/* Halt algorithm and toggle LED A, read the registers */
toggle_led:
ssrf AVR32_SR_GM_OFFSET
ld.w r9, r6[AVR32_PIO_ODSR]
sub r9, -1
st.w r6[AVR32_PIO_ODSR], r9
mov r10, 0xffff
orh r10, 2
delay_loop:
sub r10, 1
brne delay_loop
#if LOOP_ALGO == 0
rjmp toggle_led
#else
/* Optional reset r5 and jump back to algorithm */
mov r5, 0
csrf AVR32_SR_GM_OFFSET
rjmp 5b
#endif
.endfunc
.align(2)
.type random, %object
random: .short 0x803b, 0x15ae, 0x8f2f, 0x2ddf, 0x2226, 0xb7f1, 0x74dc, 0xe3f6
.short 0x3ce2, 0xa894, 0x322a, 0x221d, 0x8329, 0x8fb3, 0xd73e, 0x927a
.short 0x68b0, 0xff8b, 0x483c, 0xac79, 0x4f93, 0xa498, 0x6ba7, 0xdf04
.short 0x0803, 0xda61, 0xa954, 0xcd49, 0xe059, 0x01f8, 0xae51, 0xff68
.size random, . - random
.type ref, %object
ref: .short 0x803a, 0x15af, 0x8f2e, 0x2de0, 0x2227, 0xb7f0, 0x74dd, 0xe3f5
.short 0x3ce3, 0xa893, 0x322b, 0x221e, 0x8328, 0x8fb2, 0xd73d, 0x9279
.short 0x68b1, 0xff8a, 0x483d, 0xac78, 0x4f94, 0xa497, 0x6ba8, 0xdf03
.short 0x0804, 0xda60, 0xa953, 0xcd48, 0xe058, 0x01f9, 0xae50, 0xff67
.size ref, . - ref