<html>
<body>
<div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src</tt></b></td></tr>
<tr><td><tt><a href="#file1">Makefile.am</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+3</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">de9ad2c0cf56 -> 700e16c321e5</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">Makefile.in</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+43</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-5</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">de9ad2c0cf56 -> 700e16c321e5</td></tr>
<tr><td><tt>tools/<a href="#file3"><span id="added" style="background-color:#ddffdd;" >genmach.c</span></a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+372</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" align="right" nowrap="nowrap">added 700e16c321e5</td></tr>
<tr class="alt" style=";" ><td><tt> /<a href="#file4"><span id="addedalt" style="background-color:#ccf7cc;" >genmach.h</span></a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+127</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" align="right" nowrap="nowrap">added 700e16c321e5</td></tr>
<tr><td><tt> /<a href="#file5"><span id="added" style="background-color:#ddffdd;" >mdparse.c</span></a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+721</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" align="right" nowrap="nowrap">added 700e16c321e5</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1266</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-6</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >3 added + 2 modified, total 5 files</small><br />
<div class="tasklist" style="padding:4px;border:1px dashed #000000;margin-top:1em;" ><ul>
<li><a href="#task1">FIXME: handle endian mismatches */</a></li>
</ul></div>
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
Commit genmach work-in-progress
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Makefile.am</b></big> <small id="info" style="color: #888888;" >de9ad2c0cf56 -> 700e16c321e5</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/Makefile.am
+++ lxdream/src/Makefile.am
@@ -12,7 +12,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > PLUGINCFLAGS = @PLUGINCFLAGS@
PLUGINLDFLAGS = @PLUGINLDFLAGS@
bin_PROGRAMS = lxdream
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-noinst_PROGRAMS = gendec genglsl
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+noinst_PROGRAMS = gendec genglsl<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > genmach</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > check_PROGRAMS = test/testxlt test/testisoread
pkglib_PROGRAMS=
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -36,6 +36,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #all-am: checkversion
gendec_SOURCES = tools/gendec.c tools/gendec.h tools/insparse.c tools/actparse.c
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach_SOURCES = tools/genmach.c tools/genmach.h tools/mdparse.c
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > genglsl_SOURCES = tools/genglsl.c
lxdream_LINK = $(LINK) @LXDREAMLDFLAGS@
lxdream_LDADD = @LXDREAM_LIBS@ @GLIB_LIBS@ @GTK_LIBS@ @LIBPNG_LIBS@ $(INTLLIBS)
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -236,6 +237,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
gendec_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
genglsl_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
test_testxlt_SOURCES = test/testxlt.c xlat/xltcache.c xlat/xltcache.h
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Makefile.in</b></big> <small id="info" style="color: #888888;" >de9ad2c0cf56 -> 700e16c321e5</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/Makefile.in
+++ lxdream/src/Makefile.in
@@ -37,7 +37,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = lxdream$(EXEEXT)
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-noinst_PROGRAMS = gendec$(EXEEXT) genglsl$(EXEEXT)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+noinst_PROGRAMS = gendec$(EXEEXT) genglsl$(EXEEXT)<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > genmach$(EXEEXT)</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > check_PROGRAMS = test/testxlt$(EXEEXT) test/testisoread$(EXEEXT) \
$(am__EXEEXT_1)
pkglib_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -135,6 +135,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > am_genglsl_OBJECTS = genglsl.$(OBJEXT)
genglsl_OBJECTS = $(am_genglsl_OBJECTS)
genglsl_DEPENDENCIES = $(am__DEPENDENCIES_1)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+am_genmach_OBJECTS = genmach.$(OBJEXT) mdparse.$(OBJEXT)
+genmach_OBJECTS = $(am_genmach_OBJECTS)
+genmach_DEPENDENCIES = $(am__DEPENDENCIES_1)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > am_input_lirc_@SOEXT@_OBJECTS =
input_lirc_@SOEXT@_OBJECTS = $(am_input_lirc_@SOEXT@_OBJECTS)
@BUILD_SHARED_TRUE@@INPUT_LIRC_TRUE@input_lirc_@SOEXT@_DEPENDENCIES = \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -336,16 +339,16 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > $(LDFLAGS) -o $@
SOURCES = $(audio_alsa_@SOEXT@_SOURCES) $(audio_esd_@SOEXT@_SOURCES) \
$(audio_pulse_@SOEXT@_SOURCES) $(audio_sdl_@SOEXT@_SOURCES) \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- $(gendec_SOURCES) $(genglsl_SOURCES) \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ $(gendec_SOURCES) $(genglsl_SOURCES) <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >$(genmach_SOURCES) </span>\
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > $(input_lirc_@SOEXT@_SOURCES) $(lxdream_SOURCES) \
$(lxdream_dummy_@SOEXT@_SOURCES) $(test_testisoread_SOURCES) \
$(test_testsh4x86_SOURCES) $(test_testxlt_SOURCES)
DIST_SOURCES = $(audio_alsa_@SOEXT@_SOURCES) \
$(audio_esd_@SOEXT@_SOURCES) $(audio_pulse_@SOEXT@_SOURCES) \
$(audio_sdl_@SOEXT@_SOURCES) $(gendec_SOURCES) \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- $(genglsl_SOURCES) $(input_lirc_@SOEXT@_SOURCES) \
- $(am__lxdream_SOURCES_DIST) $(lxdream_dummy_@SOEXT@_SOURCES) \
- $(test_testisoread_SOURCES) \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ $(genglsl_SOURCES) $(genmach_SOURCES) \
+ $(input_lirc_@SOEXT@_SOURCES) $(am__lxdream_SOURCES_DIST) \
+ $(lxdream_dummy_@SOEXT@_SOURCES) $(test_testisoread_SOURCES) \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > $(am__test_testsh4x86_SOURCES_DIST) $(test_testxlt_SOURCES)
ETAGS = etags
CTAGS = ctags
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -555,6 +558,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
#all-am: checkversion
gendec_SOURCES = tools/gendec.c tools/gendec.h tools/insparse.c tools/actparse.c
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach_SOURCES = tools/genmach.c tools/genmach.h tools/mdparse.c
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > genglsl_SOURCES = tools/genglsl.c
lxdream_LINK = $(LINK) @LXDREAMLDFLAGS@
lxdream_LDADD = @LXDREAM_LIBS@ @GLIB_LIBS@ @GTK_LIBS@ @LIBPNG_LIBS@ \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -631,6 +635,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @BUILD_SHARED_TRUE@@INPUT_LIRC_TRUE@input_lirc_@SOEXT@_LDFLAGS = $(PLUGINLDFLAGS)
gendec_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
genglsl_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach_LDADD = @GLIB_LIBS@ @GTK_LIBS@ $(INTLLIBS)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > test_testxlt_SOURCES = test/testxlt.c xlat/xltcache.c xlat/xltcache.h
test_testisoread_SOURCES = test/testisoread.c drivers/cdrom/isoread.c \
drivers/cdrom/isoread.h drivers/cdrom/isofs_impl.h drivers/cdrom/ecc.h \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -746,6 +751,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > genglsl$(EXEEXT): $(genglsl_OBJECTS) $(genglsl_DEPENDENCIES)
@rm -f genglsl$(EXEEXT)
$(LINK) $(genglsl_LDFLAGS) $(genglsl_OBJECTS) $(genglsl_LDADD) $(LIBS)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach$(EXEEXT): $(genmach_OBJECTS) $(genmach_DEPENDENCIES)
+ @rm -f genmach$(EXEEXT)
+ $(LINK) $(genmach_LDFLAGS) $(genmach_OBJECTS) $(genmach_LDADD) $(LIBS)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > input_lirc.@SOEXT@$(EXEEXT): $(input_lirc_@SOEXT@_OBJECTS) $(input_lirc_@SOEXT@_DEPENDENCIES)
@rm -f input_lirc.@SOEXT@$(EXEEXT)
$(LINK) $(input_lirc_@SOEXT@_LDFLAGS) $(input_lirc_@SOEXT@_OBJECTS) $(input_lirc_@SOEXT@_LDADD) $(LIBS)
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -783,6 +791,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edc_ecc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gendec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genglsl.Po@am__quote@
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genmach.Po@am__quote@
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/insparse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isoread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-aica.Po@am__quote@
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -905,6 +914,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-x86dasm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-xltcache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-yuv.Po@am__quote@
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdparse.Po@am__quote@
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sector.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testsh4x86-cpu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testsh4x86-dis-buf.Po@am__quote@
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -992,6 +1002,34 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o genglsl.obj `if test -f 'tools/genglsl.c'; then $(CYGPATH_W) 'tools/genglsl.c'; else $(CYGPATH_W) '$(srcdir)/tools/genglsl.c'; fi`
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+genmach.o: tools/genmach.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT genmach.o -MD -MP -MF "$(DEPDIR)/genmach.Tpo" -c -o genmach.o `test -f 'tools/genmach.c' || echo '$(srcdir)/'`tools/genmach.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/genmach.Tpo" "$(DEPDIR)/genmach.Po"; else rm -f "$(DEPDIR)/genmach.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tools/genmach.c' object='genmach.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o genmach.o `test -f 'tools/genmach.c' || echo '$(srcdir)/'`tools/genmach.c
+
+genmach.obj: tools/genmach.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT genmach.obj -MD -MP -MF "$(DEPDIR)/genmach.Tpo" -c -o genmach.obj `if test -f 'tools/genmach.c'; then $(CYGPATH_W) 'tools/genmach.c'; else $(CYGPATH_W) '$(srcdir)/tools/genmach.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/genmach.Tpo" "$(DEPDIR)/genmach.Po"; else rm -f "$(DEPDIR)/genmach.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tools/genmach.c' object='genmach.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o genmach.obj `if test -f 'tools/genmach.c'; then $(CYGPATH_W) 'tools/genmach.c'; else $(CYGPATH_W) '$(srcdir)/tools/genmach.c'; fi`
+
+mdparse.o: tools/mdparse.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdparse.o -MD -MP -MF "$(DEPDIR)/mdparse.Tpo" -c -o mdparse.o `test -f 'tools/mdparse.c' || echo '$(srcdir)/'`tools/mdparse.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mdparse.Tpo" "$(DEPDIR)/mdparse.Po"; else rm -f "$(DEPDIR)/mdparse.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tools/mdparse.c' object='mdparse.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdparse.o `test -f 'tools/mdparse.c' || echo '$(srcdir)/'`tools/mdparse.c
+
+mdparse.obj: tools/mdparse.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdparse.obj -MD -MP -MF "$(DEPDIR)/mdparse.Tpo" -c -o mdparse.obj `if test -f 'tools/mdparse.c'; then $(CYGPATH_W) 'tools/mdparse.c'; else $(CYGPATH_W) '$(srcdir)/tools/mdparse.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mdparse.Tpo" "$(DEPDIR)/mdparse.Po"; else rm -f "$(DEPDIR)/mdparse.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tools/mdparse.c' object='mdparse.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdparse.obj `if test -f 'tools/mdparse.c'; then $(CYGPATH_W) 'tools/mdparse.c'; else $(CYGPATH_W) '$(srcdir)/tools/mdparse.c'; fi`
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > lxdream-main.o: main.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-main.o -MD -MP -MF "$(DEPDIR)/lxdream-main.Tpo" -c -o lxdream-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lxdream-main.Tpo" "$(DEPDIR)/lxdream-main.Po"; else rm -f "$(DEPDIR)/lxdream-main.Tpo"; exit 1; fi
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="added" class="pathname" style="font-family:monospace; float:right; background-color:#ddffdd;" >lxdream/src/tools</span><br />
<div id="added" class="fileheader" style="margin-bottom:.5em; background-color:#ddffdd;" ><big><b>genmach.c</b></big> <small id="info" style="color: #888888;" >added at 700e16c321e5</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/tools/genmach.c
+++ lxdream/src/tools/genmach.c
@@ -0,0 +1,372 @@
</small></pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * $Id$
+ *
+ * mmio register code generator
+ *
+ * Copyright (c) 2010 Nathan Keynes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <errno.h>
+#include <glib/gstrfuncs.h>
+#include <glib/glist.h>
+#include "gettext.h"
+#include "genmach.h"
+
+#define LXDREAM_PAGE_SIZE 4096
+
+const char *short_options = "cd:ho:v";
+struct option long_options[] = {
+ { "output", required_argument, NULL, 'o' },
+ { "header", required_argument, NULL, 'd' },
+ { "check-only", no_argument, NULL, 'c' },
+ { "help", no_argument, NULL, 'h' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL, 0, 0, 0 } };
+
+static void print_version()
+{
+ printf( "genmmio 0.1\n" );
+}
+
+static void print_usage()
+{
+ print_version();
+ printf( "Usage: genmmio [options] <input-register-files>\n" );
+ printf( "Options:\n" );
+ printf( " -c, --check-only %s\n", _("Check specification files but don't write any output") );
+ printf( " -d, --header=FILE %s\n", _("Specify header output file [corresponding .h for .c file]") );
+ printf( " -h, --help %s\n", _("Display this usage information") );
+ printf( " -o, --output=FILE %s\n", _("Specify main output file [corresponding .c for input file]") );
+ printf( " -v, --verbose %s\n", _("Print verbose output") );
+}
+
+/**
+ * Given an input baseName of the form "path/file.blah", return
+ * a newly allocated string "file<ext>" where <ext> is the second
+ * parameter.
+ *
+ * @param baseName a non-null filename
+ * @param ext a file extension including leading '.'
+ */
+char *makeFilename( const char *baseName, const char *ext )
+{
+ const char *p = strrchr(baseName, '/');
+ if( p == NULL )
+ p = baseName;
+ const char *q = strchr(p, '.');
+ if( q == NULL ) {
+ return g_strdup_printf("%s%s", p, ext);
+ } else {
+ return g_strdup_printf("%.*s%s", q-p, p, ext );
+ }
+}
+
+/**
+ * Process all registers after parsing is complete. This does a few things:
+ * 1. Ensures that there are no overlapping registers, so that every operation
+ * is well-defined.
+ * 2. Replaces transitive mirror groups with a set of equivalent direct
+ * mirrors so that later processing doesn't need to check for this case.
+ * This also checks for cycles in the graph.
+ * 3. Organises the memory map(s) into page-size quantities (combining and
+ * splitting groups where necessary).
+ */
+GList *postprocess_registers( GList *blocks )
+{
+ for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
+ regblock_t block = (regblock_t)ptr->data;
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ if( reg->mode == REG_MIRROR ) {
+ }
+ }
+ }
+ return blocks;
+}
+
+/**
+ * Check register definition semantics. Primarily this verifies that there
+ * are no overlapping definitions.
+ * @return number of errors found.
+ */
+int check_registers( GList *registers )
+{
+ return 0;
+}
+
+/**
+ * Dump the high-level register map to the given file.
+ */
+void dump_register_blocks( FILE *f, GList *blocks, gboolean detail )
+{
+ const char *mode_names[] = { "--", "RW", "RO", "RW" };
+ for( GList *ptr = blocks; ptr != NULL; ptr=ptr->next ) {
+ regblock_t block = (regblock_t)ptr->data;
+ fprintf( f, "%08X: %s - %s\n", block->address,
+ block->name,
+ (block->description == NULL ? "<no description>" : block->description) );
+ if( detail ) {
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ fprintf( f, " %04X: %s %s", reg->offset,
+ mode_names[reg->mode],
+ reg->name == NULL ? "<anon>" : reg->name );
+ if( reg->numElements > 1 ) {
+ fprintf( f, "[%d]", reg->numElements );
+ }
+ fprintf( f, " - %s\n",
+ (reg->description == NULL ? "<no description>" : reg->description) );
+ }
+ }
+ }
+}
+
+char *build_page_initializer( regblock_t block )
+{
+ char *page = g_malloc(LXDREAM_PAGE_SIZE);
+
+ /* First, background fill if any */
+ if( block->flags.fillSizeBytes == 0 ) {
+ memset(page, 0, LXDREAM_PAGE_SIZE);
+ } else {
+ for( unsigned i=0; i<LXDREAM_PAGE_SIZE; i++ ) {
+ page[i] = block->flags.fillValue.a[i%block->flags.fillSizeBytes];
+ }
+ }
+
+ /* Next, set register initializer (except for wo + mirror regs) */
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ if( reg->mode != REG_WO && reg->mode != REG_MIRROR ) {
+ unsigned offset = reg->offset;
+ for( unsigned j=0; j<reg->numElements; j++ ) {
+ if( reg->type == REG_STRING ) {
+ memcpy( &page[offset], reg->initValue.s, reg->numBytes );
+ } else {
+ memcpy( &page[offset], reg->initValue.a, reg->numBytes );
+ }
+ offset += reg->numBytes;
+ }
+ }
+ }
+
+ /* Finally clone mirror groups */
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ if( reg->mode == REG_MIRROR ) {
+ unsigned offset = reg->offset;
+ unsigned target = reg->initValue.i;
+ for( unsigned i=0; i<reg->numElements; i++ ) {
+ memcpy( &page[offset], &page[target], reg->numBytes );
+ offset += reg->stride;
+ }
+ }
+ }
+
+ return page;
+}
+
+
+void fwrite_dump( unsigned char *data, unsigned int length, FILE *f )
+{
+ unsigned int i, j;
+ int skipped = 0;
+ for( i =0; i<length; i+=16 ) {
+ if( i >= 16 && i < length-16 && memcmp( &data[i], &data[i-16], 16) == 0 ) {
+ skipped++;
+ continue;
+ }
+ if( skipped ) {
+ fprintf( f, " ** \n" );
+ skipped = 0;
+ }
+ fprintf( f, "%08X:", i);
+ for( j=i; j<i+16; j++ ) {
+ if( j != i && (j % 4) == 0 )
+ fprintf( f, " " );
+ if( j < length )
+ fprintf( f, " %02X", (unsigned int)(data[j]) );
+ else
+ fprintf( f, " " );
+ }
+ fprintf( f, " " );
+ for( j=i; j<i+16 && j<length; j++ ) {
+ fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
+ }
+ fprintf( f, "\n" );
+ }
+}
+
+static const char *file_top = "/**\n"
+ " * This file was automatically generated by genmmio, do not edit\n"
+ " */\n";
+
+void write_source( FILE *f, GList *blocks, const char *header_filename )
+{
+ fputs( file_top, f );
+ fprintf( f, "\n#include \"%s\"\n\n", header_filename );
+
+ for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
+ regblock_t block = (regblock_t)ptr->data;
+ /* Generate the mmio region struct */
+ fprintf( f, "void FASTCALL mmio_region_%s_write(uint32_t, uint32_t);\n", block->name );
+ fprintf( f, "void FASTCALL mmio_region_%s_write_word(uint32_t, uint32_t);\n", block->name );
+ fprintf( f, "void FASTCALL mmio_region_%s_write_byte(uint32_t, uint32_t);\n", block->name );
+ fprintf( f, "void FASTCALL mmio_region_%s_write_burst(uint32_t, unsigned char *);\n", block->name );
+ fprintf( f, "int32_t FASTCALL mmio_region_%s_read(uint32_t);\n", block->name );
+ fprintf( f, "int32_t FASTCALL mmio_region_%s_read_word(uint32_t);\n", block->name );
+ fprintf( f, "int32_t FASTCALL mmio_region_%s_read_byte(uint32_t);\n", block->name );
+ fprintf( f, "void FASTCALL mmio_region_%s_read_burst(unsigned char *, uint32_t);\n", block->name );
+ fprintf( f, "struct mmio_region mmio_region_%s = {\n", block->name );
+ fprintf( f, " \"%s\", \"%s\", %08x, {\n", block->name,
+ block->description == NULL ? block->name : block->description,
+ block->address );
+ fprintf( f, " mmio_region_%s_read, mmio_region_%s_write,\n", block->name, block->name );
+ fprintf( f, " mmio_region_%s_read_word, mmio_region_%s_write_word,\n", block->name, block->name );
+ fprintf( f, " mmio_region_%s_read_byte, mmio_region_%s_write_byte,\n", block->name, block->name );
+ fprintf( f, " mmio_region_%s_read_burst, mmio_region_%s_write_burst,\n", block->name, block->name );
+ fprintf( f, " unmapped_prefetch, mmio_region_%s_read_byte },\n", block->name, block->name );
+ fprintf( f, " NULL, NULL, {\n" );
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ if( reg->mode != REG_CONST ) {
+ char tmp[32];
+ const char *regname = reg->name;
+ if( regname == NULL ) {
+ regname = tmp;
+ snprintf( tmp, sizeof(tmp), "%s_%03X", block->name, reg->offset );
+ }
+
+ fprintf( f, " { \"%s\", \"%s\", %d, 0x%03x, 0x%08x, %s },\n", regname,
+ reg->description == NULL ? regname : reg->description,
+ reg->numBytes*8, reg->offset, (unsigned)reg->initValue.i,
+ (reg->mode == REG_RW ? "PORT_MRW" : (reg->mode == REG_WO ? "PORT_W" : "PORT_R")) );
+ }
+ }
+ fprintf( f, " }, NULL };\n" );
+ }
+
+}
+
+void write_header( FILE *f, GList *blocks )
+{
+ fputs( file_top, f );
+
+ fputs( "\n#include \"mmio.h\"\n\n", f );
+
+ for( GList *ptr = blocks; ptr != NULL; ptr = ptr->next ) {
+ regblock_t block = (regblock_t)ptr->data;
+ fprintf( f, "extern struct mmio_region mmio_region_%s;\n", block->name );
+ fprintf( f, "enum mmio_region_%s_port_t {\n", block->name );
+ for( unsigned i=0; i<block->numRegs; i++ ) {
+ regdef_t reg = block->regs[i];
+ if( reg->name != NULL ) {
+ fprintf( f, " %s = 0x%03x,\n", reg->name, reg->offset );
+ }
+ }
+ fprintf( f, "};\n" );
+ }
+}
+
+void write_test( FILE *f, GList *blocks )
+{
+
+
+}
+
+int main(int argc, char *argv[])
+{
+ const char *header = NULL;
+ const char *output = NULL;
+ gboolean check_only = FALSE;
+ int verbose = 0, opt;
+ GList *block_list = NULL;
+
+ while( (opt = getopt_long( argc, argv, short_options, long_options, NULL )) != -1 ) {
+ switch(opt) {
+ case 'c':
+ check_only = TRUE;
+ break;
+ case 'd':
+ header = optarg;
+ break;
+ case 'h':
+ print_usage();
+ exit(0);
+ case 'o':
+ output = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ }
+ }
+
+ if( optind == argc ) {
+ print_usage();
+ exit(1);
+ }
+
+ if( output == NULL ) {
+ output = makeFilename(argv[optind],".c");
+ }
+ if( header == NULL ) {
+ header = makeFilename(argv[optind],".h");
+ }
+
+ for( ; optind < argc; optind++ ) {
+ block_list = ioparse(argv[optind], block_list);
+ }
+
+ if( verbose ) {
+ dump_register_blocks(stdout, block_list, verbose>1);
+ }
+
+ int errors = check_registers(block_list);
+ if( errors != 0 ) {
+ fprintf( stderr, "Aborting due to validation errors\n" );
+ return 2;
+ }
+
+ if( !check_only ) {
+ FILE *f = fopen( output, "wo" );
+ if( f == NULL ) {
+ fprintf( stderr, "Unable to open output file '%s': %s\n", output, strerror(errno) );
+ return 3;
+ }
+ write_source( f, block_list, header );
+ fclose(f);
+
+ f = fopen( header, "wo" );
+ if( f == NULL ) {
+ fprintf( stderr, "Unable to open header file '%s': %s\n", header, strerror(errno) );
+ return 4;
+ }
+ write_header( f, block_list );
+ fclose(f);
+ }
+
+ for( GList *ptr = block_list; ptr != NULL; ptr = ptr->next ) {
+ char *data = build_page_initializer((regblock_t)ptr->data);
+ fwrite_dump( data, LXDREAM_PAGE_SIZE, stdout );
+ g_free(data);
+ }
+ return 0;
+}
+
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="added" class="pathname" style="font-family:monospace; float:right; background-color:#ddffdd;" >lxdream/src/tools</span><br />
<div id="added" class="fileheader" style="margin-bottom:.5em; background-color:#ddffdd;" ><big><b>genmach.h</b></big> <small id="info" style="color: #888888;" >added at 700e16c321e5</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/tools/genmach.h
+++ lxdream/src/tools/genmach.h
@@ -0,0 +1,127 @@
</small></pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * $Id$
+ *
+ * mmio register code generator
+ *
+ * Copyright (c) 2010 Nathan Keynes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef lxdream_genmmio_H
+#define lxdream_genmmio_H 1
+
+#include <stdint.h>
+#include <glib/glist.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ REG_CONST,
+ REG_RW,
+ REG_RO,
+ REG_WO,
+ REG_MIRROR, /* Additional address for an existing register - value is the offset of the target reg */
+} register_mode_t;
+
+typedef enum {
+ REG_I8,
+ REG_I16,
+ REG_I32,
+ REG_I64,
+ REG_F32,
+ REG_F64,
+ REG_STRING,
+} register_type_t;
+
+typedef enum {
+ ENDIAN_DEFAULT,
+ ENDIAN_LITTLE,
+ ENDIAN_BIG
+} register_endian_t;
+
+typedef enum {
+ ACCESS_DEFAULT,
+ ACCESS_ANY,
+ ACCESS_NOOFFSET,
+ ACCESS_EXACT
+} register_access_t;
+
+typedef enum {
+ TRACE_DEFAULT,
+ TRACE_NEVER,
+ TRACE_ALWAYS
+} register_trace_t;
+
+typedef enum {
+ TEST_DEFAULT,
+ TEST_OFF,
+ TEST_ON
+} register_test_t;
+
+union apval {
+ uint64_t i;
+ char a[8];
+ const char *s;
+};
+
+struct action {
+ const char *filename;
+ int lineno;
+ const char *text;
+};
+
+typedef struct regflags {
+ register_endian_t endian;
+ register_access_t access;
+ register_trace_t traceFlag;
+ register_test_t testFlag;
+ union apval maskValue;
+ unsigned int fillSizeBytes;
+ union apval fillValue;
+} *regflags_t;
+
+typedef struct regdef {
+ const char *name;
+ const char *description;
+ uint32_t offset;
+ unsigned numBytes;
+ unsigned numElements;
+ unsigned stride;
+ register_mode_t mode;
+ register_type_t type;
+ gboolean initUndefined;
+ union apval initValue;
+ struct regflags flags;
+ struct action *action;
+} *regdef_t;
+
+typedef struct regblock {
+ const char *name;
+ const char *description;
+ uint32_t address;
+ struct regflags flags;
+ unsigned numRegs;
+ unsigned blockSize;
+ regdef_t regs[];
+} *regblock_t;
+
+
+
+GList *ioparse( const char *filename, GList *list );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !lxdream_genmmio_H */
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="added" class="pathname" style="font-family:monospace; float:right; background-color:#ddffdd;" >lxdream/src/tools</span><br />
<div id="added" class="fileheader" style="margin-bottom:.5em; background-color:#ddffdd;" ><big><b>mdparse.c</b></big> <small id="info" style="color: #888888;" >added at 700e16c321e5</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/tools/mdparse.c
+++ lxdream/src/tools/mdparse.c
@@ -0,0 +1,721 @@
</small></pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * $Id$
+ *
+ * genmmio I/O register definition parser.
+ *
+ * Copyright (c) 2010 Nathan Keynes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <glib/gmem.h>
+
+#include "genmach.h"
+/*
+ * Grammar:
+ *
+ * start: start register_block | ;
+ * register_block: 'registers' IDENTIFIER 'at' INTEGER opt_paramlist '{' register_list '}';
+ * opt_paramlist: '(' param_list ')' | '(' ')' | ;
+ * param_list: param_list ',' param | param ;
+ * param: access_param | fill_param | endian_param | mask_param ;
+ * access_param: 'access' '=' 'any' // Behaves as if it were memory
+ * | 'access' '=' 'nooffset' // Recognize any size access (zero-ext or trunc) as long as the address is exactly the same
+ * | 'access' '=' 'exact' // Recognize only the exact access type at the exact address
+ * ;
+ * fill_param: 'fill' '=' literal;
+ * endian_param: 'endian' '=' 'little'
+ * | 'endian' '=' 'big'
+ * ;
+ * mask_param: 'mask' '=' literal;
+ *
+ * register_list: register_list register_desc | ;
+ * register_desc: INTEGER ':' mode_spec type_spec IDENTIFIER opt_paramlist [ '=' literal ] [ ACTION ]
+ * mode_spec: 'const' | 'rw' | 'ro' | 'wo';
+ * type_spec: 'i8' | 'i16' | 'i32' | 'i64' | 'f32' | 'f64' | 'string' | 'cstring';
+ * literal: INTEGER | STRING | 'undefined' ;
+ *
+ * C-style comments are recognized as such.
+ */
+
+#define TOK_IDENTIFIER 1
+#define TOK_INTEGER 2
+#define TOK_STRING 3
+#define TOK_ACTION 4
+#define TOK_EOF 5
+#define TOK_ERROR 6
+#define TOK_LPAREN 7
+#define TOK_RPAREN 8
+#define TOK_LBRACE 9
+#define TOK_RBRACE 10
+#define TOK_COMMA 11
+#define TOK_COLON 12
+#define TOK_SEMI 13
+#define TOK_PERIOD 14
+#define TOK_RANGE 15
+#define TOK_LSQUARE 16
+#define TOK_RSQUARE 17
+#define TOK_EQUALS 18
+#define TOK_ACCESS 19
+#define TOK_AT 20
+#define TOK_ENDIAN 21
+#define TOK_FILL 22
+#define TOK_INCLUDE 23
+#define TOK_MASK 24
+#define TOK_REGISTERS 25
+#define TOK_SPACE 26
+#define TOK_STRIDE 27
+#define TOK_TEST 28
+#define TOK_TRACE 29
+#define TOK_UNDEFINED 30
+
+
+#define FIRST_KEYWORD TOK_ACCESS
+#define LAST_KEYWORD TOK_UNDEFINED
+static const char *TOKEN_NAMES[] = {"NULL", "IDENTIFIER", "INTEGER", "STRING", "ACTION", "EOF", "ERROR",
+ "(", ")", "{", "}", ",", ":", ";", ".", "..", "[", "]", "=",
+ "ACCESS", "AT", "ENDIAN", "FILL", "INCLUDE", "MASK", "REGISTERS", "SPACE", "STRIDE", "TEST", "TRACE", "UNDEFINED" };
+static const char *MODE_NAMES[] = {"const", "rw", "ro", "wo", "mirror"};
+static const char *TYPE_NAMES[] = {"i8", "i16", "i32", "i64", "f32", "f64", "string"};
+static int TYPE_SIZES[] = {1,2,4,8,4,8,0};
+static const char *ENDIAN_NAMES[] = {"default", "little", "big"};
+static const char *ACCESS_NAMES[] = {"default", "any", "nooffset", "exact"};
+static const char *TRACE_NAMES[] = {"default", "off", "on"};
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+typedef struct token_data {
+ char *yytext;
+ int yylength;
+ int yyline;
+ int yycol;
+ union {
+ long i;
+ char *s;
+ } v;
+ int slen;
+} token_data;
+
+static char *yybuffer;
+static char *yyposn, *yylineposn;
+static char *yyend;
+static int yyline;
+static struct token_data yytok;
+
+#define YYPARSE_ERROR( msg, ... ) \
+ do { \
+ fprintf( stderr, "Parse error at %d:%d: " msg "\n", yytok.yyline, yytok.yycol, __VA_ARGS__ ); \
+ exit(2); \
+ } while(0)
+
+#define READ(x) \
+{ int _tok = iolex(x); \
+ if( _tok != (x) ) { \
+ YYPARSE_ERROR( "Expected %s but got %s", TOKEN_NAMES[x], TOKEN_NAMES[_tok] ); \
+ } \
+}
+
+static int iolex( int expectToken );
+static int iolex_open( const char *filename );
+static void iolex_close();
+
+static inline char *yystrdup()
+{
+ char *str = g_malloc0(yytok.yylength+1);
+ memcpy( str, yytok.yytext, yytok.yylength);
+ return str;
+}
+
+static inline int yystrcasecmp(const char *cmp)
+{
+ int len = strlen(cmp);
+ if( len != yytok.yylength ) {
+ return yytok.yylength - len;
+ }
+ return strncasecmp(yytok.yytext, cmp, yytok.yylength);
+}
+
+static int yymatch( const char *arr[], unsigned numOptions )
+{
+ for( unsigned i=0; i<numOptions; i++ ) {
+ if( yystrcasecmp( arr[i] ) == 0 ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static gint register_block_sort_cb( gconstpointer a, gconstpointer b )
+{
+ struct regblock *blocka = (struct regblock *)a;
+ struct regblock *blockb = (struct regblock *)b;
+ return blocka->address - blockb->address;
+}
+
+static int register_ptr_sort_cb( const void *a, const void *b )
+{
+ regdef_t *ptra = (regdef_t *)a;
+ regdef_t *ptrb = (regdef_t *)b;
+ if( (*ptra)->offset != (*ptrb)->offset )
+ return (*ptra)->offset - (*ptrb)->offset;
+ return (*ptra)->type - (*ptrb)->type;
+}
+
+static void ioparse_apval(int tok, union apval *apv, unsigned *numBytes)
+{
+ if( tok == TOK_INTEGER ) {
+ apv->i = yytok.v.i;
+ if( *numBytes == 0 ) {
+ YYPARSE_ERROR( "Expected string initializer but was an integer (0x%x)", yytok.v.i );
+ }
+ } else if( tok = TOK_STRING ) {
+ if( *numBytes == 0 ) {
+ *numBytes = yytok.slen;
+ apv->s = yytok.v.s;
+ } else {
+ if( *numBytes != yytok.slen ) {
+ YYPARSE_ERROR( "Expected %d byte initializer but was %d", *numBytes, yytok.slen );
+ }
+ assert( *numBytes < sizeof(uint64_t) );
+ apv->i = 0;
<a name="task1" />+ /* <span class="task" style="background-color:#ffff00;" >FIXME</span>: handle endian mismatches */
+ memcpy( &apv->i, yytok.v.s, yytok.slen );
+ }
+ } else {
+ YYPARSE_ERROR( "Expected literal (integer or string), but got %s", TOKEN_NAMES[tok] );
+ }
+}
+
+static void ioparse_regflags( regflags_t flags, unsigned *numBytes )
+{
+ do {
+ int tok = iolex(TOK_RPAREN);
+ switch(tok) {
+ case TOK_FILL:
+ READ(TOK_EQUALS);
+ tok = iolex(TOK_INTEGER);
+ flags->fillSizeBytes = 4;
+ ioparse_apval( tok, &flags->fillValue, &flags->fillSizeBytes );
+ break;
+ case TOK_ACCESS:
+ READ(TOK_EQUALS);
+ READ(TOK_IDENTIFIER);
+ flags->access = yymatch(ACCESS_NAMES,elementsof(ACCESS_NAMES));
+ if( flags->access == -1 ) {
+ YYPARSE_ERROR("Unknown access mode '%s'", yystrdup());
+ }
+ break;
+ case TOK_MASK:
+ if( numBytes ) {
+ READ(TOK_EQUALS);
+ tok = iolex(TOK_INTEGER);
+ ioparse_apval( tok, &flags->maskValue, numBytes );
+ } else {
+ YYPARSE_ERROR("mask is not valid on a register block",0);
+ }
+ break;
+ case TOK_ENDIAN:
+ READ(TOK_EQUALS);
+ READ(TOK_IDENTIFIER);
+ flags->endian = yymatch(ENDIAN_NAMES,elementsof(ENDIAN_NAMES));
+ if( flags->endian == -1 ) {
+ YYPARSE_ERROR("Unknown endianness '%s'", yystrdup());
+ }
+ break;
+ case TOK_TRACE:
+ READ(TOK_EQUALS);
+ READ(TOK_IDENTIFIER);
+ flags->traceFlag = yymatch(TRACE_NAMES,elementsof(TRACE_NAMES));
+ if( flags->traceFlag == -1 ) {
+ YYPARSE_ERROR("Unknown trace flag '%s'", yystrdup());
+ }
+ break;
+ case TOK_TEST:
+ READ(TOK_EQUALS);
+ READ(TOK_IDENTIFIER);
+ flags->testFlag = yymatch(TRACE_NAMES,elementsof(TRACE_NAMES));
+ if( flags->testFlag == -1 ) {
+ YYPARSE_ERROR("Unknown test flag '%s'", yystrdup());
+ }
+ break;
+ case TOK_COMMA:
+ break;
+ case TOK_RPAREN:
+ return;
+ default:
+ YYPARSE_ERROR("Expected flag or ')' but was %s", TOKEN_NAMES[tok]);
+ }
+ } while(1);
+}
+
+static void ioparse_regdef( struct regdef *reg )
+{
+ reg->offset = yytok.v.i;
+ reg->numElements = 1;
+ reg->numBytes = 0;
+ reg->initValue.i = 0;
+ reg->flags.maskValue.i = -1;
+ unsigned rangeOffset = reg->offset;
+
+ int tok = iolex(TOK_COLON);
+ if( tok == TOK_RANGE ) {
+ READ(TOK_INTEGER);
+ rangeOffset = yytok.v.i;
+ if( rangeOffset < reg->offset ) {
+ YYPARSE_ERROR( "Range end (0x%x) must be greater than the range start (0x%x)", rangeOffset, reg->offset );
+ }
+ READ(TOK_COLON);
+ } else if( tok != TOK_COLON ) {
+ YYPARSE_ERROR( "Expected ':' but was %s\n", TOKEN_NAMES[tok] );
+ }
+ READ(TOK_IDENTIFIER);
+ reg->mode = yymatch(MODE_NAMES, elementsof(MODE_NAMES));
+ if( reg->mode == -1 ) {
+ YYPARSE_ERROR( "Unknown register mode '%s'", yystrdup() );
+ }
+ if( reg->mode == REG_MIRROR ) {
+ /* Mirror regions have a target range only */
+ READ(TOK_INTEGER);
+ reg->initValue.i = yytok.v.i;
+ reg->type = REG_I8;
+ tok = iolex(TOK_RANGE);
+ if( tok == TOK_RANGE ) {
+ READ(TOK_INTEGER);
+ if( yytok.v.i < reg->initValue.i ) {
+ YYPARSE_ERROR( "Invalid mirror target range 0x%x..0x%x", reg->initValue.i, yytok.v.i );
+ }
+ reg->numBytes = yytok.v.i - reg->initValue.i + 1;
+ tok = iolex(TOK_STRIDE);
+ }
+ if( tok == TOK_STRIDE ) {
+ READ(TOK_INTEGER);
+ reg->stride = yytok.v.i;
+ tok = iolex(TOK_ACTION);
+ } else {
+ reg->stride = reg->numBytes;
+ }
+
+ if( tok != TOK_SEMI ) {
+ YYPARSE_ERROR( "Expected ; but gut %s", TOKEN_NAMES[tok] );
+ }
+
+ if( reg->stride < reg->numBytes ) {
+ YYPARSE_ERROR( "Invalid mirror stride: %x is less than block size %x\n", reg->stride, reg->numBytes );
+ }
+
+ if( rangeOffset != reg->offset ) {
+ reg->numElements *= ((rangeOffset - reg->offset) + reg->stride - 1) / reg->stride;
+ }
+
+ } else {
+ READ(TOK_IDENTIFIER);
+ reg->type = yymatch(TYPE_NAMES, elementsof(TYPE_NAMES));
+ if( reg->type == -1 ) {
+ YYPARSE_ERROR( "Unknown register type '%s'", yystrdup() );
+ }
+ reg->numBytes = TYPE_SIZES[reg->type];
+ tok = iolex(TOK_IDENTIFIER);
+ if( tok == TOK_IDENTIFIER ) {
+ reg->name = yystrdup();
+ tok = iolex(TOK_ACTION);
+ }
+ if( tok == TOK_STRING ) {
+ reg->description = yytok.v.s;
+ tok = iolex(TOK_ACTION);
+ }
+ if( tok == TOK_LPAREN ) {
+ ioparse_regflags(®->flags, ®->numBytes);
+ tok = iolex(TOK_ACTION);
+ }
+ if( tok == TOK_EQUALS ) {
+ tok = iolex(TOK_INTEGER);
+ if( tok == TOK_UNDEFINED ) {
+ reg->initValue.i = 0xDEADBEEFDEADBEEF;
+ reg->initUndefined = TRUE;
+ } else {
+ ioparse_apval(tok, ®->initValue, ®->numBytes);
+ }
+ tok = iolex(TOK_ACTION);
+ } else if( reg->type == REG_STRING ) {
+ YYPARSE_ERROR( "String declarations must have an initializer (ie = 'abcd')",0 );
+ }
+ if( tok == TOK_ACTION ) {
+ // reg->action = yystrdup();
+ } else if( tok != TOK_SEMI ) {
+ YYPARSE_ERROR( "Expected ; or {, but got %s", TOKEN_NAMES[tok] );
+ }
+
+ if( rangeOffset != reg->offset ) {
+ reg->numElements *= ((rangeOffset - reg->offset) + reg->numBytes - 1) / reg->numBytes;
+ }
+ }
+
+}
+
+static struct regblock *ioparse_regblock( )
+{
+ unsigned regsAllocSize = 128;
+ struct regblock *block = g_malloc0(sizeof(struct regblock) + sizeof(regdef_t)*regsAllocSize);
+ block->numRegs = 0;
+
+ READ(TOK_IDENTIFIER);
+ block->name = yystrdup();
+ int tok = iolex(TOK_AT);
+ if( tok == TOK_STRING ) {
+ block->description = yytok.v.s;
+ tok = iolex(TOK_AT);
+ }
+ if( tok != TOK_AT ) {
+ YYPARSE_ERROR("Expected AT but got %s\n", TOKEN_NAMES[tok] );
+ }
+ READ(TOK_INTEGER);
+ block->address = yytok.v.i;
+
+ tok = iolex(TOK_LBRACE);
+ if( tok == TOK_LPAREN) {
+ ioparse_regflags(&block->flags, NULL);
+ READ(TOK_LBRACE);
+ } else if( tok != TOK_LBRACE ) {
+ YYPARSE_ERROR("Expected { but got %s\n", TOKEN_NAMES[tok] );
+ }
+
+ tok = iolex(TOK_INTEGER);
+ while( tok != TOK_RBRACE ) {
+ if( tok != TOK_INTEGER ) {
+ YYPARSE_ERROR("Expected INTEGER or } but got %s\n", TOKEN_NAMES[tok]);
+ }
+ struct regdef *regdef = g_malloc0(sizeof(struct regdef));
+ if( block->numRegs >= regsAllocSize ) {
+ regsAllocSize *= 2;
+ block = g_realloc(block, sizeof(struct regblock) + sizeof(regdef_t)*regsAllocSize);
+ }
+ block->regs[block->numRegs++] = regdef;
+ ioparse_regdef(regdef);
+
+ tok = iolex(TOK_INTEGER);
+ }
+
+ qsort( &block->regs[0], block->numRegs, sizeof(block->regs[0]), register_ptr_sort_cb );
+
+ return block;
+}
+
+GList *ioparse( const char *filename, GList *list )
+{
+ GList *blocks = list;
+ int count = 0;
+
+ if( iolex_open(filename) != 0 )
+ return blocks;
+
+ int tok;
+ do {
+ tok = iolex(TOK_REGISTERS);
+ if( tok == TOK_EOF ) {
+ return blocks;
+ } else if( tok == TOK_INCLUDE) {
+ READ(TOK_STRING);
+
+ } else if( tok == TOK_SPACE ) {
+ } else if( tok == TOK_REGISTERS ) {
+ struct regblock *block = ioparse_regblock(block);
+ count++;
+ blocks = g_list_insert_sorted(blocks, block, register_block_sort_cb);
+ } else {
+ YYPARSE_ERROR("Expected REGISTERS but got %s\n", TOKEN_NAMES[tok] );
+ }
+ } while( tok != TOK_EOF );
+
+ iolex_close();
+ if( count == 0 ) {
+ fprintf( stderr, "Warning: input file '%s' did not contain any register definitions\n" );
+ }
+
+ return blocks;
+}
+
+/**************************** Lexical analyser ***************************/
+
+static int iolex_open( const char *filename )
+{
+ struct stat st;
+ int fd = open( filename, O_RDONLY );
+ if( fd == -1 ) {
+ fprintf( stderr, "Error opening file '%s': %s\n", filename, strerror(errno) );
+ return -1;
+ }
+
+ if( fstat( fd, &st ) != 0 ) {
+ fprintf( stderr, "Error statting file '%s': %s\n", filename, strerror(errno) );
+ close(fd);
+ return -1;
+ }
+
+ char *data = g_malloc( st.st_size + 1 );
+ if( read(fd, data, st.st_size) != st.st_size ) {
+ fprintf( stderr, "Error reading file '%s': %s\n", filename, strerror(errno) );
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ data[st.st_size] = 0;
+
+ yybuffer = yyposn = data;
+ yyend = data + st.st_size;
+ yyline = 1;
+ yylineposn = yyposn;
+ return 0;
+}
+
+static void iolex_close()
+{
+ g_free(yybuffer);
+ yybuffer = yyend = NULL;
+}
+
+#define YYRETURN(x) do{ \
+ yytok.yylength = yyposn - yystart; \
+ return (x); \
+} while(0)
+
+static int iolex_readhex(char *p, int digits)
+{
+ int result = 0;
+ for( int i=0; i < digits; i++ ) {
+ result <<= 4;
+ if( isdigit(p[i]) ) {
+ result += p[i]-'0';
+ } else if( p[i] >= 'a' && p[i] <= 'f' ) {
+ result += p[i]-'a'+10;
+ } else if( p[i] >= 'A' && p[i] <= 'F' ) {
+ result += p[i]-'A'+10;
+ } else {
+ return (result >> 4);
+ }
+
+ }
+ return result;
+}
+
+static int iolex_readoctal(char *p, int digits)
+{
+ int result = 0;
+ for( int i=0; i < digits; i++ ) {
+ result <<= 3;
+ if( p[i] >= '0' && p[i] <= '7' ) {
+ result += p[i]-'0';
+ } else {
+ return (result >> 4);
+ }
+ }
+ return result;
+}
+
+/**
+ * Copy and interpret the string segment as a C string, replacing escape
+ * expressions with the corresponding value.
+ */
+static char *iolex_getcstring( char *start, char *end, int *len )
+{
+ char *result = g_malloc0(end-start+1); /* Allocate enough memory for the string as-is */
+ char *q = result;
+
+ for( char *p = start; p != end; p++ ) {
+ if( *p == '\\' ) {
+ if( ++p == end ) {
+ *q++ = '\\';
+ break;
+ }
+ if( p[0] >= '0' && p[0] <= '3' && p+3 <= end &&
+ p[1] >= '0' && p[1] <= '7' &&
+ p[2] >= '0' && p[2] <= '7' ) {
+ *q++ = (char)iolex_readoctal(p,3);
+ p+=2;
+ } else {
+ switch( *p ) {
+ case 'n':
+ *q++ = '\n';
+ break;
+ case 'r':
+ *q++ = '\r';
+ break;
+ case 't':
+ *q++ = '\t';
+ break;
+ case 'x': /* hex */
+ if( p + 3 > end || !isxdigit(p[1]) || !isxdigit(p[2]) ) {
+ *q++ = '\\';
+ *q++ = *p;
+ } else {
+ *q++ = (char)iolex_readhex(p+1, 2);
+ p+=2;
+ }
+ break;
+ default:
+ *q++ = '\\';
+ *q++ = *p;
+ }
+ }
+ } else {
+ *q++ = *p;
+ }
+ }
+ *len = q - result;
+ return result;
+}
+
+int iolex( int expectToken )
+{
+ int count = 0;
+ while( yyposn < yyend ) {
+ char *yystart = yytok.yytext = yyposn;
+ yytok.yylength = 1;
+ yytok.yyline = yyline;
+ yytok.yycol = yyposn - yylineposn+1;
+ int ch = *yyposn++;
+ if( isdigit(ch) ) {
+ /* INTEGER */
+ if( ch == '0' ) {
+ if( *yyposn == 'x' ) {
+ while( yyposn < yyend && isxdigit(*++yyposn) ) ;
+ } else {
+ while( yyposn < yyend && *yyposn >= '0' && *yyposn <= '7' )
+ yyposn++;
+ }
+ } else {
+ while( yyposn < yyend && isdigit(*yyposn) )
+ yyposn++;
+ }
+ yytok.v.i = strtol( yystart, NULL, 0 );
+ YYRETURN(TOK_INTEGER);
+ } else if( isalpha(ch) || ch == '_' ) {
+ /* IDENTIFIER */
+ while( yyposn < yyend && (isalnum(*yyposn) || *yyposn == '_') )
+ yyposn++;
+ yytok.yylength = yyposn - yystart;
+ if( expectToken == TOK_IDENTIFIER ) {
+ YYRETURN(TOK_IDENTIFIER);
+ }
+ /* Otherwise check for keywords */
+ for( int i=FIRST_KEYWORD; i <= LAST_KEYWORD; i++ ) {
+ if( strlen(TOKEN_NAMES[i]) == yytok.yylength &&
+ strncasecmp(TOKEN_NAMES[i], yystart, yytok.yylength ) == 0 ) {
+ YYRETURN(i);
+ }
+ }
+ YYRETURN(TOK_IDENTIFIER);
+ } else if( isspace(ch) ) {
+ if( ch == '\n' ) {
+ yyline++;
+ yylineposn = yyposn;
+ }
+ while( isspace(*yyposn) ) {
+ if( *yyposn == '\n' ) {
+ yyline++;
+ yylineposn = yyposn+1;
+ }
+ yyposn++;
+ }
+ } else {
+ switch( ch ) {
+ case '(': YYRETURN(TOK_LPAREN);
+ case ')': YYRETURN(TOK_RPAREN);
+ case '[': YYRETURN(TOK_LSQUARE);
+ case ']': YYRETURN(TOK_RSQUARE);
+ case ',': YYRETURN(TOK_COMMA);
+ case ':': YYRETURN(TOK_COLON);
+ case ';': YYRETURN(TOK_SEMI);
+ case '=': YYRETURN(TOK_EQUALS);
+ case '/':
+ if( *yyposn == '/' ) { /* Line comment */
+ while( yyposn < yyend && *++yyposn != '\n' ) ;
+ } else if( *yyposn == '*' ) { /* C comment */
+ while( yyposn < yyend && (*++yyposn != '*' || *++yyposn != '/' ) ) {
+ if( *yyposn == '\n' ) {
+ yyline++;
+ yylineposn = yyposn+1;
+ }
+ }
+ }
+ break;
+ case '\'': /* STRING */
+ while( *yyposn != '\'' ) {
+ if( *yyposn == '\n' ) {
+ fprintf( stderr, "Unexpected newline in string constant!\n" );
+ YYRETURN(TOK_ERROR);
+ } else if( yyposn >= yyend ) {
+ fprintf( stderr, "Unexpected EOF in string constant!\n" );
+ YYRETURN(TOK_ERROR);
+ } else if( *yyposn == '\\' && yyposn[1] == '\'' ) {
+ yyposn++;
+ }
+ yyposn++;
+ }
+ yyposn++;
+ yytok.v.s = iolex_getcstring(yystart+1, yyposn-1, &yytok.slen);
+ YYRETURN(TOK_STRING);
+ case '\"': /* STRING */
+ while( *yyposn != '\"' ) {
+ if( *yyposn == '\n' ) {
+ fprintf( stderr, "Unexpected newline in string constant!\n" );
+ YYRETURN(TOK_ERROR);
+ } else if( yyposn >= yyend ) {
+ fprintf( stderr, "Unexpected EOF in string constant!\n" );
+ YYRETURN(TOK_ERROR);
+ } else if( *yyposn == '\\' && yyposn[1] == '\"' ) {
+ yyposn++;
+ }
+ yyposn++;
+ }
+ yyposn++;
+ yytok.v.s = iolex_getcstring(yystart+1, yyposn-1, &yytok.slen);
+ YYRETURN(TOK_STRING);
+ case '}':
+ YYRETURN(TOK_RBRACE);
+ case '{': /* ACTION or LBRACE */
+ if( expectToken == TOK_LBRACE ) {
+ YYRETURN(TOK_LBRACE);
+ } else {
+ count++;
+ while( count > 0 && yyposn < yyend ) {
+ if( *yyposn == '{' )
+ count++;
+ if( *yyposn == '}' )
+ count--;
+ yyposn++;
+ }
+ YYRETURN(TOK_ACTION);
+ }
+ case '.':
+ if( *yyposn == '.' ) {
+ yyposn++;
+ YYRETURN(TOK_RANGE);
+ } else {
+ YYRETURN(TOK_PERIOD);
+ }
+ default:
+ fprintf( stderr, "Illegal character: '%c'\n", ch );
+ YYRETURN(TOK_ERROR);
+ }
+ }
+
+ }
+ return TOK_EOF;
+}
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>