--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+bin_PROGRAMS = as10k1
+as10k1_SOURCES = as10k1.c parse.c assemble.c macro.c
+EXTRA_DIST = cvscompile output.doc examples/Makefile examples/*.asm
+
+dsp:
+ $(MAKE) -C examples
+
+clean:
+ rm -rf .deps *~
+ $(MAKE) -C examples clean
--- /dev/null
+
+AS10k1 Assembler version A0.99
+------------------------------
+
+This is an assembler for the emu10k1 DSP chip present in the creative SB
+live, PCI 512, and emu APS sound cards. It is used to make audio effects such
+as a flanger, chorus or reverb.
+
+
+Author: Daniel Bertrand <d.bertrand@ieee.ca>
+
+
+This version of the assembler was modified for the ALSA driver by
+Jaroslav Kysela <perex@suse.cz>.
+
+
+Usage: as10k1 <asm file> [bin output file]
+------
+
+Making binary DSP programs:
+
+example, type:
+
+./as10k1 chorus.asm
+
+(it creates chorus.bin)
+
+--
+Loading Binary DSP files
+
+
+<..TODO..>
+
+
+Description of files included
+------------------------------
+
+Chorus.asm -- chorus effect
+Flanger.asm -- flanger effect
+Delay.asm -- generates Echos, this is _not_ a reverb
+eq5.asm -- A 5 band Equalizer (needs a bit more work)
+fir.asm -- A low pass filter (A demo of a fir filter implementation)
+sine.asm -- A sinewave generator (can be useful for debuging)
+vibrato.asm -- A vibrato effect (or is it a tremolo?)
+vol_ctrl.asm -- provides support for the hardware volume control
+emu_constants.asm -- not an effect, just contains handy constants and macros
+
+
+
+
+===============================================================================
+
+
+Programming Usage:
+=================
+
+Assembly Syntax
+---------------
+
+Assembly lines generally have four fields seperated by spaces or tabs:
+
+
+Name_Field Opcode_field Operand_Field Comment_Field
+---------- ------------ ------------- -------------
+[symbol] [mnemonic] [operands] [text]
+
+
+With this assembler, each line can have a maximum of 256 characters and each
+symbol can be a maximum of 32 characters. Symbols ARE case sensitive, opcodes
+ARE NOT.
+
+OPCODES
+--------
+
+
+All instructions require 4 operands, they have the format
+
+ <opcode> R,A,X,Y
+
+(note some documentation out there the call the R operand as Z and the A
+operand as W).
+
+Here are 16 opcodes.
+
+ 0x0 (MACS) : R = A + (X * Y >> 31) ; saturation
+ 0x1 (MACS1) : R = A + (-X * Y >> 31) ; saturation
+ 0x2 (MACW) : R = A + (X * Y >> 31) ; wraparound
+ 0x3 (MACW1) : R = A + (-X * Y >> 31) ; wraparound
+ 0x4 (MACINTS) : R = A + X * Y ; saturation
+ 0x5 (MACINTW) : R = A + X * Y ; wraparound (31-bit)
+ 0x6 (ACC3) : R = A + X + Y ; saturation
+ 0x7 (MACMV) : R = A, acc += X * Y >> 31
+ 0x8 (ANDXOR) : R = (A & X) ^ Y
+ 0x9 (TSTNEG) : R = (A >= Y) ? X : ~X
+ 0xa (LIMIT) : R = (A >= Y) ? X : Y
+ 0xb (LIMIT1): R = (A < Y) ? X : Y
+ 0xc (LOG) : ...
+ 0xd (EXP) : ...
+ 0xe (INTERP) : R = A + (X * (Y - A) >> 31) ; saturation
+ 0xf (SKIP) : R,CCR,CC_TEST,COUNT
+
+
+Special note on the accumulator:
+mac* instruction with ACCUM as A operand => uses Most significant 32 bits.
+macint* instruction with ACCUM as A operand => uses Least significant 32 bits.
+
+
+For more details on the emu10k1 see the dsp.txt file distributed with the
+linux driver.
+
+
+
+Operands
+--------
+
+Operands can be specified as either a symbol or a value. hex values are
+prefixed by $, octal by @, and binary by %.
+
+e.g.:
+
+123 decimal value
+$123 hex value
+@123 octal value
+%01101 binary value
+
+The operands for emu10k1 instructions are always addresses of registers, there
+are no instruction which take immediate values.
+
+Operands currently support basic arithmetic, It does not support bedmas (or is it bodmas)
+so don't try to use (). Infact don't put spaces either (for now, until I fix this).
+
+Summary of assembler directives
+-------------------------------
+
+ NAME "string" ;give a name to the patch
+
+<symbol> IO ;defines an Input/output pair
+<symbol> CONTROL <symbol> ;defines a controlable GPR
+<symbol> DYNamic <number of storage spaces> ;defines a temporary GPR
+<symbol> STAtic <initial value> ;defines a constant GPR /w initial value
+<symbol> EQU <Value equated> ;assembly time constant
+<symbol> CONstant <value> ;defines a read-only GPR
+
+<symbol> DELAY <value> ;defines a Delay line
+<symbol> TABLE <value> ;defines a lookup table
+
+<symbol> TREAD <tram id>,<value> ;defines a tram read
+<symbol> TWRITE <tram id>,<value> ;defines a tram write
+
+
+ INCLUDE <"file name"> ;includes an external file
+
+ FOR <variable>=<start>:<finish> ;Assembly-time 'for' statement
+ ENDFOR ;ends a for loop
+
+
+<symbol> MACRO arg1,arg2,arg3.... ;used for define a macro
+ ENDM ;end a macro definition
+
+ END ;ends the code
+
+
+Detailed description of directives:
+----------------------------------
+
+( <> brackets indicate required fields, [] brackets indicate optional fields)
+
+DYNamic directive (replaces DS):
+
+Defines a storage space from the gpr pool on the emu10k1. The
+assembler maintains a pointer to the gpr registers (starting at $100). The
+symbol is assigned the value of the address of the gpr pointer. The pointer is
+increment by the number following the dynamic directive.
+
+syntax:
+<symbol> dynamic <number of storage spaces
+
+or
+
+<symbol> dyn <number of storage spaces>
+
+--
+STAtic directive (replaces DC):
+
+Similar to dynamic, but places an initial value in the memory location.
+
+The values specified are slightly different from operands for instructions.
+The values are 32 bit signed intergers so that a maximum magnitude of 2^31 can
+be stored. values can be in signed decimal, unsigned octal, binary and hex,
+and in fractional decimal (values between -1 to 1) for filter coefficients.
+
+A fractional decimal is specified using the '#' prefix and can include an
+exponent. These values should be used with the fractional "mac" instructions.
+
+NEW! fractional numbers are now handle automatically, a value between 1 and
+-1 will be converted into fractional form. The old # form still works though.
+(BUG:confusion occurs at 1 and -1 however, should 1 be represented as $1
+ or $7ffffff?, currently defaults to $1, so #1 still has some importance)
+
+examples:
+ .03412
+ 123E-3
+ #-0.1236
+
+syntax:
+
+<symbol> static <initial value>
+
+or
+
+<symbol> sta <initial value>
+
+--
+CONTROL
+
+Control registers are similar to DC, but they also include a min and max value. The control register is used
+by a mixer app to change values in a GPR (a volume control, for example).
+
+syntax:
+
+<symbol> CONTROL <initial value>,<min>,<max>
+
+--
+IO
+
+Defines an input and an output register.
+
+<symbol> IO
+
+It defines two register, but they both use the symbol. The assembler handles it automagically
+depending on whether you're performing a read (X, Y or Z operand) or a write (R operand) to the GPR.
+
+-
+If you insist on having two different symbols for read/write (for readability or whatever), use an EQU,
+
+i.e.:
+
+IN IO
+OUT EQU IN
+
+-
+To force a read from the output (for whatever reason) use <symbol>.o (i.e. OUT.o)
+
+Writing to an input is not allowed.
+--
+CONSTANT
+
+defines a read-only constant GPR
+
+When the assembler encounters a CONSTANT define, it'll try three things. First
+it'll check to see if the defined constant is a hardware constant, if so
+substitutes that instead. Next the assembler check to see if another constant
+has alrady been declared with the same value, if so it'll substitute it. Else
+it'll declare a new GPR for holding the value of the constant.
+
+syntax:
+
+<symbol> constant <value>
+
+or
+
+<symbol> con <value>
+
+
+--
+
+DELAY LINES
+
+Delay lines are defined via three directives:
+
+--
+DELAY Directive
+
+Define Delay, used for allocating an amount of TRAM for a delay line.
+
+<symbol> DELAY <value>
+
+The symbol is used to identify this delay line.The value is the amount of TRAM
+allocated, it may be specified as a decimal,hex, octal, binary or time value.
+
+The time value is prefixed with '&' and represents seconds of time.
+
+e.g.
+
+foo DELAY &100e-3 ;;a 100msec delay line
+bar DELAY 1000 ;;a 1000 sample delay line
+
+--
+TABLE directive
+
+Define lookup Table
+
+same as DELAY but for lookup tables.
+
+--
+TREAD Directive
+
+Define read: used for defining a TRAM read point
+
+<symbol1> TREAD <symbol2>,<value>
+
+The value represents the read point within the delay line. symbol2 defines
+which delay line this read belongs to.
+
+Symbol1 is a pointer to TRAM data register associated with this TRAM read
+operation. The assembler will create <symbol1>.a which points to the TRAM
+address register.
+
+example:
+
+fooread TREAD 100e-3,foo
+ macs fooread.a,one,two,three ; writes a new tram read address
+ macs temp,fooread,one,two ; reads the data from the delay line
+
+--
+WRITE Direcive
+
+Define write: same as TREAD but used for writing data to a delay line.
+<symbol1> TWRITE <symbol2>,<value>
+
+--
+EQU directive:
+
+Equates a symbol to a be constant which is substituted at assembly time:
+
+syntax:
+
+<symbol> EQU <Value equated>
+
+--
+END directive
+
+The END directive should be placed at the end of the assembly source file. If
+the END directive is not found, a warning will be generated. All text located
+after the END directive is ignored.
+
+Syntax:
+
+[symbol] END
+
+--
+INCLUDE Directive
+
+The include directive is used to include external asm files into the current
+asm file.
+
+Syntax:
+
+ INCLUDE <"file name">
+
+The file name Must be enclosed in "" or '' .
+
+examples:
+
+ include 'qwerty.asm'
+ include "foobar.asm"
+
+
+--
+
+MACRO directive
+
+Used for defining a macro
+
+Defining Macro:
+
+<symbol> macro arg1,arg2,arg3....
+ ....
+ <opcode> arg4,arg1,arg2... ;;for example
+ ....
+ ....
+ endm
+
+were the <symbol> used is the nmeumonic representing the macro.
+
+arg1,arg2,arg3... can be any symbols (auto-defining and local to a macro)
+as long as the symbol is not already in use outside the macro (i.e. as
+a DC, DS, etc.).
+
+There's no limit to how many arguments can be used.
+
+
+Using Macro:
+
+ <macro nmeumonic> arg1,arg2,arg3....
+
+where arg1,arg2,arg3,... are values or symbols.
+
+--
+Assembly-time For loop
+
+
+usage:
+
+ For <symbol>=<start>:<stop>
+ ...
+ ...
+ macs <symbol>,....
+ ...
+ endfor
+
+<start> and <stop> must be integers
+
+
+--
+Handling Skips
+
+the as10k1 assembler handles skips in a special way explained best by an example:
+
+ skip CRR,CRR,CC_test,.foo
+ ...
+ ...
+ ...
+.foo ...
+
+the "." tell the assembler that the symbol is for skipping purposes, it will
+automatically define a GPR when parsing the skip instruction, and when the second
+.foo is encountered it will insert the number of instructions to skip. (the skip
+instruction needs a GPR by design, so don't blame me for the half-assness of it).
+
+
+
+Features NOT YET Supported
+==========================
+
+any ideas?
+
+
+
+
+
+
--- /dev/null
+/***************************************************************************
+ as10k1.c - Main assembler routine
+ -------------------
+ Date : May 22, 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/*
+ * This program was changed to conform the ALSA ideas. Please,
+ * bug reports and all other things should be discussed on the
+ * <alsa-devel@alsa-project.org> mailing list.
+ * Jaroslav Kysela <perex@suse.cz>
+ */
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include<stdio.h>
+#include<stdlib.h>
+#include<fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include<string.h>
+#include "types.h"
+
+#include "as10k1.h"
+
+char *ptralloc[MAXINCLUDES];
+static int num_alloc;
+int source_line_num=0,file_num=0;
+int macro_line_num=0;
+FILE *fp=NULL,*listfile;
+char *input=NULL,*output=NULL,*listing=NULL,*current_line=NULL,listtemp[60];
+
+
+int dbg_opt=0;
+
+char version[]="As10k1 assembler version " VERSION;
+
+char help[]="
+Usage: as10k1 [option...] asmfile
+
+The as10k1 assembler is for the emu10k1 dsp processor
+found in Creative Lab's sblive series of sound cards.
+
+Author: Daniel Bertrand <d.bertrand@ieee.ca>
+
+Options:\n
+ -l [listfile] Specify a listing file, default is none.
+ -o [emu10k1 file] Specify an output file, default is based input,
+ Substituting .asm to .emu10k1
+ -d [dbg_options...] Turn on debug messages.
+ s prints all symbols
+ g prints defined gprs
+ t prints tram usage
+ i prints instructions
+ -h Prints this message
+ -v Prints version number.
+
+This program is distributed under the GPL.
+
+";
+
+// cli==Command-Line Interface && !Creative Labs Inc.
+
+void parse_cli_args(int argc, char *argv[])
+{
+ int i,j;
+ for(i=1;i<argc;i++){
+
+ if(argv[i][0]=='-'){
+ switch(argv[i][1]){
+
+ case 'o'://specify an output file name
+ i++;
+ if((i==argc)||(argv[i][0]=='-')){
+ printf("Error -o option requires a destination file name\n");
+ exit(-1);
+ }
+ output=argv[i];
+ break;
+ case 'd': //turn on debugging messages
+ j=0;
+ i++;
+ printf("Debug on, Displaying:");
+
+ if((i==argc)||(argv[i][0]=='-')){
+ dbg_opt=dbg_opt|DBG_INSTR;//default
+ i--;
+ printf(" instructions by default\n");
+ goto next_cli_arg;
+ }
+
+ while(argv[i][j]!='\0'){
+
+ switch(argv[i][j]){
+ case 's':
+ dbg_opt=dbg_opt|DBG_SYM;
+ printf(" Symbols,");
+ break;
+ case 'g':
+ dbg_opt=dbg_opt|DBG_GPR;
+ printf(" GPRs,");
+ break;
+ case 't':
+ dbg_opt=dbg_opt|DBG_TRAM;
+ printf(" TRAM,");
+ break;
+ case 'i':
+ dbg_opt=dbg_opt|DBG_INSTR;
+ printf(" Instructions,");
+ break;
+
+ default:
+ printf("\b \n**Bad debug option. ");
+ exit(-1);
+ }
+ j++;
+ }
+ printf("\b \n");
+ break;
+
+ case 'l'://produce a listing file
+ //printf("Will save list file to %s\n", );
+ i++;
+ if((i==argc)||(argv[i][0]=='-')){
+ printf("Error -l option requires a destination file name\n");
+ exit(-1);
+ }
+ listing=argv[i];
+
+
+ break;
+
+ case 'h'://printf help message
+
+ default:
+ printf("%s",help);
+
+ case 'v':
+ printf("%s\n",version);
+ exit(0);
+ }
+
+
+ }else{
+ if(input==NULL)
+ input=argv[i];
+ else{
+ printf("Error, only one input file can be specified");
+ as_exit("");
+
+ }
+
+ }
+next_cli_arg:
+
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+
+ int i;
+ char filename[FILENAME_MAX];
+ extern int ip;
+ u32 val;
+
+ parse_cli_args(argc,argv);
+ if(input==NULL){
+ printf("Error, an input file must be specified\n");
+ exit(-1);
+ }
+
+ //init symbol list:
+
+ INIT_LIST_HEAD(&sym_head);
+
+ if(listing!=NULL)
+ if((listfile = fopen(listing, "w"))==NULL){
+ printf("\nError writing to file %s\n",argv[1]);
+ as_exit("error");
+ }
+ asm_open(input); //opens the source file and starts parsing it.
+
+ if(output==NULL){
+ strcpy(filename, input);
+ strtok(filename,".\0");
+ strcat(filename, ".emu10k1");
+ output = filename;
+ }
+
+ if((fp = fopen(output, "w"))==NULL){
+ printf("\nError writing to file %s\n",argv[1]);
+ as_exit("error");
+ }
+
+ if(listing)
+ fprintf(listfile,"Summary:\n");
+ /*create header*/
+ header();
+
+ /*output number of instructions*/
+
+ val = __cpu_to_le32(ip);
+ fwrite(&val,sizeof(u16),1,fp);
+
+ /* write binary code */
+
+
+ for (i = 0; i < ip; i++) {
+ val = __cpu_to_le32(dsp_code[i]);
+ fwrite(&val,sizeof(u32),1,fp);
+ //for (j = 3; j >= 0; j--)
+ //fprintf(fp, "%c", ((u8 *) dsp_code)[i * 4 + j]);
+ }
+
+
+ if(listing)
+ fclose(listfile);
+ fclose(fp);
+ for(i=0;i<num_alloc;i++) //free mem, is this necessary, or will the kernel free it automatically?
+ free(ptralloc[i]);
+
+ return 0; //that's it were done
+}
+
+/*this function is called to open a asm file and parse it using the parse function.
+this function is called by the main function and also by the parse function
+when it encounters an "INCLUDE" directive.
+*/
+
+void asm_open(char *name)
+{
+
+ int fd,i;
+ int done=0;
+ char string[MAX_LINE_LENGTH];
+ struct stat st;
+ char *next;
+ int backup_line_num,backup_file_num;
+
+
+
+
+
+ backup_line_num=source_line_num;
+ backup_file_num=file_num;
+
+ if( (include_depth++) > max_depth){
+ printf("Error: maximum recursive include depth(%d) exceeded\n",max_depth);
+ as_exit("");
+ }
+ buff[num_alloc].name=name;
+ source_line_num=0;
+ file_num=num_alloc;
+ //open the file
+
+ if ((unsigned) (fd = open(name, O_RDONLY)) > 255){
+ as_exit("error opening input file\n");
+ }
+ //get it's stats
+ if ( -1 == fstat( fd, &st)){
+ printf("Error occured attempting to stat %s\n", name);
+ as_exit("");
+ }
+
+ if(( ptralloc[num_alloc]=(char *) malloc(st.st_size+2) )== 0){
+ printf("error allocating memory for file %s\n",name);
+ close(fd);
+ as_exit("");
+ }else{
+ buff[num_alloc].mem_start=ptralloc[num_alloc];
+
+ }
+
+ i=num_alloc;
+ num_alloc++;
+
+ buff[i].mem_end = buff[i].mem_start+st.st_size;
+
+ read(fd, buff[i].mem_start, st.st_size);
+ close(fd);
+
+#ifdef DEBUG
+ printf("File %s opened:\n",name);
+#endif
+
+ //
+ //get each line and parse it:
+ //
+ current_line=buff[i].mem_start;
+ source_line_num=1;
+ next=current_line;
+ while(next!=buff[i].mem_end){
+ while((*next!= '\n') && (next!=buff[i].mem_end) )
+ next++;
+ listtemp[0]='\0';
+ *next='\0';
+
+#ifdef DEBUG
+ printf("%s\n",current_line);
+#endif
+ if(strlen(current_line)>MAX_LINE_LENGTH)
+ as_exit("Parse error: Line exceeds allowable limit");
+ strcpy(&string[0],current_line);
+
+ done = parse(string,current_line);
+ if(listing){
+ if(done==1 &&include_depth!=1)
+ sprintf(listtemp,"Exiting included file");
+ if(done!=-3)
+ fprintf(listfile,"%-50s || %s\n",listtemp,current_line);
+ }
+
+ *next='\n';
+
+ if(done==1)
+ goto done;
+
+ if(next!=buff[i].mem_end){
+ source_line_num++;
+ next++;
+ }
+
+ current_line=next;
+ }
+
+ if(done==0)
+ printf("warning no END directive at end of file %s\n",name);
+done:
+ source_line_num=backup_line_num;
+ file_num=backup_file_num;
+
+ include_depth--;
+
+
+#ifdef DEBUG
+ printf("File %s closed:\n",name);
+#endif
+ return;
+}
+
+
+
+
+void as_exit(const char *message)
+{
+ int i;
+
+ if(macro_line_num!=0)
+ fprintf(stderr, "** Error while expanding macro at line %d\n",macro_line_num);
+
+ if(source_line_num!=0)
+ fprintf(stderr, "** %s.\n** line number %d:\n %s\nIn file: %s\n", message, source_line_num,current_line,buff[file_num].name);
+ else
+ fprintf(stderr, "** Error with file:%s\n",buff[file_num].name);
+ for(i=num_alloc-1;i>=0;i--)
+ free(ptralloc[i]);
+
+ exit(1);
+}
+
+inline void output_tram_line( struct list_head *line_head, int type){
+
+ struct tram *tram_sym;
+ struct list_head *entry;
+
+ list_for_each(entry, line_head ){
+
+ tram_sym=list_entry(entry,struct tram,tram);
+
+ if(tram_sym->type==type){
+ u32 val;
+ //printf("table read:%s,%x\n",tram_sym->data.name,tram_sym->data.address);
+ tram_sym->data.address-=TRAM_ADDR_BASE;
+ fwrite(&(tram_sym->data.address),sizeof(u8),1,fp);
+ val = __cpu_to_le32(tram_sym->data.value);
+ fwrite(&val,sizeof(u32),1,fp);
+ if(listing){
+ if(type==TYPE_TRAM_ADDR_READ)
+ fprintf(listfile,"\tRead");
+ else
+ fprintf(listfile,"\tWrite");
+
+ fprintf(listfile,": 0x3%02x/0x2%02x (%s), offset 0x%07x\n",tram_sym->data.address,tram_sym->data.address,
+ (prev_sym((&tram_sym->list)))->data.name,tram_sym->data.value);
+ }
+
+ }
+ }
+}
+
+
+//creates output header
+void header(void)
+{
+ int i;
+ struct sym *sym;
+
+ extern struct list_head sym_head;
+ struct list_head *entry;
+ if(listing)
+ fprintf(listfile,"Patch name: \"%s\"\n\n",patch_name);
+
+ //patch signature
+ //1234567890123456
+ fprintf(fp, "EMU10K1 FX8010 1");
+
+ //patchname
+ fwrite(patch_name,sizeof(char), PATCH_NAME_SIZE,fp);
+
+
+ fwrite(&gpr_input_count,sizeof(u8),1,fp);
+ //write ins/outs
+
+ if(listing)
+ fprintf(listfile,"*****************************GPR******************************\n");
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(sym->type==GPR_TYPE_INPUT){
+ sym->data.address-=GPR_BASE;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ if(listing)
+ fprintf(listfile,"%s IN: 0x%03x, OUT: 0x%03x\n",sym->data.name,sym->data.address+GPR_BASE,sym->data.address+GPR_BASE+1);
+ sym->data.address++;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ }
+ }
+
+
+ /* dynamic gprs */
+ fwrite(&gpr_dynamic_count,sizeof(u8),1,fp);
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(sym->type==GPR_TYPE_DYNAMIC) {
+ sym->data.address-=GPR_BASE;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ if(listing)
+ fprintf(listfile,"GPR Dynamic: 0x%03x(%s)\n",sym->data.address+GPR_BASE,sym->data.name);
+ }
+ }
+
+
+ /* static gprs */
+ fwrite(&gpr_static_count,sizeof(u8),1,fp);
+
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(sym->type==GPR_TYPE_STATIC){
+ u32 value;
+ sym->data.address-=GPR_BASE;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ value = __cpu_to_le32(sym->data.value);
+ fwrite(&value,sizeof(u32),1,fp);
+ if(listing)
+ fprintf(listfile,"GPR Static: 0x%03x(%s), Value:0x%08x\n",sym->data.address+GPR_BASE
+ ,sym->data.name,sym->data.value);
+ }
+
+ }
+
+ /* control gprs */
+ fwrite(&gpr_control_count,sizeof(u8),1,fp);
+
+
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(sym->type==GPR_TYPE_CONTROL){
+ u32 value;
+ sym->data.address-=GPR_BASE;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ value = __cpu_to_le32(sym->data.value);
+ fwrite(&value,sizeof(u32),1,fp);
+ value = __cpu_to_le32(((struct control *)sym)->min);
+ fwrite(&value,sizeof(u32),1,fp);
+ value = __cpu_to_le32(((struct control *)sym)->max);
+ fwrite(&value,sizeof(u32),1,fp);
+
+ fwrite(&(sym->data.name), sizeof(char), MAX_SYM_LEN, fp);
+ if(listing)
+ fprintf(listfile,"GPR Control: 0x%03x(%s), value:0x%08x, Min:0x%08x, Max:0x%08x\n",sym->data.address+GPR_BASE,sym->data.name,
+ sym->data.value,((struct control *)sym)->min,((struct control *)sym)->max);
+
+
+ }
+ }
+
+ /*constant GPRs*/
+ fwrite(&gpr_constant_count,sizeof(u8),1,fp);
+
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(sym->type==GPR_TYPE_CONSTANT){
+ sym->data.address-=GPR_BASE;
+ fwrite(&(sym->data.address),sizeof(u8),1,fp);
+ fwrite(&(sym->data.value),sizeof(u32),1,fp);
+ if(listing)
+ fprintf(listfile,"GPR Constant: 0x%03x(%s), Value:0x%08x\n",sym->data.address+0x100
+ ,sym->data.name,sym->data.value);
+ }
+ }
+
+
+ if(listing)
+ fprintf(listfile,"*****************************TRAM*****************************\n");
+
+ /*lookup-tables*/
+ fwrite(&tram_table_count,sizeof(u8),1,fp);
+
+ for(i=0;i<tram_table_count;i++){
+ u32 value;
+ value = __cpu_to_le32(tram_lookup[i].size);
+ fwrite(&value,sizeof(u32),1,fp);
+ if(listing)
+ fprintf(listfile,"Lookup-table block:%s, size:0x%08x\n",(&tram_lookup[i])->name,tram_lookup[i].size);
+ // read lines
+ fwrite(&(tram_lookup[i].read),sizeof(u8),1,fp);
+ output_tram_line(&(tram_lookup[i].tram),TYPE_TRAM_ADDR_READ);
+ //write lines
+ fwrite(&(tram_lookup[i].write),sizeof(u8),1,fp);
+ output_tram_line(&(tram_lookup[i].tram),TYPE_TRAM_ADDR_WRITE);
+ }
+
+ /*Delay Lines*/
+ fwrite(&tram_delay_count,sizeof(u8),1,fp);
+ for(i=0;i<tram_delay_count;i++){
+
+ fwrite(&(tram_delay[i].size),sizeof(u32),1,fp);
+ if(listing)
+ fprintf(listfile,"Delay-line block:%s, size:0x%08x\n",tram_delay[i].name,tram_delay[i].size);
+ // read lines
+ fwrite(&(tram_delay[i].read),sizeof(u8),1,fp);
+ output_tram_line(&(tram_delay[i].tram),TYPE_TRAM_ADDR_READ);
+
+ //write lines
+ fwrite(&(tram_delay[i].write),sizeof(u8),1,fp);
+ output_tram_line(&(tram_delay[i].tram),TYPE_TRAM_ADDR_WRITE);
+ }
+}
--- /dev/null
+/***************************************************************************
+ as10k1.h - description
+ -------------------
+ Date : May 25, 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include"types.h"
+#include"proto.h"
+
+
+#define max_depth 3 //max include nesting depth
+FILE *dc_fp;
+int include_depth=0;
+
+
+#define MAXINCLUDES 25
+
+struct list_head sym_head;
+
+struct alloc
+{
+ char *mem_start;
+ char *mem_end;
+ char *name;
+};
+
+struct alloc buff[MAXINCLUDES];
+u32 dsp_code[DSP_CODE_SIZE];
+int ip=0;
+
+int ds_addr=0x100; // DS start at 0x100 ( start of the general purpose registers).
+int tram_addr=0; // tram data/addr read/write counter
+
+struct delay tram_delay[MAX_TANK_ADDR];
+struct lookup tram_lookup[MAX_TANK_ADDR];
+
+int gpr_input_count=0;
+int gpr_output_count=0;
+int gpr_static_count=0;
+int gpr_dynamic_count=0;
+int gpr_control_count=0;
+int tram_delay_count=0;
+int tram_table_count=0;
+int gpr_constant_count=0;
+
+char patch_name[PATCH_NAME_SIZE]="NO_NAME";
+int macro_depth=0;
+
+
--- /dev/null
+/***************************************************************************
+ assemble.c - Assembles the parsed lines
+ -------------------
+ Date : May 24 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#include<string.h>
+#include<stdio.h>
+#include<stdlib.h>
+#include <ctype.h>
+
+
+#include"types.h"
+#include"proto.h"
+
+extern int dbg_opt;
+extern FILE *listfile;
+extern char *listing;
+char type_strings[GPR_TYPE_EQUATE+1][20]={
+"Input",
+"Output",
+"Constant",
+"Static",
+"Dynamic",
+"Control",
+"Tram Data Reg",
+"Tram Address/Read",
+"Tram Address/Write",
+"Macro arg",
+"Equate"
+};
+
+void op(int op, int z,int w,int x,int y)
+{
+ int w0, w1;
+ extern int dsp_code[DSP_CODE_SIZE];
+ extern int ip;
+ extern char op_codes[35][9];
+ extern char listtemp[60];
+ if (ip >= 0x200)
+ as_exit("to many instructions");
+ if (op >= 0x10 || op < 0x00)
+ as_exit("illegal op code");
+
+ //check if gpr is valid, optional do additional modifications
+ z=declared(z,1);
+ declared(w,2);
+ declared(x,3);
+ declared(y,4);
+
+ if ( (dbg_opt & DBG_INSTR) !=0 )
+ printf( "0x%03x\t%s(%d) \t0x%03x,0x%03x,0x%03x,0x%03x\n",2*ip,op_codes[op],op,z,w,x,y);
+ if(listing)
+ sprintf(listtemp, "0x%03x %-9s(%02d) 0x%03x,0x%03x,0x%03x,0x%03x",2*ip,op_codes[op],op,z,w,x,y);
+
+ w0 = (x << 10) | y;
+ w1 = (op << 20) | (z << 10) | w;
+ dsp_code[ip * 2] = w0;
+ dsp_code[ip * 2 + 1] = w1;
+ ip++;
+
+}
+
+int declared(int operand,int i){
+
+ struct sym *sym;
+ extern struct list_head sym_head;
+ struct list_head *entry;
+
+
+
+ if ((operand < 0x040)||(operand >= 0x400)){
+ printf("** Assembler Error with Operand %d:0x%x\n",i,operand);
+ as_exit("Operand has value out of range");
+ }
+
+ if((operand < 0x400) && operand >= 0x100)
+ {
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if( (sym->data.address == operand ) && sym->type!=GPR_TYPE_EQUATE){
+ if( ( sym->type==GPR_TYPE_CONSTANT) && (i==1) ){
+ printf("** Assembler Error with Operand %d:0x%x\n",i,operand);
+ as_exit("** Error: Destination register is a read-only constant");
+ }
+
+ else if(sym->type!=GPR_TYPE_INPUT)
+ return(operand);
+ else
+ return( i==1? operand + 1 : operand);
+ }
+ }
+
+
+ }
+ else if(operand<0x100)
+ return(operand);
+
+ printf("** Assembler Error with Operand %d:0x%x\n",i,operand);
+ as_exit("Operand address is undeclared");
+ return(0);
+}
+
+//each operand will be something like : , sym1 + sym2 * sym3 ,
+//we will recursively decode each symbol and perform proper operations:
+int arg_decode(char *operand, int prev_val)
+{
+ int value;
+ char oper='0';
+
+
+ //Nothing:
+ if(operand==NULL)
+ as_exit("Parse Error: missing operand(s)");
+
+
+ if(*operand==','||*operand=='\n'||*operand=='\0')
+ return(prev_val);
+
+
+ //skip over leading blanks(if any):
+ advance_over_whites(operand);
+
+ if(*operand==','||*operand=='\n' ||*operand=='\0')
+ return(prev_val);
+
+ //get the operator:
+ if(*operand=='+' || *operand=='-' || *operand=='/' || *operand== '*'){
+ oper=*operand;
+ operand++;
+ }
+
+ //skip over any blanks after the oper
+ advance_over_whites(operand);
+
+ //decode the symbol/value:
+ value=arg_decode2(operand);
+
+ //advance to next symbol
+ while( *operand!='+' && *operand!='-' && *operand!='/' && *operand!= '*' && *operand != '\0' &&*operand!=',' &&*operand!='\n')
+ operand++;
+
+ switch (oper){
+
+ case '+':
+ return(arg_decode(operand,prev_val+value));
+ case '-':
+ return(arg_decode(operand,prev_val-value));
+ case '/':
+ return(arg_decode(operand,prev_val/value));
+ case '*':
+ return(arg_decode(operand,prev_val*value));
+ default:
+ return(arg_decode(operand,value));
+
+ }
+
+}
+
+//this function does argument decoding
+int arg_decode2(char *operand)
+{
+ extern int ip,ds_addr;
+ extern unsigned int macro_depth;
+ struct sym *sym;
+ extern struct list_head sym_head;
+ struct list_head *entry;
+ //printf("operand:%s\n",operand);
+
+
+ if(operand[0]=='.' &&isalpha(operand[1])){
+ add_symbol(operand,GPR_TYPE_STATIC, ds_addr++, -(long)ip);
+ return(ds_addr-1);
+ }
+
+
+ // Hex
+ if((char)(*operand)=='$')
+ return((int)strtol(operand+1,NULL,16));
+ // Octal
+ if((char)(*operand)=='@')
+ return((int)strtol(operand+1,NULL,8));
+ // Binary:
+ if((char)(*operand)=='%')
+ return((int)strtol(operand+1,NULL,2));
+ // Decimal:
+ if( (operand[0] >= '0' && operand[0] <='9') ||operand[0]=='-')
+ return((int)strtol(operand,NULL,10));
+
+
+
+ //Symbol:
+ list_for_each(entry,&sym_head){
+ sym=list_entry(entry,struct sym,list);
+ if(symcmp(sym->data.name,operand)==0){
+ if(sym->type!=TYPE_MACRO_ARG)
+ return(sym->data.address);
+ else if(sym->data.value==(macro_depth))
+ return(sym->data.address);
+
+ }
+ }
+
+
+
+ printf("Parse error with operand: \"");
+ while(!symend(operand))
+ printf("%c",*(operand++));
+ printf("\"\n");
+ as_exit("Bad operand");
+
+ //printf("** Parse error with operand: \"%s\"\n",operand);
+ as_exit("\"\nOperand isn't a defined symbol or value");
+ return(0);
+}
+
+
+#define FACTOR 0x7fffffff
+#define SAMP_FREQ 48000
+//used by the DC operation to get a long int:
+long arg2long(char *operand){
+
+
+ //Nothing:
+ if(operand==NULL)
+ as_exit("Parse Error: missing operand(s)");
+
+ advance(operand);
+
+ //Fractional ( -1 <= operand <= 1 )
+ if(operand[0]=='#')
+ return((long)(atof(operand+1)*FACTOR));
+ // Time value
+ if(operand[0]=='&')
+ return((long)(atof(operand+1)*48000));
+ // Hex:
+ if((char)(*operand)=='$')
+ return(strtoul(operand+1,NULL,16));
+ // Binary:
+ if((char)(*operand)=='%')
+ return(strtoul(operand+1,NULL,2));
+ // Octal:
+ if((char)(*operand)=='@')
+ return(strtoul(operand+1,NULL,8));
+ // Decimal:
+ if( (operand[0] >= '0' && operand[0] <='9') || operand[0]=='-' || operand[0]=='.'){
+ if(atof(operand)<1 && atof(operand)>-1)
+ return((long)(atof(operand)*FACTOR));
+ else
+ return(strtol(operand,NULL,10));
+ }
+
+
+ printf("Parse error with operand:\"%s\"\n",operand);
+ // while(!symend(operand))
+ // printf("%c",*operand);
+ //printf("\"\n");
+ as_exit("Bad operand");
+
+ return(0);
+}
+void update_symbol(char *name,u16 type,u16 address,u32 value){
+ struct sym *sym;
+
+
+ switch(type){
+
+ case TYPE_MACRO_ARG:
+
+ if( issymbol(name,&sym) == -1 ){
+ add_symbol(name,type,address,value);
+ return;
+ }
+
+ if(sym->type!=TYPE_MACRO_ARG){
+ printf("Error: with argument:%s",name);
+ as_exit("Error:symbol is already defined");
+ }
+ sym->data.address=address;
+ break;
+ default:
+ if( issymbol(name,&sym) == -1 ){
+ add_symbol(name,type,address,value);
+ return;
+ }
+ break;
+ }
+
+}
+
+
+
+
+void add_symbol(char *name, u16 type, u16 address, u32 value)
+{
+
+ extern int gpr_input_count,gpr_output_count,gpr_static_count,gpr_dynamic_count,gpr_control_count,gpr_constant_count;
+ struct sym *sym;
+ struct tram *tmp_ptr;
+ extern struct list_head sym_head;
+ extern struct delay tram_delay[MAX_TANK_ADDR];
+ extern struct lookup tram_lookup[MAX_TANK_ADDR];
+ int tmp;
+
+
+ if(name==NULL)
+ as_exit("Parse Error: This directive requires a label");
+
+ if(symcmp(name,NO_SYM)!=0 &&type== GPR_TYPE_CONSTANT){
+ if(issymbol(name,&sym)==0){
+ if(sym->data.value != value)
+ as_exit("Error: Constant redeclared as another value");
+ else
+
+ return;
+ }
+ }
+
+
+ if(symcmp(name,NO_SYM)!=0 && type!=TYPE_MACRO_ARG)
+ {
+ if(issymbol(name,&sym)!=-1)
+ as_exit("Parse Error: Symbol is already defined");
+ if(ismacro(name)!=-1)
+ as_exit("Parse Error: Symbol is already defined as a macro");
+ if(isalpha(*name)==0 && name[0]!='.')
+ as_exit("Parse Error: Symbol must start with a alpha character (a-z)");
+ }
+
+ switch(type){
+ case GPR_TYPE_CONTROL:
+ sym=(struct sym *)malloc(sizeof(struct control));
+ list_add_tail(&sym->list, &sym_head);
+ break;
+ case TYPE_TRAM_ADDR_READ:
+ case TYPE_TRAM_ADDR_WRITE:
+ sym=(struct sym *)malloc(sizeof(struct tram));
+ list_add_tail(&sym->list, &sym_head);
+
+ //if ID is that of a delay:
+ if((tmp=((struct sym * ) sym->list.prev)->data.value)>0xff){
+ tmp=tmp-0x100;
+ list_add_tail(&(((struct tram *)sym)->tram) , &(tram_delay[tmp].tram) );
+ if(type== TYPE_TRAM_ADDR_READ)
+ tram_delay[tmp].read++;
+ else
+ tram_delay[tmp].write++;
+ }else{
+ tmp_ptr=(struct tram *)sym;
+ list_add_tail(&(((struct tram *)sym)->tram) , &(tram_lookup[tmp].tram) );
+ tmp_ptr=(struct tram *)sym;
+ if(type== TYPE_TRAM_ADDR_READ)
+ tram_lookup[tmp].read++;
+ else
+ tram_lookup[tmp].write++;
+ }
+ break;
+ default:
+
+ sym=(struct sym *)malloc(sizeof(struct sym));
+ list_add_tail(&sym->list, &sym_head);
+
+ }
+
+
+
+ symcpy(sym->data.name,name);
+ sym->data.address=address;
+ sym->type=type;
+ sym->data.value=value;
+ //GPR debugging:
+ if((dbg_opt&DBG_GPR) && type<=GPR_TYPE_CONTROL)
+ printf("GPR: %-16s 0x%03x Value=0x%08x, Type: %s\n",name,address,value,type_strings[type] );
+
+ //tram debugging:
+ else if((dbg_opt&DBG_TRAM && type == TYPE_TRAM_DATA))
+ printf("TRAM Access: %-16s",name);
+ else if((dbg_opt&DBG_TRAM && type == TYPE_TRAM_ADDR_WRITE))
+ printf(", type: Write, using 0x%03x/0x%03x, offset:0x%07x",address,address-0x100,value );
+ else if((dbg_opt&DBG_TRAM && type == TYPE_TRAM_ADDR_READ))
+ printf(", type: Read, using 0x%03x/0x%03x, offset:0x%07x",address,address-0x100,value );
+ //General Symbol debugging:
+ else if((dbg_opt&DBG_SYM )){
+ printf("symbol: %-16s 0x%03x Type: %s\n",name,address,type_strings[type]);
+ }
+
+
+ switch(type){
+ case TYPE_MACRO_ARG:
+ return;
+ case GPR_TYPE_INPUT:
+ gpr_input_count++;
+ return;
+ case GPR_TYPE_OUTPUT:
+ gpr_output_count++;
+ return;
+ case GPR_TYPE_STATIC:
+ gpr_static_count++;
+ return;
+ case GPR_TYPE_DYNAMIC:
+ gpr_dynamic_count++;
+ return;
+ case GPR_TYPE_CONTROL:
+ gpr_control_count++;
+ return;
+ case GPR_TYPE_CONSTANT:
+ gpr_constant_count++;
+ return;
+ default:
+ return;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+AC_INIT(as10k1.c)
+AM_INIT_AUTOMAKE(as10k1, A0.99)
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_HEADER_STDC
+CFLAGS="$CFLAGS"
+LDFLAGS="$LDFLAGS"
+
+AC_OUTPUT(Makefile)
--- /dev/null
+#!/bin/bash
+
+if test "x$AUTOMAKE_DIR" = "x"; then
+ if test -d /usr/local/share/automake; then
+ AUTOMAKE_DIR=/usr/local/share/automake
+ fi
+ if test -d /usr/share/automake; then
+ AUTOMAKE_DIR="/usr/share/automake"
+ fi
+fi
+
+for f in install-sh mkinstalldirs missing; do
+ cp -av $AUTOMAKE_DIR/$f .
+done
+
+aclocal $ACLOCAL_FLAGS
+automake --foreign --add-missing
+autoconf
+export CFLAGS='-O2 -Wall -pipe -g'
+echo "CFLAGS=$CFLAGS"
+echo "./configure $@"
+./configure $@
+unset CFLAGS
+make
--- /dev/null
+TARGETS = blank.emu10k1 chorus.emu10k1 delay.emu10k1 eq2.emu10k1 eq5.emu10k1 \
+ fir.emu10k1 flanger.emu10k1 sine.emu10k1 tremolo.emu10k1 vibrato.emu10k1 \
+ vol_ctrl.emu10k1
+
+%.emu10k1: %.asm
+ ../as10k1 $<
+
+all: $(TARGETS)
+
+clean:
+ rm -f *~ *.emu10k1
\ No newline at end of file
--- /dev/null
+;;; A blank file for clearing programs from the emu10k1
+
+ end
\ No newline at end of file
--- /dev/null
+;;; Simple Chorus
+;;; Author:Daniel Bertrand
+;;; Date: Oct 12, 2000
+
+;;; 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.
+
+;;; References:
+;;; http://www.harmony-central.com/Effects/Articles/Chorus
+
+
+;;; speed(formerly "delta")=2*pi*freq/48000
+;;; this give us our delta value for a specific freq (0.1-0.3Hz is good)
+
+
+ include "emu_constants.asm"
+ name "Chorus"
+
+in IO
+out equ in
+
+
+
+speed control 4e-05 , 0 , 1e-4 ; Controls frequency (radians)
+delay control &40e-3 ,&10e-3 , &80e-3; twice (2*) average delay (sec)
+width control #0.3 ,0 ,0.5 ; width control
+mix control #1 ,0 ,#1 ; forward mix
+
+;; sine generator storage spaces:
+sinx sta 0
+cosx sta #0.5
+
+tmp dyn
+tmp2 dyn
+
+;;; Two Delay Lines:
+
+
+dly delay &80e-3 ;10msec delay line
+
+write twrite dly,0 ; tram writes
+ready tread dly,0 ; tram reads
+reada tread dly,0
+
+;;;The code:
+
+
+;;; two opcode sinewave generator (I love this chip!):
+ macs sinx,sinx,speed,cosx
+ macs1 cosx,cosx,speed,sinx
+
+;;; 0.5Asint+0.5:
+ macs tmp,C_2^30,sinx,width
+
+;;; calculate address:
+ macs ready.a,write.a,delay,tmp
+
+;second addresses for interpolation:
+;(interesting how the emu engineers decided that $800 wasn't a needed value)
+ macints reada.a,ready.a,C_8,C_256
+
+
+;;; Write to the delay line:
+
+ macs write,C_0,in,C_2^29
+
+
+;;; output values:
+;;; 0x55 is 00100000 (?)
+ macints tmp,C_0,reada.a,C_LSshift; get least significant part of address
+
+ interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings
+
+ macs out,in,tmp2,mix
+
+
+
+
+
+ end
+
+
+
+
+
--- /dev/null
+;;; A simple delay routine
+
+ include "emu_constants.asm"
+ name "delay"
+
+
+level control 0.5, #0 , #1
+feedback control #0.3, #0 , #1
+delay control &0.2, &0, &0.5
+
+io IO
+
+dly delay &0.5 ; 0.5 sec delay block
+
+write twrite dly,0 ; write at 0 sec
+read tread dly,&.2 ; read at 0.2 sec
+
+
+ acc3 read.a,delay,write.a,C_0
+
+
+ macs io,io,level,read
+ macs write,io,read,feedback
+
+ end
+
+
+
+
--- /dev/null
+;some hardware constants C_[n]<DecimalValue>, 'n' indicates negative value
+;
+;these are in 2's complement representation
+
+C_0 equ $040 ;;00000000
+C_1 equ $041 ;;00000001
+C_2 equ $042 ;;00000002
+C_3 equ $043 ;;00000003
+C_4 equ $044 ;;00000004
+C_8 equ $045 ;;00000008
+C_16 equ $046 ;;00000010
+C_32 equ $047 ;;00000020
+C_256 equ $048 ;;00000100
+C_65536 equ $049 ;;00010000
+C_2^23 equ $04A ;;00080000
+C_2^28 equ $04b ;;10000000
+C_2^29 equ $04c ;;20000000 (C_max /4) +1
+C_2^30 equ $04d ;;40000000 ( C_max / 2 ) + 1 (almost half)
+C_nmax equ $04e ;;80000000 most negative number
+C_max equ $04f ;;7fffffff most positive number
+C_n1 equ $050 ;;ffffffff -1
+C_n2 equ $051 ;;fffffffe -2
+C_n2^30 equ $052 ;;c0000000 C_nmax /2
+
+C_LSshift equ $55 ;;to left shift an address by using macsints
+ ;;for fractional addresses
+
+
+ZERO equ C_0;
+ONE equ C_1;
+
+;;; Hardware Registers:
+
+ACCUM equ $56
+CCR equ $57
+NOISE1 equ $58
+NOISE2 equ $59
+IRQ equ $5A
+DBAC equ $5B
+
+and macro dest,srcA,srcB
+ andxor dest,srcA,srcB,C_0
+ endm
+
+xor macro dest,srcA,srcB
+ andxor dest,C_n1,srcA,srcB
+ endm
+
+not macro dest,src
+ andxor dest,src,C_n1,C_n1
+ endm
+
+nand macro dest,srcA,srcB
+ andxor dest,srcA,srcB,C_n1
+ endm
+
+or macro dest,srcA,srcB
+ not C_0,srcA
+ andxor dest,ACCUM,srcA,srcB
+ endm
+
+nor macro dest,srcA,scrB
+ not dest,srcA
+ andxor dest,srcB,dest,srcA
+ not dest,dest
+ endm
+
+
+neg macro dest,src
+ macs1 dest,C_0,C_1,C_nmax
+ endm
+
+;;; branch on:
+;;; ==0
+beq macro count
+ skip CCR,CCR,C_8,count
+ endm
+;;; !=0
+bne macro count
+ skip CCR,CCR,C_256,count
+ endm
+;;; <0
+blt macro count
+ skip CCR,CCR,C_4,count
+ endm
+;;; always branch
+bra macro count
+ skip C_0,C_max,C_max,count
+ endm
+;;; on saturation
+bsa macro count
+ skip CCR,CCR,C_16,count
+ endm
+bge macro count
+C___80 con $80
+ skip CCR,CCR,C___80,count
+ endm
+
+bgt macro count
+C___180 con $180
+ skip CCR,CCR,C___180,count
+ endm
+
+move macro dest,src
+ macs dest,src,C_0,C_0
+ endm
+
+ end
+
+;;; usefull for testing values before a skip
+test macro test
+ macs C_0,test,C_0,C_0
+ endm
+
+cmp macro src1.scr2
+ macints C_0,src1,C_n1,src2
+ endm
--- /dev/null
+;;; Bass and Treble Effect
+;;; By: Daniel Bertrand
+;;; Date: Dec 19th,200
+;;; License: GPL v2
+;;;
+ name "Eq2"
+ include "emu_constants.asm"
+
+;;; a and b coefs for bass:
+b_b con 2.736129417e-01 5.240710533e-01 2.620355267e-01
+a_b con 9.560258858e-01 -4.576868881e-01
+
+;;; a and b coef for treble:
+b_t con -4.982305773e-01 9.964611547e-01 -4.982305773e-01
+a_t con 9.317583774e-01 -4.356836381e-01
+
+scalein con 2.449e-05, 1.157407407e-04
+scaleout con 128, 16192
+
+bass control 0.25,#0,#1
+treble control 0.25,#0,#1
+
+in IO
+out equ in
+
+tmp dyn
+tmpout dyn
+
+dly_b sta 0,0
+dly_t sta 0,0
+
+
+ ;;; bass filter(iir):
+
+ macw tmp, C_0, dly_b+1, a_b+1
+ macw tmp, tmp, dly_b , a_b
+ macw tmp,tmp,in,scalein
+ macints tmp, C_0, tmp, C_2
+
+ macs C_0,C_0,C_0,C_0
+
+ macmv dly_b+1,dly_b, dly_b+1, b_b+2
+ macmv dly_b,tmp, dly_b, b_b+1
+ macw tmp,ACCUM, tmp, b_b
+
+
+ macs tmp,C_0,bass,tmp
+ macints tmpout,C_0,tmp,scaleout
+
+;;; treble
+
+
+ macw tmp, C_0, dly_t+1, a_t+1
+ macw tmp, tmp, dly_t , a_t
+ macw tmp, tmp, in,scalein+1
+ macints tmp,C_0,tmp,C_2
+
+ macs C_0,C_0,C_0,C_0
+
+ macmv dly_t+1,dly_t, dly_t+1, b_t+2
+ macmv dly_t,tmp, dly_t, b_t+1
+ macw tmp,ACCUM, tmp, b_t
+
+ macs tmp,C_0,treble,tmp
+ macints out,tmpout,tmp,scaleout+1
+
+
+ end
+
--- /dev/null
+ name "5 band EQ"
+ include "emu_constants.asm"
+
+
+c0 con -0.98485626 0.98502633 0.99034926 -0.99034926
+c1 con -0.95169465 0.95337028 0.93878619 -0.93878619
+c2 con -0.84376963 0.85967945 0.84174451 -0.84174451
+c3 con -0.47720462 0.61368058 0.73503304 -0.73503304
+c4 con -0.28987550 0.11999291 0.72670869 -0.72670869
+
+scalein sta 0.00013665 0.00134590 0.01265823 0.10000000 0.50000000
+scaleout sta 420.00000000 140.00000000 50.00000000 20.00000000 10.00000000
+
+in io
+out equ in
+
+F_100Hz control #0.2,0,#1
+F_316Hz control #0.1,0,#1
+F_1000Hz control #0.1,0,#1
+F_3160Hz control #0.1,0,#1
+F_10000Hz control #0.2,0,#1
+
+dly0 sta 0 0
+dly1 sta 0 0
+dly2 sta 0 0
+dly3 sta 0 0
+dly4 sta 0 0
+
+out_tmp dyn
+tmp2 dyn
+tmp dyn
+
+;;; Band Pass Filter Macro:
+BPF macro OUT , IN , DELAY , COEF , SCALEIN , SCALEOUT , FOO , GAIN
+ macs tmp,C_0,SCALEIN,IN
+ macs1 tmp,tmp,DELAY,FOO
+ macw1 tmp,tmp,DELAY,COEF
+ macw1 tmp,tmp,DELAY+1,COEF+1
+ macs tmp2,C_0,DELAY+1,COEF+3
+ macs DELAY+1,DELAY,C_0,C_0
+ macs tmp2,tmp2,tmp,COEF+2
+ macs DELAY,tmp,C_0,C_0
+ macints tmp2,C_0,tmp2,SCALEOUT
+ macs OUT,OUT,tmp2,GAIN
+ endm
+
+
+ macs out_tmp,C_0,C_0,C_0
+ BPF out_tmp,in,dly0,c0,scalein,scaleout,C_nmax,F_100Hz
+ BPF out_tmp,in,dly1,c1,scalein+1,scaleout+1,C_nmax,F_316Hz
+ BPF out_tmp,in,dly2,c2,scalein+2,scaleout+2,C_nmax,F_1000Hz
+ BPF out_tmp,in,dly3,c3,scalein+3,scaleout+3,C_nmax,F_3160Hz
+ BPF out_tmp,in,dly4,c4,scalein+4,scaleout+4,C_0,F_10000Hz
+ macs out,out_tmp,C_0,C_0
+
+
+ end
+
+
+
--- /dev/null
+;;; low pass filter with cut off at 0.004pi (96Hz)
+ name "trebass"
+
+ include "emu_constants.asm"
+
+coef con 0.038684406 0.058115275 0.113007075 0.194116501 0.287525429 0.377072924 0.447195555 0.485671998 0.485783252 0.447503000 0.377505237 0.287987288 0.194517783 0.113292922 0.058289230 0.038818213
+
+
+
+n equ 15 ; filter order
+
+in io
+out equ in
+bass control 0,0,#1
+delay sta 0,0,0,0,0 ,0,0,0,0,0 ,0,0,0,0,0 ,0
+tmp dyn
+
+ macints delay,in,C_0,C_0
+
+;;;our filter for the left channel
+
+ macs C_0,C_0,C_0,C_0
+ for i = n : 1
+ macmv delay+i,delay+i-1,delay+i,coef+i
+ endfor
+
+ macs tmp,ACCUM,delay,coef
+
+ macs1 out,in,tmp,bass
+
+ end
+
+
+
+
+
+
+
+
--- /dev/null
+;;; Simple mono flanger
+;;; Author:Daniel Bertrand
+;;; Date: May 29,2000
+
+;;; 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.
+
+;;; References:
+;;; http://www.harmony-central.com/Effects/Articles/Flanging/
+
+;;; speed( formerly "delta")=2*pi*freq/48000
+;;; this give us our delta value for a specific freq (0.1-0.3Hz is good)
+
+
+ include "emu_constants.asm"
+ name "flanger"
+
+in IO
+out equ in
+
+
+
+speed control 2e-05 , 0 , 1e-4 ; Controls frequency (radians)
+delay control &7e-3 ,$1600 , 20e-3 ; twice (2*) average delay (sec)
+width control #0.33 ,0 ,0.5 ; width control
+forward control #1 ,0 ,#1 ; forward mix
+feedback control 0.3 ,0 ,0.5 ; feedback level
+
+;; sine generator storage spaces:
+sinx sta 0
+cosx sta #0.5
+
+tmp dyn
+tmp2 dyn
+
+;;; Two Delay Lines:
+
+
+dly delay &20e-3 ;20msec delay line
+
+write twrite dly,0 ; tram writes
+ready tread dly,0 ; tram reads
+reada tread dly,0
+
+;;;The code:
+
+
+;;; two opcode sinewave generator (I love this chip!):
+ macs sinx,sinx,speed,cosx
+ macs1 cosx,cosx,speed,sinx
+
+;;; 0.5Asint+0.5:
+ macs tmp,C_2^30,sinx,width
+
+;;; calculate address:
+ macs ready.a,write.a,delay,tmp
+
+;second addresses for interpolation:
+;(interesting how the emu engineers decided that $800 wasn't a needed value)
+ macints reada.a,ready.a,C_8,C_256
+
+
+;;; output values:
+;;; 0x55 is 00100000 (?)
+ macints tmp,C_0,reada.a,C_LSshift; get least significant part of address
+
+ interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings
+ macs out,in,tmp2,forward
+
+
+;;; feedback and write to the delay line:
+
+ macs write,in,tmp2,feedback
+
+
+ end
+
+
+
+
+
--- /dev/null
+ name "Sine wave Gen"
+ include "emu_constants.asm"
+
+in io
+out equ in
+
+
+delta control $3afa691,0,$7fffffff ; controls frequency
+
+
+cosx control #1,0,#1 ; amplitude of sinewave
+sinx sta 0
+
+
+
+ macs sinx,sinx,delta,cosx
+ macs1 cosx,cosx,delta,sinx
+ macmv out,cosx,C_0,C_0
+
+
+ end
+
+
+
+
+
+
+
+
--- /dev/null
+;;; Tremolo Effect
+;;; By: Daniel Bertrand
+;;; Oct 29, 2000
+
+ include "emu_constants.asm"
+ name "tremolo"
+
+in IO
+out equ in
+
+
+;;; sinewave generator:
+delta control 10e-4,0,1e-2 ; controls frequency (2*pi*freq/48000)
+cosx sta #0.5
+sinx sta 0
+depth control &0.001,0,&0.001
+
+
+tmp dyn
+
+delay delay &0.01
+wrt twrite delay,0
+rd tread delay,0
+rd2 tread delay,0
+c1000 sta $1000
+
+ macs wrt,in,C_0,C_0
+;;; sinwave generator:
+ macs sinx,sinx,delta,cosx
+ macs1 cosx,cosx,delta,sinx
+
+;;; calulate address = depth*sin(wt)+0.5*depth
+
+
+ macs tmp,c1000,depth,C_2^30
+ macs tmp,tmp,sinx,depth
+ acc3 rd.a,tmp,C_0,wrt.a
+
+ macints rd2.a,rd.a,C_8,C_256 ;;;next address
+
+;;; get fractional address:
+ macints tmp,C_0,rd.a,C_LSshift
+;;; linear interpolate fraction between the 2 reads
+;;; output result
+
+
+ interp out,rd,tmp,rd2
+
+
+ end
+
--- /dev/null
+;;; written by: Daniel Bertrand <d.bertrand@ieee.ca>
+
+ include "emu_constants.asm"
+ name "Vibro Effect"
+
+in io
+out equ in
+
+
+
+;;; sinewave generator:
+delta control 1.5e-3,0,1e-2 ; controls frequency (2*pi*freq/48000)
+cosx sta #0.5
+sinx sta 0
+depth control #1,0,#1
+sin2 dyn 1
+
+
+ macs sinx,sinx,delta,cosx
+ macs1 cosx,cosx,delta,sinx
+;; depth control (and add 0.5 DC offset):
+ macs sin2,C_2^30,sinx,depth
+
+;;; multiply signals by sinewave
+ macs out,C_0,in,sin2
+ end
+
+
+
+
+
--- /dev/null
+ name "hw vol ctrl"
+
+ include "emu_constants.asm"
+Vol_ctrl control #1,0,#1
+
+in IO
+out equ in
+ macs out,C_0,in,Vol_ctrl
+ end
+
+
+
+
--- /dev/null
+/* From linux kernel source */
+
+
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD(name) \
+ struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/*
+ * Insert a new entry before the specified head..
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#endif
--- /dev/null
+/***************************************************************************
+ macro.c - various functions to handle macros
+ -------------------
+ Date : May 23 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include<string.h>
+#include<stdio.h>
+#include"types.h"
+#include"proto.h"
+#include <ctype.h>
+
+int macro_ctn;
+struct macrdef macro[MAX_DEF_MACRO];
+extern char *listing,listtemp[60];
+extern FILE *listfile;
+
+//determines if an opcode neumonic is a macro
+
+int ismacro(char *mac)
+{
+
+ int i;
+
+ for(i=0;i<macro_ctn; i++){
+ if(strcasecmp(macro[i].name,mac)==0){
+ return(i);
+ }
+ }
+ return(-1);
+}
+
+//defines a new macro, adds it to the macro list
+void new_macro(char *symbol, char *line, char *operand)
+{
+ extern int source_line_num;
+ struct sym *sym;
+ if(isalpha(*symbol)==0)
+ as_exit("Parse Error: Symbol must start with an alpha character");
+
+ if(ismacro(symbol)!=-1)
+ as_exit("Parsed Error: macro is already defined");
+
+ if(issymbol(symbol,&sym)!=-1)
+ as_exit("Parse Error: Symbol is already defined");
+
+ macro[macro_ctn].line_num=source_line_num;
+ macro[macro_ctn].ptr=line;
+ strcpy(macro[macro_ctn].name,symbol);
+ macro[macro_ctn].operands=operand;
+ macro_ctn++;
+
+}
+
+//called from parsed() when a macro is used, stores the arguments and recursively calls the parse().
+
+void macro_expand(int macnum,char *operand )
+{
+ char *line,*next;
+ int done=0,i,old;
+ extern unsigned int macro_depth;
+ extern int macro_line_num;
+ char string[MAX_LINE_LENGTH];
+
+ //initialize macro use:
+ i=0;
+
+ if(macro_depth+1> MAX_MAC_DEPTH)
+ as_exit("Error exceeded maximum number of recursive macro calls");
+
+ old=macro_line_num;
+ macro_line_num=macro[macnum].line_num;
+ macro_operand(macro[macnum].operands,operand);
+ macro_depth++;
+
+ line=macro[macnum].ptr;
+ next=line;
+
+
+ while((*next!= '\n') ) //skip to the line after the macro definition
+ next++;
+ line=next;
+
+
+ //Expand the macro calling parse()
+
+ while(done!=-1)
+ {
+
+ while((*next!= '\n') )
+ next++;
+
+ *next='\0';
+
+ strcpy(&string[0],line);
+ listtemp[0]='\0';
+ done=parse(string, line);
+ macro_line_num++;
+ *next='\n';
+ if(listing){
+ if(done==1)
+ sprintf(listtemp,"macro expansion done");
+ if(done!=-3)
+ fprintf(listfile,"%-50s || %s\n",listtemp,line);
+ }
+ if(done==-1)
+ break;
+ next++;
+ line=next;
+ }
+ macro_line_num=old;
+ macro_depth--;
+
+ return;
+
+}
+//assigns calling arguments with defined symbols.
+void macro_operand(char *symbols,char *val)
+{
+ char tmp[MAX_LINE_LENGTH],*ptr=symbols,*sym=tmp,*next_sym=sym,*next_val=val;
+ extern unsigned int macro_depth;
+
+
+ if(symbols==NULL&&val==NULL)
+ return;
+ if(symbols==NULL||val==NULL)
+ as_exit("error in macro_operand, Null operand list");
+
+
+ while(*ptr!='\n' && *ptr!=';')
+ ptr++;
+ *ptr='\0';
+
+ strcpy(tmp,symbols);
+
+ //#ifdef DEBUG
+ // printf("syms:\"%s\",vals:\"%s\"\n",sym,val);
+ //#endif
+ *ptr='\n';
+
+ while(1){
+
+ //skip over blanks:
+ advance(next_sym);
+ advance(next_val);
+
+
+ sym = next_sym;
+ val = next_val;
+
+ if(*next_val=='\0' && *next_sym=='\0')
+ return;
+ if(*next_sym=='\0')
+ as_exit("Error, To many arguments for defined Macro");
+
+
+ if(*next_val=='\0')
+ as_exit("Error, Not enough arguments for defined macro");
+
+
+
+ while(*next_sym != '\0' && *next_sym!= ',' )
+ next_sym++;
+
+ while(*next_val != '\0' && *next_val!= ',' )
+ next_val++;
+ // printf("sym=\"%s\";val=\"%s\"(=0x%x)\n",sym, val,arg_decode(val,0) );
+ if( sym!=next_sym || val!=next_val ){
+ update_symbol(sym,TYPE_MACRO_ARG,arg_decode(val,0),macro_depth+1);
+ }
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+EMU10K1 patch binary file format (.emu10k1)
+-------------------------------------------
+
+Notice: this format is a bit different from the original as10k1 assembler.
+
+16 bytes signature 'EMU10K1 FX8010 1' ; last number means the patch version
+32 bytes name ; ASCIIZ patch name
+1 byte count of input/output GPRS
+? bytes input/output GPRS
+1 byte count of dynamic GPRS
+? bytes dynamic GPRS
+1 byte count of static GPRS
+? pairs
+ 1 byte static GPRS
+ 1 dword (little-endian, 32-bit) value
+1 byte count of control GPRS
+? entries
+ 1 byte control GPRS
+ 1 dword (little-endian, 32-bit) value
+ 1 dword (little-endian, 32-bit) range - min
+ 1 dword (little-endian, 32-bit) range - max
+ 32 bytes symbol name ; ASCIIZ symbol name
+1 byte count of constant GPRS
+? pairs
+ 1 byte constant GPRS
+ 1 dword (little-endian, 32-bit) value
+1 byte count of TRAM lookup tables
+? entries
+ 1 dword (little-endian, 32-bit) size
+ 1 byte count of read lines
+ ? pairs
+ 1 char address of the TRAM line
+ 1 dword (little-endian, 32-bit) size in samples
+ 1 byte count of write lines
+ ? pairs
+ 1 char address of the TRAM line
+ 1 dword (little-endian, 32-bit) size in samples
+1 byte count of TRAM delay tables
+? entries
+ 1 dword (little-endian, 32-bit) size
+ 1 byte count of read lines
+ ? pairs
+ 1 char address of the TRAM line
+ 1 dword (little-endian, 32-bit) size in samples
+ 1 byte count of write lines
+ ? pairs
+ 1 char address of the TRAM line
+ 1 dword (little-endian, 32-bit) size in samples
+2 word (little-endian, 16-bit), count of 64-bit instructions
+? double-dwords (little-endian, 64-bit) instruction
--- /dev/null
+/***************************************************************************
+ parse.c - parses each line, stores in temp space
+ -------------------
+ Date : May 23 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include<string.h>
+#include<stdio.h>
+#include"types.h"
+#include"parse.h"
+#include"proto.h"
+
+/*
+This function parses the asm file calling appropriate functions to blow up macros, include files,
+define constants, keep track of equates, and handling assembler directives.
+
+This function is called on a line by line basis.
+
+normally returns value 0 except when "end" directive is encountered in which case it returns 1,
+ the "endm" directive which return -1, or the "endfor" deirective which returns -2
+*/
+
+extern char type_strings[GPR_TYPE_EQUATE+1][20];
+extern int dbg_opt;
+extern char *listing,listtemp[60];
+extern FILE *listfile;
+
+int parse( char line_string[MAX_LINE_LENGTH], char *line)
+{
+ int tmp,i,arg[4];
+ static int defmacro=0; //set to 0 unless we're in a macro definition
+ int op_num;
+ char *leading_symbol=NULL, *op_name_ptr,*tmpc;
+ extern char patch_name[PATCH_NAME_SIZE];
+ extern int ds_addr,ip,tram_addr,tram_delay_count,tram_table_count;
+ extern unsigned int macro_depth;
+
+ struct sym *sym;
+ struct control *control;
+
+ extern struct delay tram_delay[MAX_TANK_ADDR];
+ extern struct lookup tram_lookup[MAX_TANK_ADDR];
+
+
+ if( line_string[0]=='\0' || line_string[0]==';'||line_string[0]=='%'||line_string[0]=='*')
+ return(0);
+ //remove anything after a ; if one exist
+ tmpc=line_string;
+ while( *tmpc != ';' &&*tmpc != '\0')
+ tmpc++;
+ *tmpc='\0';
+
+ //check for a leading symbol
+ if( line_string[0] != ' ' && line_string[0] != '\t'){
+
+ if(strlen(leading_symbol=strtok(line_string,": \t\n"))>MAX_SYM_LEN ){
+ printf("symbol \"%s\" is more than %d characters long\n",leading_symbol,MAX_SYM_LEN );
+ as_exit("Parse error");
+ }
+
+ //address ref for skip command:
+ if(*leading_symbol=='.'){
+ if( issymbol(leading_symbol,&sym)!=-1)
+ (sym->data.value)+=ip-1;
+ }
+ op_name_ptr=strtok(NULL, " \t\n");
+ }else{
+ op_name_ptr=strtok(line_string, " \t\n");
+ }
+
+ if(op_name_ptr==NULL)
+ return(0);
+
+
+ //check if it a macro:
+ if((tmp=ismacro(op_name_ptr)) != -1 ){
+ if(defmacro==0)
+ macro_expand(tmp,strtok(NULL,""));
+ return(0);
+ }
+
+ if( (op_num=op_decode(op_name_ptr))==-1) {
+ printf("**Parse Error with op code field \"%s\"\n",op_name_ptr);
+ as_exit("Parse Error: Bad neumonic");
+ }
+
+ //check to see if we're defining a macro
+ if(leading_symbol!=NULL && defmacro!=0 && op_num!=CON && op_num!=CONSTANT)
+ as_exit("Parse error: Cannot define symbols inside of a macro");
+
+
+ switch(op_num){
+
+ case EQU:
+ add_symbol(leading_symbol,GPR_TYPE_EQUATE,arg_decode(strtok(NULL, " \t\n"),0),0);
+ return(0);
+
+ case DS:
+ printf("**Assembler warning: \"DS\" will be obsoleted\n");
+ case DYNAMIC:
+ case DYN:
+ add_symbol(leading_symbol,GPR_TYPE_DYNAMIC,ds_addr++,0);
+
+ if( (tmpc=strtok(NULL, " \t\n"))==NULL)
+ tmp=0;
+ else if((tmp=arg_decode(tmpc,0)) <=0)
+ tmp=1;
+ for(i=1;i<tmp;i++){
+ add_symbol( (char *)NO_SYM ,GPR_TYPE_DYNAMIC,ds_addr++,0);
+
+ }
+ return(0);
+ case MACRO:
+ new_macro(leading_symbol,line,strtok(NULL, "")-line_string+line);
+ defmacro++;
+ return(0);
+ case DC:
+ printf("**Assembler warning: \"DC\" will be obsoleted\n");
+ case STA:
+ case STATIC:
+ tmpc = strtok(NULL, " ,\t\n") ;
+
+ if(tmpc == NULL)
+ as_exit("Error DC directive must contain an initial value");
+ while(tmpc!=NULL ){
+
+ if( tmpc[0] == '&' )
+ tmp=arg2long(tmpc)*0x800; //account for 11 bit shift of addresses
+ else
+ tmp=arg2long(tmpc);
+
+ add_symbol(leading_symbol,GPR_TYPE_STATIC,ds_addr++,tmp);
+
+ leading_symbol=(char *)NO_SYM;
+
+ tmpc=strtok(NULL, " ,\t");
+ }
+ return(0);
+
+ case CONSTANT:
+ case CON:
+ //declaring constants inside of a macro is legal and needed for branch macros
+ if(defmacro!=0)
+ return (0);
+
+
+ tmpc = strtok(NULL, " ,\t\n") ;
+
+ if(tmpc == NULL)
+ as_exit("Error Constant directive must contain a value");
+ while(tmpc!=NULL ){
+
+ if( tmpc[0] == '&' )
+ tmp=arg2long(tmpc)*0x800; //account for 11 bit shift of addresses
+ else
+ tmp=arg2long(tmpc);
+
+ // add_constant(leading_symbol,tmp);
+
+ add_symbol(leading_symbol,GPR_TYPE_CONSTANT,ds_addr++,tmp);
+
+ leading_symbol=(char *)NO_SYM;
+
+ tmpc=strtok(NULL, " ,\t");
+ }
+
+ return(0);
+ case IO:
+ add_symbol(leading_symbol,GPR_TYPE_INPUT,ds_addr++,0);
+ add_symbol(strcat(leading_symbol,".o"),GPR_TYPE_OUTPUT,ds_addr++,0);
+ return(0);
+ case DIN:
+ as_exit("DIN is obsoleted, use IO instead");
+ add_symbol(leading_symbol,GPR_TYPE_INPUT,ds_addr++,0);
+ return(0);
+ case DOUT:
+ as_exit("DOUT is obsoleted, use IO instead");
+ add_symbol(leading_symbol,GPR_TYPE_OUTPUT,ds_addr++,0);
+ return(0);
+ case DD:
+ add_symbol(leading_symbol,GPR_TYPE_EQUATE,0x100+tram_delay_count,0);
+ (&tram_delay[tram_delay_count])->size = arg2long( strtok(NULL, " \t\n" ) ) +1;
+
+ INIT_LIST_HEAD( &(tram_delay[tram_delay_count].tram ) );
+ strcpy((&tram_delay[tram_delay_count])->name,leading_symbol);
+ if((dbg_opt&DBG_TRAM))
+ printf("Delay Line: %-16s, length: 0x%05x samples,\n",(&tram_delay[tram_delay_count])->name, (&tram_delay[tram_delay_count])->size);
+ tram_delay_count++;
+ return(0);
+ case DT:
+ add_symbol(leading_symbol,GPR_TYPE_EQUATE,tram_table_count,0);
+ (&tram_lookup[tram_table_count])->size = arg2long( strtok(NULL, " \t\n" ) );
+ INIT_LIST_HEAD( &(tram_lookup[tram_table_count].tram) );
+ strcpy((&tram_lookup[tram_table_count])->name,leading_symbol);
+
+ if((dbg_opt&DBG_TRAM))
+ printf("Lookup table: %-16s, length: 0x%05x samples\n",leading_symbol, (&tram_delay[tram_delay_count])->size);
+ tram_table_count++;
+ return(0);
+ case DW:
+ //two symbols are created, "symbol" -> addr:0x2xx ; value: tram id #
+ // "symbol.a" -> addr:0x3xx ; value: write offset
+
+ add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200, arg_decode(tmpc=strtok(NULL, " \t," ),0) );
+ add_symbol( strcat(leading_symbol,".a") ,TYPE_TRAM_ADDR_WRITE, (tram_addr++)+0x300 ,
+ arg2long(strtok(NULL," \t\n")));
+ if(dbg_opt&DBG_TRAM)
+ printf(", in segment: \"%s\"\n",tmpc);
+
+ return(0);
+
+ case DR:
+ add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200,arg_decode(tmpc=strtok(NULL, " \t," ),0) );
+ add_symbol(strcat(leading_symbol,".a"),TYPE_TRAM_ADDR_READ,(tram_addr++)+0x300,
+ arg2long(strtok(NULL," \t\n")));
+ if(dbg_opt&DBG_TRAM)
+ printf(", in segment: \"%s\"\n",tmpc);
+ return(0);
+ case CONTROL:
+ if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL)
+ as_exit("Parse Error: missing operand(s)");
+
+ if( tmpc[0] == '&' )
+ tmp=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
+ else
+ tmp=arg2long(tmpc);
+ add_symbol(leading_symbol,GPR_TYPE_CONTROL,ds_addr++,tmp);
+ issymbol(leading_symbol,(struct sym **)(&control));
+
+
+ if( (tmpc = strtok(NULL, "\t ,\n") )==NULL)
+ as_exit("Parse Error: missing operand(s)");
+
+
+ if( tmpc[0] == '&' )
+ control->min=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
+ else
+ control->min=arg2long(tmpc);
+
+ if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL)
+ as_exit("Parse Error: missing operand(s)");
+
+
+ if( tmpc[0] == '&' )
+ control->max=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
+ else
+ control->max=arg2long(tmpc);
+
+ return(0);
+ case ENDM:
+ if(defmacro==1) {
+ defmacro--;
+ return(0);
+ }else if(macro_depth!=0)
+ return(-1);
+ else
+ as_exit("Error, stray ENDM directive");
+ case END:
+ if(defmacro==1)
+ as_exit("Error end directive in macro definition");
+ return(1);
+ case INCLUDE:
+ if(defmacro==1)
+ as_exit("Error, cannot include file from within macro definition");
+ if(listing){
+ sprintf(listtemp,"including file");
+ fprintf(listfile,"%-50s || %s\n",listtemp,line);
+ }
+ asm_open(strtok(NULL, "\'\""));
+
+ return(-3);
+ case NAME:
+ advance_to_end(op_name_ptr);
+ op_name_ptr++;
+ advance_over_whites(op_name_ptr);
+ if(dbg_opt)
+ printf("Patch name:%s\n",op_name_ptr);
+
+ // printf("%s\n",op_name_ptr);
+ tmpc=strtok(op_name_ptr,"\"");
+ if(tmpc==NULL)
+ as_exit("Bad name string, did you remember quotes\"\"");
+ if(strlen(tmpc)>PATCH_NAME_SIZE)
+ as_exit("Error Patch name exceeds maximum allowed amount (16)");
+ memset(patch_name,0,PATCH_NAME_SIZE);
+ strcpy(patch_name,tmpc);
+ return(0);
+ case FOR:
+ if(listing){
+ sprintf(listtemp,"FOR LOOP");
+ fprintf(listfile,"%-50s || %s\n",listtemp,line);
+ }
+ for_handler(line,strtok(NULL,""));
+
+ return(-3);
+ case ENDFOR:
+ sprintf(listtemp,"FOR LOOP DONE");
+ return(-2);
+ default:
+
+ if(defmacro==0){
+
+ for(i=0;i<=3;i++)
+ arg[i]=arg_decode(strtok(NULL,","),0);
+ op(op_num,arg[0],arg[1],arg[2],arg[3]);
+ return(0);
+
+ }else
+ return(0);
+ }
+ return(0);
+}
+//assembly-time for loop handling:
+void for_handler(char *begin, char *operand )
+{
+ char *ptr,*next,*line,string[MAX_LINE_LENGTH];
+ int start,end,i,done;
+ int diff, incr=1;
+ struct sym *sym;
+
+ ptr=strtok(operand,"=");
+
+ start= arg_decode(strtok(NULL,":"),0);
+ end = arg_decode(strtok(NULL," \t"),0);
+
+
+ if(end>start)
+ diff=end-start;
+ else{
+ diff=start-end;
+ incr=-1;
+ }
+
+ if( (issymbol(ptr,&sym))!=-1)
+ sym->data.address=start;
+ else
+ add_symbol(ptr,GPR_TYPE_EQUATE, start,0);
+
+ issymbol(ptr,&sym);
+
+
+ while(*begin!='\0')
+ begin++;
+ begin++;
+
+ for(i=0;i<diff;i++){
+ next=begin;
+ line=next;
+ done=0;
+
+ while(done==0)
+ {
+ while((*next!= '\n') )
+ next++;
+ listtemp[0]='\0';
+ *next='\0';
+ if(strlen(line)>MAX_LINE_LENGTH)
+ as_exit("Parse error: Line exceeds allowable limit");
+ strcpy(&string[0],line);
+ //printf("%s\n",string);
+ done=parse(string, line);
+ if(listing)
+ if(done!=-2)
+ fprintf(listfile,"%-50s || %s\n",listtemp,line);
+ *next='\n';
+ if(done==-2)
+ break;
+ next++;
+
+
+ line=next;
+ }
+ sym->data.address = start+(incr*(i+1));
+
+ }
+
+
+}
+
+
+
+int op_decode(char *op_name_ptr)
+{
+ int op_num;
+
+ for(op_num=0;op_num<NUM_OPS;op_num++){
+ if( strcasecmp(&op_codes[op_num][0],op_name_ptr) == 0 )
+ return(op_num);
+ }
+ return(-1);
+}
+
+
+//check if a symbol is used and returns it's pointer value in sym
+//normally returns 0, if symbol is non exitant, return -1
+
+int issymbol(char *symbol,struct sym **sym)
+{
+ extern unsigned int macro_depth;
+ extern struct list_head sym_head;
+ struct list_head *entry;
+
+
+ list_for_each(entry,&sym_head){
+ (*sym)=list_entry(entry,struct sym,list);
+ if(symcmp((char *)&(*sym)->data.name,symbol)==0){
+ if((*sym)->type!=TYPE_MACRO_ARG)
+ return(0);
+ else if( (*sym)->data.value==(macro_depth+1) )
+ return(0);
+ }
+
+
+ }
+
+ return(-1);
+}
+
+
+//compares to words, the words can be terminated with a ' ', '\t', ',' or '\0'
+int symcmp (char *symbol1,char *symbol2)
+{
+
+
+ while(1){
+ if(*symbol1!=*symbol2)
+ return(-1);
+ symbol1++;
+ symbol2++;
+
+ if(symend(symbol1) && symend(symbol2))
+ return(0);
+
+ }
+
+
+}
+
+//copies a symbol, symbols can be terminated with a ' ' , '\t' , ',' , '\n' , a '\0'
+void symcpy (char *dest, char *source)
+{ int i=0;
+ for(i=0;i<=MAX_SYM_LEN;i++){
+ if(source[i]== ' ' || source[i]=='\0' ||source[i]==',' ||source[i]=='\n' || source[i]=='\t' ) {
+ dest[i]='\0';
+ return;
+ }
+ dest[i]=source[i];
+ }
+ as_exit("Error, Maximum symbol length exceeded");
+
+
+}
--- /dev/null
+/***************************************************************************
+ parse.h - description
+ -------------------
+ Date : May 23 2000
+ Copyright : (C) 2000 by Daniel Bertrand
+ Email : d.bertrand@ieee.ca
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+//#define NUM_OPS 17 //number of op code mneumonic and directives
+
+
+enum foo {
+ MACS=0,
+ MACS1,
+ MACW,
+ MACW1,
+ MACINTS,
+ MACINTW,
+ ACC3,
+ MACMV,
+ ANDXOR,
+ TSTNEG,
+ LIMIT,
+ LIMIT1,
+ LOG,
+ EXP,
+ INTERP,
+ SKIP,
+ EQU,
+ DS,
+ DYNAMIC,
+ DYN,
+ MACRO,
+ DC,
+ STATIC,
+ STA,
+ DIN,
+ DOUT,
+ DD,
+ DT,
+ DW,
+ DR,
+ CONTROL,
+ ENDM,
+ END,
+ INCLUDE,
+ NAME,
+ FOR,
+ ENDFOR,
+ IO,
+ CONSTANT,
+ CON,
+ NUM_OPS
+
+};
+
+
+char op_codes[NUM_OPS+1][9]=
+ {
+ "MACS",
+ "MACS1",
+ "MACW",
+ "MACW1",
+
+ "MACINTS",
+ "MACINTW",
+
+ "ACC3",
+ "MACMV",
+ "ANDXOR",
+ "TSTNEG",
+ "LIMIT",
+ "LIMIT1",
+ "LOG",
+ "EXP",
+ "INTERP",
+ "SKIP",
+ "equ",
+ "ds",
+ "dynamic",
+ "dyn",
+ "macro",
+ "dc",
+ "static",
+ "sta",
+ "din",
+ "dout",
+ "delay",
+ "table",
+ "twrite",
+ "tread",
+ "control",
+ "endm",
+ "end",
+ "include",
+ "name",
+ "for",
+ "endfor",
+ "IO",
+ "constant",
+ "con",
+ "NotAnOp"
+ };
+
+//extern int file_num,source_line_num
+
--- /dev/null
+#ifndef PROTO_H
+#define PROTO_H
+
+//as10k1.c:
+
+void as_exit(const char *message);
+void asm_open(char *name);
+void header(void);
+
+//assemble.c:
+void op(int,int,int,int,int);
+int arg_decode(char *operand,int prev_val);
+int arg_decode2(char *operand);
+int symbol2index(char *operand, int *flag);
+long arg2long(char *operand);
+void update_symbol(char *name,u16 type,u16 address, u32 value);
+void add_symbol(char *name,u16 type,u16 address, u32 value);
+int declared(int operand,int i);
+//parse.c:
+int parse( char line_string[MAX_LINE_LENGTH], char *line);
+int op_decode(char *op_name_ptr);
+void new_symbol( char *name_ptr, int constant);
+void new_dc(char *symbol,long value, int addr);
+int issymbol(char *symbol,struct sym **sym);
+void for_handler(char *begin, char *operand );
+int symcmp (char *symbol1,char *symbol2);
+void symcpy (char *dest, char *source);
+//macro.c
+void new_macro(char *symbol, char *line, char *operands);
+void macro_expand(int macnum,char * operand);
+void macro_operand(char *line,char *value);
+int ismacro(char *mac);
+
+
+#define DSP_CODE_SIZE 0x400
+
+#endif
+
+
+
+
+
+
+
--- /dev/null
+#ifndef TYPES_H
+#define TYPES_H
+
+#include "list.h"
+//i'm not sure about these type definitions, especially on non-x86
+#ifdef NO_LINUX //in the event this actually is used on non-linux platforms
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#else
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#define u8 __u8
+#define u16 __u16
+#define u32 __u32
+#endif
+
+#define MAX_SYM_LEN 32
+#define PATCH_NAME_SIZE 32
+
+#define MAX_TANK_ADDR 0x9f //maximum number of tank address
+#define MAX_LINE_LENGTH 256 //max length of a source code line
+
+
+#define GPR_TYPE_INPUT 0x0
+#define GPR_TYPE_OUTPUT 0x1
+#define GPR_TYPE_CONSTANT 0x2
+#define GPR_TYPE_STATIC 0x3
+#define GPR_TYPE_DYNAMIC 0x4
+#define GPR_TYPE_CONTROL 0x5
+
+#define TYPE_TRAM_DATA 0x6
+#define TYPE_TRAM_ADDR_READ 0x7
+#define TYPE_TRAM_ADDR_WRITE 0x8
+
+
+#define TYPE_MACRO_ARG 0x9
+#define GPR_TYPE_EQUATE 0xa //just a symbol
+
+
+
+#define TRAM_READ 0x1
+#define TRAM_WRITE 0x2
+
+
+
+
+#define DBG_SYM 1
+#define DBG_GPR 2
+#define DBG_TRAM 4
+#define DBG_INSTR 8
+
+
+struct symbol{
+ char name[MAX_SYM_LEN ];
+ u32 value; //initial value of GPR, or the value (if it's an equate);
+ u16 address; //address of GPR
+};
+
+
+struct sym{
+ struct list_head list;
+ u16 type;
+ struct symbol data;
+};
+
+struct control{
+ struct list_head list;
+ u16 type;
+ struct symbol data;
+ u32 max;
+ u32 min;
+};
+
+//all tram read/writes from a linked-list with list head in the delay/lookup-table definition block.
+struct tram{
+ struct list_head list;
+ u16 type;
+ struct symbol data;
+ struct list_head tram;
+};
+
+//a delay block
+struct delay{
+ u32 size;
+ u8 read;
+ u8 write;
+ struct list_head tram;
+ char name[MAX_SYM_LEN];
+};
+//a lookup-table block
+struct lookup{
+ u32 size;
+ u8 read;
+ u8 write;
+ struct list_head tram;
+ char name[MAX_SYM_LEN];
+};
+
+struct macrdef{
+ char *ptr;
+ char name[MAX_SYM_LEN ];
+ char *operands;
+ int line_num;
+};
+
+
+#define NO_SYM "__NO_NAME"
+
+
+#define MAX_DEF_MACRO 25
+#define MAX_MAC_DEPTH 5
+
+
+//some C macros:
+//blank ptr:
+#define blank(PTR) (*PTR==' ' || *PTR=='\t')
+
+//value is end of a symbol:
+#define symend(ptr) ( blank(ptr) || *ptr=='\0'|| *ptr==','||*ptr=='+'||*ptr=='-'||*ptr=='/'||*ptr=='*')
+
+//used for advancing over white spaces and comma:
+#define advance(ptr) while( *ptr == ' ' || *ptr== '\t' ||*ptr==',' ){ ptr++;}
+//advance over white spaces only:
+#define advance_over_whites(ptr) while(*ptr == ' ' || *ptr== '\t'){ptr++;}
+//advances to end of symbol
+#define advance_to_end(ptr) while(!symend(ptr)){ptr++;}
+
+//"returns" pointer to the previous entry:
+#define prev_sym(entry) list_entry(entry->prev,struct sym,list)
+
+#endif
+
+#define GPR_BASE 0x100
+#define TRAM_DATA_BASE 0x200
+#define TRAM_ADDR_BASE 0x300