All pastes #1534871 Raw Edit

Stuff

public text v1 · immutable
#1534871 ·published 2009-08-19 10:05 UTC
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