/* * Enable forwarding in Maverick Crunch * * cc -mcpu=ep9312 -mfpu=maverick and -mfloat-abi=softfp if using EABI. * * Martin Guy 5 Oct 2007 - 1 Apr 2008 */ #include #include static void read_dspsc(void); static void write_dspsc(void); static void print_dspsc(void); /* Somewhere to examine the teo 32-bit words of a 64-bit value */ union { unsigned long long ll; struct { unsigned long l0, l1; } l; } in, out; /* bug4_*() routines copy ontents of "in" to "out". If we hit the bug, * the most significant word (the dead bodi) should come out as garbage * at certain distances between the data instr and the 64-bit store. */ void crunch_fwden() { register int tmp; double save; register double *savep = &save; asm("cfstr64 mvdx0, [%0]" : : "r" (savep)); asm("cfmv32sc mvdx0, dspsc"); /* Read DSPSC contents */ asm("cfmvrdl %0, mvd0" : "=r"(tmp)); /* Move LSW to ARM */ asm("orr %0, %0, #0x4000" : "=r"(tmp) : "0"(tmp)); /* Set forwarding bit */ asm("cfmvdlr mvd0, %0" : : "r"(tmp));/* Move ARM to LSW */ asm("cfmvsc32 dspsc, mvdx0"); /* Write DSPSC contents */ asm("cfldr64 mvdx0, [%0]" : : "r" (savep)); } main() { read_dspsc(); print_dspsc(); crunch_fwden(); read_dspsc(); print_dspsc(); exit(0); } /* Contents of Maverick Crunch DSPSC register in little-endian mode. * See EP9307 Users Guide, Chapter 2 */ struct DSPSC { #define u unsigned u IO:1; u RSVD1:1; u OF:1; u UF:1; u IX:1; u IOE:1; u RSVD6:1; u OFE:1; u UFE:1; u IXE:1; u RM:2; u Denorm:1; u Invalid:1; u FWDEN:1; u V:1; u FCC:2; u SAT:2; u AEXC:1; u INT:1; u UI:1; u ISAT:1; u RSVD24:2; u HVID:3; u DAID:3; u INST:32; #undef u } dspsc; /* Print the contents of the structure in human-readable form */ static void print_dspsc() { #define d dspsc printf("INST=0x%08x\n", d.INST); printf("DAID=%d HVID=%d ISAT=%d UI=%d INT=%d AEXC=%d SAT=%d\n", d.DAID, d.HVID, d.ISAT, d.UI, d.INT, d.AEXC, d.SAT); printf("FCC=%d V=%d FWDEN=%d Invalid=%d Denorm=%d RM=%d\n", d.FCC, d.V, d.FWDEN, d.Invalid, d.Denorm, d.RM); printf("IXE=%d UFE=%d OFE=%d IOE=%d IX=%d UF=%d OF=%d IO=%d\n", d.IXE, d.UFE, d.OFE, d.IOE, d.IX, d.UF, d.OF, d.IO); #undef d } /* Copy register contents into our structure */ static void read_dspsc() { /* If you tuck the stfmd and/or ldr after the cfmv32sc, you can * trigger timing-dependent Maverick erratum #4 (data operation * into Crunch register followed by 64-bit store of the same Maverick * register into RAM), storing all 0's in the first 32 bits of the * memory (the condition codes) sometimes and sometimes not. * (Tested on Rev E1 hardware). */ asm("stmfd sp!, {r3}"); /* Save r3 */ asm("ldr r3, =dspsc"); /* Get address of dspsc */ asm("cfmv32sc mvdx0, dspsc"); /* Get DSPSC contents */ asm("cfstr64 mvdx0, [r3]"); /* Store dspcc contents in dspsc */ asm("ldmfd sp!, {r3}"); /* Restore r3 */ } /* Copy our structure's contents into the register */ static void write_dspsc() { asm("stmfd sp!, {r3}"); /* Save r3 */ asm("ldr r3, =dspsc"); /* Get address of dspsc */ /* no-op to workaround Maverick timing bug: cfldr64 must not busy-wait. * Without this, rubbish is written into all 64 bits of DSPSC. * (Tested on Rev E1 hardware) */ asm("mov r3, r3"); asm("cfldr64 mvdx1, [r3]"); /* Read dspsc into c0 */ asm("cfmvsc32 dspsc, mvdx1"); /* Write to dspcc */ asm("ldmfd sp!, {r3}"); /* Restore r3 */ }