/* * Probe timing-dependent bugs in Maverick FPU * as used in Cirrus Logic EP93xx chips. * * cc -mcpu=ep9312 -mfpu=maverick and -mfloat-abi=softfp if using EABI. * * Martin Guy 5 Oct 2007 - 1 Apr 2008 */ #include #include unsigned long i32; main() { i32 = 21; erratum2_condexec(); printf("Erratum 2 with condexec: %s\n", i32==42 ? "ok" : "buggy"); i32 = 21; erratum2_branch(); printf("Erratum 2 with branch: %s\n", i32==42 ? "ok" : "buggy"); exit(0); } erratum2_condexec() { /* FP instruction with same target not executed due to false condition: * following instruction with register as source gets old value unless * three extra nops are inserted between the first and last insns * There are only two here - the bug still occurs. */ asm("ldr r3, =i32"); /* r3 = &i32 */ asm("cmp r3, r3"); /* set eq condition */ asm("cfldr32 mvfx0, [r3]"); /* c0 = i32 */ asm("cfadd32 MVFX0,mvfx0,mvfx0"); /* double it */ asm("nop"); asm("cfadd32ne MVFX0,mvfx0,mvfx0"); /* not exec with same target */ asm("nop"); asm("cfstr32 MVFX0, [r3]"); /* stores value in i32 */ } erratum2_branch() { /* FP instruction with same target not executed due to branch taken: * the following instruction with that as source register gets old value * unless * - one nop after branch instruction, or * - one nop after foo: * The errata say that it should also fail if it is in the second slot * after the branch, but that appears not to be true on E2 silicon. */ asm(" ldr r3, =i32"); /* r3 = &i32 */ asm(" cfldr32 mvfx0, [r3]"); /* mvd0 = i32 */ asm(" cfadd32 MVFX0,mvfx0,mvfx0"); /* double it */ asm(" b foo"); asm(" cfadd32 MVFX0,mvfx0,mvfx0"); /* FP insn with same target */ asm("foo:"); asm(" cfstr32 MVFX0, [r3]"); /* stores value in i32 */ }