Commit 027eaf81 authored by Jeffrey Lee's avatar Jeffrey Lee

Add a new, machine-generated VFP/NEON disassembler. Fix some ARMv6/v7 disassembly bugs.

Detail:
  This change adds up-to-date VFP & NEON disassembly to the module, by way of a partially machine-generated disassembler written in C.
  It's also possible to build a standalone disassembler utility (dubbed 'dis2') which is 100% C and has support for all ARM instructions (including some obscure stuff the assembler disassembler currently lacks, e.g. XScale DSP instructions). One day this may completely replace the assembler disassembler, but at the moment it's a bit bulky and probably has a few bugs left to squash. The disassembler is also fairly flexible, supporting various output formatting options.

  Main changes:
  - Makefile - Rewritten to switch over to using the CModule makefile fragment instead of AAsmModule, to allow the C code to be included in the component. Also added 'dis2' as an alternative component to build as.
  - Resources/UK/Messages, Resources/Germany/Messages - Updated with new disassembler messages
  - s/Debugger - Add new UseCVFPNEON switch to allow control over whether the module builds with the C VFP/NEON disassembler or the original assembler VFP disassembler
  - s/CGlue - Glue code used with the C disassembler to bridge the gap between the assembler world and the C world
  - actions/* - A set of decgen action files describing what to do for each instruction the new disassembler supports. These are basically just blocks of C code - although they need to match up with the encoding names in Library/Misc/decgen/encodings
  - cache/* - Folder for decgen to cache decision trees in. Building the decision tree for the disassembler is currently a lengthy process, but caching the trees reduces the build time to a fraction of the full time.
  - c/head - Stub C file that decgen prepends to the code it generates
  - c/main - main frontend for the standalone version of the disassembler
  - c/support - Reimplementation of the standard C library functions required for the disassembler. This allows us to avoid a runtime dependency on the shared C library, and also allows us to deal with control-terminated strings from messagetrans where relevant. For convenience this file also has the main entry point that's called from assembler.
  - c/util - Utility code for outputting various forms of instruction, decoding immediate constants, etc.
  - h/dis2 - Header file for the C code
  - Test/c/testbed - Simple C testbed app to allow the output of dis2 to be compared against the Debugger module and decaof
  - !MkDis2,fd7 - Script to allow easy building of the standalone 'dis2' disassembler
  Bugfixes:
  - s/ARMv6 - Change 'ROR#' to 'ROR #' for UXTAB, etc. disassembly. Fix bitfield extract & clear instructions to detect unpredictable/invalid bitfield definitions
  Misc other changes:
  - s/* - Source files updated so s/Debugger contains a list of GETs instead of each source file LNK'ing to the next
Admin:
  Tested in ROM form on BB-xM, and as softload on Iyonix
  German messages are in need of translation
  Requires Library-1_65 and BuildSys-6_34


Version 1.85. Tagged as 'Debugger-1_85'
parent b364ec48
| Copyright 2013 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine COMPONENT=dis2
hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
*,ffb gitlab-language=bbcbasic linguist-language=bbcbasic linguist-detectable=true
c/** gitlab-language=c linguist-language=c linguist-detectable=true
**/c/** gitlab-language=c linguist-language=c linguist-detectable=true
h/** gitlab-language=c linguist-language=c linguist-detectable=true
......@@ -22,13 +22,112 @@
# 10-May-01 KJB Nicked
#
COMPONENT = Debugger
# Use COMPONENT=Debugger (or leave unset) to build the Debugger module
# Use COMPONENT=dis2 to build a full, standalone version of the C-based disassembler
COMPONENT ?= Debugger
ifeq ("${COMPONENT}","Debugger")
HELPSRC = HelpSrc
TOKENSOURCE = TokHelpSrc
TOKHELPSRC = ${TOKENSOURCE}
HEADER1 = Debugger
ASMHDRS = Debugger
OBJS = Debugger util dis2_vfp support
HDRS =
CMHGFILE =
# dis2 build options
ARM = FALSE
THUMB = FALSE
MODULE = TRUE
endif
ifeq ("${COMPONENT}","dis2")
OBJS = util dis2_arm main
# dis2 build options
ARM = TRUE
THUMB = FALSE
MODULE = FALSE
endif
ifeq (${ARM},TRUE)
CDEFINES += -DDISASSEMBLE_ARM
endif
ifeq (${THUMB},TRUE)
CDEFINES += -DDISASSEMBLE_THUMB
endif
ifeq (${MODULE},TRUE)
CDEFINES += -DMODULE
RAMASMDEFINES += -PD "standalone SETL {TRUE}" -PD "MergedMsgs SETS \"${MERGEDMSGS}\""
endif
ifeq ("${COMPONENT}","Debugger")
include CModule
# We don't want to link to CLib
CLIB =
ROMCSTUBS =
ABSSYM =
CFLAGS += -apcs /nofp
else
include CApp
endif
ACTIONS_ARM = actions/common \
actions/ARMv7 \
actions/ARMv7_ASIMD \
actions/ARMv7_VFP \
actions/FPA \
actions/XScale_DSP
ACTIONS_VFP = actions/common \
actions/ARMv7_ASIMD \
actions/ARMv7_VFP
ENCODINGS = Build:decgen.encodings.ARMv7 \
Build:decgen.encodings.ARMv7_ASIMD \
Build:decgen.encodings.ARMv7_VFP \
Build:decgen.encodings.FPA \
Build:decgen.encodings.XScale_DSP
DECGEN = <Tools$Dir>.Misc.decgen.decgen
# dis2 build rules
dis2_arm.c: $(ACTIONS_ARM) head.c $(ENCODINGS)
$(DECGEN) -bits=32 -e "-DCDP={ne(coproc,1)}" "-DLDC_STC={ne(coproc,1)}{ne(coproc,2)}" "-DMRC_MCR={ne(coproc,1)}" -DVFP1=(cond:4) "-DVFP2={ne(cond,15)}" -DAS1(X)=1111001[X] -DAS2=11110100 -DAS3=(cond:4)1110 "-DAS4={ne(cond,15)}" "-DCC={ne(cond,15)}" $(ENCODINGS) -valid -a $(ACTIONS_ARM) -pre head.c -o dis2_arm.c -prefix=dis2_ -name=dis2 -void -maxmaskbits=3 -opt-strings -treewalker -useargstruct -updatecache cache/arm
dis2_arm.o: dis2_arm.c
${CC} ${CFLAGS} -o $@ dis2_arm.c
dis2_arm.oz: dis2_arm.c
${CC} ${CFLAGS} ${C_MODULE} -o $@ dis2_arm.c
dis2_vfp.c: $(ACTIONS_VFP) head.c $(ENCODINGS)
$(DECGEN) -bits=32 -e "-DCDP={ne(coproc,1)}" "-DLDC_STC={ne(coproc,1)}{ne(coproc,2)}" "-DMRC_MCR={ne(coproc,1)}" -DVFP1=(cond:4) "-DVFP2={ne(cond,15)}" -DAS1(X)=1111001[X] -DAS2=11110100 -DAS3=(cond:4)1110 "-DAS4={ne(cond,15)}" "-DCC={ne(cond,15)}" $(ENCODINGS) -valid -a $(ACTIONS_VFP) -pre head.c -o dis2_vfp.c -prefix=dis2_ -name=dis2 -default=UNDEFINED -void -maxmaskbits=3 -opt-strings -treewalker -useargstruct -updatecache cache/vfp
dis2_vfp.o: dis2_vfp.c
${CC} ${CFLAGS} -o $@ dis2_vfp.c
dis2_vfp.oz: dis2_vfp.c
${CC} ${CFLAGS} ${C_MODULE} -o $@ dis2_vfp.c
clean::
${RM} c.dis2_vfp
${RM} c.dis2_arm
${RM} ${TOKENSOURCE}
# Stuff from AAsmModule that's missing from CModule
TOKENS ?= Hdr:Tokens
${TOKENSOURCE}: ${HELPSRC} ${TOKENS}
${TOKENISE} ${TOKENS} ${HELPSRC} $@
include StdTools
include AAsmModule
Debugger.s: ${TOKENSOURCE}
# Dynamic dependencies:
......@@ -29,12 +29,29 @@ M64:*** Rn in list
M66:*** Rd=Rm
M67:*** Only 1 reg on SA-1 rev 2
M49:*** Odd base of pair
M80:*** Deprecated SUBS PC,LR-like instruction
M81:*** Non-standard encoding of PC-relative address offset
M82:*** Unrecognised DMB/DSB/ISB option
M83:*** Deprecated use of SP
M84:*** Deprecated use of both LR & PC in LDM/POP
M85:*** Deprecated use of PC
M86:*** Deprecated instruction
M87:*** Bad VFP/NEON special register
M68:ARMv5 or later
M69:ARMv5TE or later
M70:ARMv6 or later
M71:ARMv6K or later
M72:ARMv6T2 or later
M73:ARMv7 or later
M74:VFP
M77:VFPv3 or later
M78:VFPv3 half-precision
M79:VFPv4 or later
M90:ASIMD
M91:ASIMD half-precision
M92:ASIMD FP
M93:ASIMDv2 FP
M94:VFP or ASIMD required
M16:Store initialised to &
M17:Register dump (stored at &
M18:) is:
......
/* Copyright 2013 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include "kernel.h"
#include "swis.h"
/* Standalone testbed app for comparing standalone dis2 builds against the
Debugger module and decaof */
#define DEBUGGER
//#define DECAOF
#define MYDIFF
#ifndef MYDIFF
void postprocess(char *folder,char *in,char *out)
{
char buf[4096];
sprintf(buf,"%s.%s",folder,in);
FILE *fin = fopen(buf,"r");
sprintf(buf,"%s.%s",folder,out);
FILE *fout = fopen(buf,"w");
setvbuf(fin,NULL,_IOFBF,65536);
setvbuf(fout,NULL,_IOFBF,65536);
while(!feof(fin) && fgets(buf,4096,fin))
{
char *c = strchr(buf,';');
if(c)
{
while(c[-1] == ' ')
c--;
*c++ = '\n';
*c = 0;
}
if(buf[0] == '\r')
fputs(buf+1,fout);
else
fputs(buf,fout);
}
fclose(fin);
fclose(fout);
}
#endif
int xstrnicmp(const char *a,const char *b,size_t l)
{
while(l--)
{
int c1 = *a++;
int c2 = *b++;
if(tolower(c1) != tolower(c2))
return 1;
}
return 0;
}
#ifdef MYDIFF
#ifdef DECAOF
#define S_WHITESPACE 0
#define S_ID 1
#define S_HASH 2
#define S_NUM 3
#define S_HEX 4
#define S_TERMINATED 5
int diff_decaof(char *folder,char *one,char *two,char *out)
{
char buf1[4096],buf2[4096];
FILE *fin1,*fin2;
FILE *fout;
sprintf(buf1,"%s.%s",folder,one);
fin1 = fopen(buf1,"r");
sprintf(buf1,"%s.%s",folder,two);
fin2 = fopen(buf1,"r");
sprintf(buf1,"%s.%s",folder,out);
fout = fopen(buf1,"w");
setvbuf(fin1,NULL,_IOFBF,65536);
setvbuf(fin2,NULL,_IOFBF,65536);
setvbuf(fout,NULL,_IOFBF,65536);
char *b1,*b2;
int ret=0;
while(!feof(fin1) && fgets(buf1,4096,fin1))
{
/* Fix newlines */
b1 = buf1;
if(b1[0] == '\r')
b1++;
int len1 = strlen(b1);
if(len1 && (b1[len1-1] == '\n'))
b1[--len1] = 0;
if(feof(fin2) || !fgets(buf2,4096,fin2))
{
if(len1)
{
fprintf(fout,"-> %s.%s longer\n",folder,one);
ret = 1;
}
break;
}
/* Fix newlines */
b2 = buf2;
if(b2[0] == '\r')
b2++;
int len2 = strlen(b2);
if(len2 && (b2[len2-1] == '\n'))
b2[--len2] = 0;
/* Compare LHS */
if(strncmp(b1,b2,29))
{
fprintf(fout,"LHS mismatch!\n%s\n%s\n",b1,b2);
ret = 1;
continue;
}
else if((len1 <= 29) || (len2 <= 29))
{
fprintf(fout,"No RHS!\n%s\n%s\n",b1,b2);
ret = 1;
continue;
}
char *c1 = b1+29;
char *c2 = b2+29;
/* Skip any that decgen thinks are nonstandard */
if(strstr(c2,"Nonstandard encoding"))
continue;
/* Compare RHS */
int s1 = -1;
int s2 = -1;
while(s1 != S_TERMINATED)
{
unsigned long long n1=0,n2=0;
while((*c1 == ' ') || (*c1 == '#'))
c1++;
if(!strncmp(c1,"foo+",4))
c1 += 4;
if((*c1 == 0) || (*c1 == ';'))
s1 = S_TERMINATED;
else if((*c1 == '0') && (c1[1] == 'x'))
{
s1 = S_NUM;
c1 += 2;
int hc;
do {
hc = *c1++;
if((hc >= '0') && (hc <= '9'))
n1 = (n1<<4) | (hc-'0');
else if((hc >= 'a') && (hc <= 'f'))
n1 = (n1<<4) | (hc-'a'+10);
else if((hc >= 'A') && (hc <= 'F'))
n1 = (n1<<4) | (hc-'A'+10);
else
{
c1--;
hc=-1;
}
} while(hc >= 0);
}
else if((*c1 >= '0') && (*c1 <= '9'))
{
s1 = S_NUM;
int hc;
do {
hc = *c1++;
if((hc >= '0') && (hc <= '9'))
n1 = (n1*10)+(hc-'0');
else
{
c1--;
hc=-1;
}
} while(hc >= 0);
}
else
{
s1 = S_ID;
if(isalnum(*c1))
{
do {
n1++;
} while(isalnum(c1[n1]));
}
else
n1 = 1;
}
while((*c2 == ' ') || (*c2 == '#'))
c2++;
if((*c2 == 0) || (*c2 == ';'))
s2 = S_TERMINATED;
else if((*c2 == '0') && (c2[1] == 'x'))
{
s2 = S_NUM;
c2 += 2;
int hc;
do {
hc = *c2++;
if((hc >= '0') && (hc <= '9'))
n2 = (n2<<4) | (hc-'0');
else if((hc >= 'a') && (hc <= 'f'))
n2 = (n2<<4) | (hc-'a'+10);
else if((hc >= 'A') && (hc <= 'F'))
n2 = (n2<<4) | (hc-'A'+10);
else
{
c2--;
hc=-1;
}
} while(hc >= 0);
}
else if((*c2 >= '0') && (*c2 <= '9'))
{
s2 = S_NUM;
int hc;
do {
hc = *c2++;
if((hc >= '0') && (hc <= '9'))
n2 = (n2*10)+(hc-'0');
else
{
c2--;
hc=-1;
}
} while(hc >= 0);
}
else
{
s2 = S_ID;
if(isalnum(*c2))
{
do {
n2++;
} while(isalnum(c2[n2]));
}
else
{
/* Skip optional ",#0" in load/store */
if((s1 == S_ID) && (*c1 == ']') && !strncmp(c2,",#0]",4))
c2 += 3;
n2 = 1;
}
}
if(s1 != s2)
{
fprintf(fout,"Formatting mismatch:\n%s\n%s\n",b1,b2);
ret = 1;
break;
}
else if((s1 == S_NUM) && (n1 != n2))
{
fprintf(fout,"Number mismatch:\n%s\n%s\n",b1,b2);
ret = 1;
break;
}
else if(s1 == S_ID)
{
if((n1 != n2) || xstrnicmp(c1,c2,(size_t) n1))
{
fprintf(fout,"ID mismatch:\n%s\n%s\n",b1,b2);
ret = 1;
break;
}
c1 += n1;
c2 += n2;
}
}
}
if(!feof(fin2) && fgets(b2,4096,fin2))
{
fprintf(fout,"-> %s.%s longer\n",folder,two);
ret = 1;
}
fclose(fin1);
fclose(fin2);
fclose(fout);
return ret;
}
#endif
#ifdef DEBUGGER
int diff_debugger(char *folder,char *one,char *two,char *out)
{
char buf1[4096],buf2[4096];
FILE *fin1,*fin2,*fout;
sprintf(buf1,"%s.%s",folder,one);
fin1 = fopen(buf1,"r");
sprintf(buf1,"%s.%s",folder,two);
fin2 = fopen(buf1,"r");
sprintf(buf1,"%s.%s",folder,out);
fout = fopen(buf1,"w");
setvbuf(fin1,NULL,_IOFBF,65536);
setvbuf(fin2,NULL,_IOFBF,65536);
setvbuf(fout,NULL,_IOFBF,65536);
char *b1,*b2;
int ret = 0;
while(!feof(fin1) && fgets(buf1,4096,fin1))
{
/* Fix newlines */
b1 = buf1;
if(b1[0] == '\r')
b1++;
int len1 = strlen(b1);
if(len1 && (b1[len1-1] == '\n'))
b1[--len1] = 0;
if(feof(fin2) || !fgets(buf2,4096,fin2))
{
if(len1)
{
fprintf(fout,"-> %s.%s longer\n",folder,one);
ret = 1;
}
break;
}
/* Fix newlines */
b2 = buf2;
if(b2[0] == '\r')
b2++;
int len2 = strlen(b2);
if(len2 && (b2[len2-1] == '\n'))
b2[--len2] = 0;
/* Compare LHS */
if(strncmp(b1,b2,29))
{
fprintf(fout,"LHS mismatch!\n%s\n%s\n",b1,b2);
ret = 1;
continue;
}
else if((len1 <= 29) || (len2 <= 29))
{
fprintf(fout,"No RHS!\n%s\n%s\n",b1,b2);
ret = 1;
continue;
}
char *c1 = b1+29;
char *c2 = b2+29;
/* Skip any that decgen thinks are nonstandard */
if(strstr(c2,"Nonstandard"))
continue;
#if 0
/* Skip any that debugger thinks are undefined */
if(!strcmp(c1,"Undefined instruction"))
continue;
#else
/* Skip any that decgen thinks are unpredictable */
if(strstr(c2,"Unpredictable"))
continue;
if(strstr(c2,"Unallocated"))
continue;
/* Skip LDC/STC/etc. - might be caused by VFP/NEON handling differences */
if(strstr(c2,"MAR") || strstr(c2,"MRA"))
continue;
if((strstr(c1,"LDC") || strstr(c1,"STC") || strstr(c1,"MCR") || strstr(c1,"MRC") || strstr(c1,"MRRC") || strstr(c1,"CDP")) && strstr(c2,"Undefined"))
continue;
if((strstr(c2,"LDC") || strstr(c2,"STC") || strstr(c2,"MCR") || strstr(c2,"MRC") || strstr(c2,"MRRC") || strstr(c2,"CDP")) && strstr(c1,"Undefined"))
continue;
#endif
/* Compare */
int l = 56;
if(l > len1)
l = len1;
if(l > len2)
l = len2;
if(!strncmp(c1,c2,l-29))
continue;
/* Ignore nonstandard immediate constants */
if(strchr(c2,'#') && (sscanf(strchr(c2,'#'),"#%d,%d",&len1,&len2) == 2))
continue;
/* Ignore [PC,#xxx] */
if(strchr(c2,'[') && (sscanf(strchr(c2,'['),"[PC,#%d]",&len1) == 1))
continue;
/* Ignore optional # in ARMv6/v7 Debugger output */
if(strchr(c2,'#') && !strchr(c1,'#') && isdigit(strchr(c2,'#')[1]))
continue;
fprintf(fout,"Disassembly mismatch!\n%s\n%s\n",b1,b2);
ret = 1;
}
if(!feof(fin2) && fgets(b2,4096,fin2))
{
fprintf(fout,"-> %s.%s longer\n",folder,two);
ret = 1;
}
fclose(fin1);
fclose(fin2);
fclose(fout);
return ret;
}
#endif
#endif
unsigned int *generate(unsigned int start,unsigned int count,char *rawfile)
{
static unsigned int *s_raw = NULL;
printf("Generating data for %08x-%08x\n",start,start+count-1);
if(!s_raw)
s_raw = (unsigned int *) malloc(4*count);
unsigned int *raw = s_raw;
for(unsigned int i=0;i<count;i++)
{
raw[i] = start+i;
}
_swix(OS_File,_INR(0,5),10,rawfile,0xffd,0,raw,raw+count);
return raw;
}
void process(char *rawfile,char *folder,unsigned int *raw,unsigned int count)
{
char buf[1024];
int ret = 0;
#ifdef DECAOF
sprintf(buf,"binaof %s %s.aof foo foo -C",rawfile,folder);
if(system(buf))
{
fprintf(stderr,"binaof failed!\n");
exit(EXIT_FAILURE);
}
#endif
printf("Disassembling\n");
#ifdef DEBUGGER
sprintf(buf,"dis2 %s 0x%08x -debugger > %s.dis2_debugger",rawfile,(unsigned int) raw,folder);
if(system(buf))
{
fprintf(stderr,"dis2 failed!\n");
exit(EXIT_FAILURE);
}
sprintf(buf,"memoryi %08x + %08x { > %s.debugger }",(unsigned int) raw,count*4,folder);
if(system(buf))
{
fprintf(stderr,"memoryi failed!\n");
exit(EXIT_FAILURE);
}
sprintf(buf,"settype %s.debugger fff",folder);
system(buf);
#endif
#ifdef DECAOF
sprintf(buf,"dis2 %s 0 -decaof > %s.dis2_decaof",rawfile,folder);
if(system(buf))
{
fprintf(stderr,"dis2 failed!\n");
exit(EXIT_FAILURE);
}
sprintf(buf,"dis2 %s 0 -decaofual > %s.dis2_decaofual",rawfile,folder);
if(system(buf))
{
fprintf(stderr,"dis2 failed!\n");
exit(EXIT_FAILURE);
}
sprintf(buf,"decaof -c %s.aof > %s.decaof",folder,folder);
if(system(buf))
{
fprintf(stderr,"decaof failed!\n");
exit(EXIT_FAILURE);
}
sprintf(buf,"decaof -uc %s.aof > %s.decaofual",folder,folder);
if(system(buf))
{
fprintf(stderr,"decaof failed!\n");
exit(EXIT_FAILURE);
}
#endif
printf("Postprocessing\n");
#ifdef DECAOF
sprintf(buf,"grep \" 0x\" %s/decaof > %s/decaof2",folder,folder);
system(buf);
sprintf(buf,"grep \" 0x\" %s/decaofual > %s/decaofual2",folder,folder);
system(buf);
#endif
#ifndef MYDIFF
#ifdef DEBUGGER
postprocess(folder,"debugger","debugger2");
postprocess(folder,"dis2_debugger","dis2_debugger2");
#endif
#ifdef DECAOF
postprocess(folder,"dis2_decaof","dis2_decaof2");
postprocess(folder,"dis2_decaofual","dis2_decaofual2");
postprocess(folder,"decaof2","decaof3");
postprocess(folder,"decaofual2","decaofual3");
#endif
#endif
printf("Diffing\n");
#ifdef DEBUGGER
#ifdef MYDIFF
ret |= diff_debugger(folder,"debugger","dis2_debugger","diff_debugger");
#else
sprintf(buf,"gnudiff -u %s/debugger2 %s/dis2_debugger2 > %s/diff_debugger",folder,folder,folder);
system(buf);
#endif
#endif
#ifdef DECAOF
#ifdef MYDIFF
ret |= diff_decaof(folder,"decaof2","dis2_decaof","diff_decaof");
ret |= diff_decaof(folder,"decaofual2","dis2_decaofual","diff_decaofual");
#else
sprintf(buf,"gnudiff -ui %s/decaof3 %s/dis2_decaof2 > %s/diff_decaof",folder,folder,folder);
system(buf);
sprintf(buf,"gnudiff -ui %s/decaofual3 %s/dis2_decaofual2 > %s/diff_decaofual",folder,folder,folder);
system(buf);
#endif
#endif
if(ret)
{
printf("Differences detected!\n");
exit(257);
}
}
int main(int argc,char **argv)
{
if((argc < 3) || (argc > 5))
{
fprintf(stderr,"usage: testbed <folder> <start> <count>\n");
fprintf(stderr,"or: testbed <folder> <start> <count> <repeat>\n");
fprintf(stderr,"or: testbed <folder> <file>\n");
exit(EXIT_FAILURE);
}
char *folder = argv[1];
unsigned int count,*raw,repeat;
if(argc == 3)
{
char *rawfile = argv[2];
FILE *f = fopen(rawfile,"rb");
if(!f)
{
fprintf(stderr,"Couldn't open '%s'\n",rawfile);
exit(EXIT_FAILURE);
}
printf("Loading file\n");
fseek(f,0,SEEK_END);
count = (unsigned int) (ftell(f)>>2);
raw = (unsigned int *) malloc(4*count);