/* * Print contents of Maverick Crunch FPU Status/Control register * as used in Cirrus Logic EP93xx chips. * * You can also use this to tickle two different 64-bit load/store Maverick * hardware bugs. Hack the read/write functions at the end of the file. * See http://www.cirrus.com/en/products/pro/detail/P131.html for HW bug list. * * Output should be: * the initial contents of the DSPSC register with 0xdeadb0d1 in the INST field, * then ten numbers ending in infinities (or saturating, depending on SAT) * then the DSPSC register contents again with FCC=2 IX=1 and OF=1. * * cc -mcpu=ep9312 -mfpu=maverick and -mfloat-abi=softfp if using EABI. * * Martin Guy 5 Oct 2007 - 22 Mar 2009 */ #include #include #include /* 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; static void read_dspsc(void); static void write_dspsc(void); static void print_dspsc(void); main(int argc, char **argv) { if(sizeof(struct DSPSC) != sizeof(double)) { fputs("Error: struct DSPSC compiles with wrong size", stderr); exit(1); } /* Fill top 32 bits with garbage to check they are written correctly */ dspsc.INST=0xdeadb0d1; read_dspsc(); print_dspsc(); printf("%sperating in serialized mode.\n", ((dspsc.IXE || dspsc.UFE || dspsc.OFE || dspsc.IOE) && !dspsc.AEXC) ? "O" : "Not o"); exit(0); } /* 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 put the ldr after the cfmv32sc, you can * trigger an undocumented Maverick hardware bug, whereby * ldr rN, foo; cfstr64 mvdX, [rN] corrupts memory at random. * (Tested on Rev E1 hardware). */ asm("ldr r3, =dspsc"); /* Get address of dspsc */ asm("cfmv32sc mvdx0, dspsc"); /* Get DSPSC contents */ asm("cfstr64 mvdx0, [r3]"); /* Store dspcc contents in dspsc */ } /* Copy our structure's contents into the register */ static void write_dspsc() { asm("ldr r0, =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. * (Erratum 3, tested on Rev E1 hardware) */ // asm("mov r0, r0"); asm("cfldr64 mvdx0, [r0]"); /* Read our variable into c0 */ asm("cfmvsc32 dspsc, mvdx0"); /* Write to dspcc */ }