]> git.alsa-project.org Git - alsa-tools.git/commitdiff
Added as10k1 tool (EMU10K1 FX8010 DSP assembler).
authorJaroslav Kysela <perex@perex.cz>
Thu, 12 Apr 2001 08:21:01 +0000 (08:21 +0000)
committerJaroslav Kysela <perex@perex.cz>
Thu, 12 Apr 2001 08:21:01 +0000 (08:21 +0000)
28 files changed:
as10k1/COPYING [new file with mode: 0644]
as10k1/Makefile.am [new file with mode: 0644]
as10k1/README [new file with mode: 0644]
as10k1/as10k1.c [new file with mode: 0644]
as10k1/as10k1.h [new file with mode: 0644]
as10k1/assemble.c [new file with mode: 0644]
as10k1/configure.in [new file with mode: 0644]
as10k1/cvscompile [new file with mode: 0644]
as10k1/examples/Makefile [new file with mode: 0644]
as10k1/examples/blank.asm [new file with mode: 0644]
as10k1/examples/chorus.asm [new file with mode: 0644]
as10k1/examples/delay.asm [new file with mode: 0644]
as10k1/examples/emu_constants.asm [new file with mode: 0644]
as10k1/examples/eq2.asm [new file with mode: 0644]
as10k1/examples/eq5.asm [new file with mode: 0644]
as10k1/examples/fir.asm [new file with mode: 0644]
as10k1/examples/flanger.asm [new file with mode: 0644]
as10k1/examples/sine.asm [new file with mode: 0644]
as10k1/examples/tremolo.asm [new file with mode: 0644]
as10k1/examples/vibrato.asm [new file with mode: 0644]
as10k1/examples/vol_ctrl.asm [new file with mode: 0644]
as10k1/list.h [new file with mode: 0644]
as10k1/macro.c [new file with mode: 0644]
as10k1/output.doc [new file with mode: 0644]
as10k1/parse.c [new file with mode: 0644]
as10k1/parse.h [new file with mode: 0644]
as10k1/proto.h [new file with mode: 0644]
as10k1/types.h [new file with mode: 0644]

diff --git a/as10k1/COPYING b/as10k1/COPYING
new file mode 100644 (file)
index 0000000..c7aea18
--- /dev/null
@@ -0,0 +1,280 @@
+                   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
diff --git a/as10k1/Makefile.am b/as10k1/Makefile.am
new file mode 100644 (file)
index 0000000..682ae2c
--- /dev/null
@@ -0,0 +1,10 @@
+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
diff --git a/as10k1/README b/as10k1/README
new file mode 100644 (file)
index 0000000..c711fc9
--- /dev/null
@@ -0,0 +1,432 @@
+
+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?
+
+
+
+
+
+
diff --git a/as10k1/as10k1.c b/as10k1/as10k1.c
new file mode 100644 (file)
index 0000000..9823e47
--- /dev/null
@@ -0,0 +1,546 @@
+/***************************************************************************
+                          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);
+        }
+}
diff --git a/as10k1/as10k1.h b/as10k1/as10k1.h
new file mode 100644 (file)
index 0000000..b897f3b
--- /dev/null
@@ -0,0 +1,60 @@
+/***************************************************************************
+                          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;
+
+
diff --git a/as10k1/assemble.c b/as10k1/assemble.c
new file mode 100644 (file)
index 0000000..4508973
--- /dev/null
@@ -0,0 +1,438 @@
+/***************************************************************************
+                          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;
+        }
+        
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/as10k1/configure.in b/as10k1/configure.in
new file mode 100644 (file)
index 0000000..37e9e6c
--- /dev/null
@@ -0,0 +1,9 @@
+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)
diff --git a/as10k1/cvscompile b/as10k1/cvscompile
new file mode 100644 (file)
index 0000000..01e8151
--- /dev/null
@@ -0,0 +1,24 @@
+#!/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
diff --git a/as10k1/examples/Makefile b/as10k1/examples/Makefile
new file mode 100644 (file)
index 0000000..5d6f391
--- /dev/null
@@ -0,0 +1,11 @@
+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
diff --git a/as10k1/examples/blank.asm b/as10k1/examples/blank.asm
new file mode 100644 (file)
index 0000000..caa7f1b
--- /dev/null
@@ -0,0 +1,3 @@
+;;; A blank file for clearing programs from the emu10k1
+
+       end
\ No newline at end of file
diff --git a/as10k1/examples/chorus.asm b/as10k1/examples/chorus.asm
new file mode 100644 (file)
index 0000000..f798c8d
--- /dev/null
@@ -0,0 +1,87 @@
+;;; 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
+
+
+
+
+
diff --git a/as10k1/examples/delay.asm b/as10k1/examples/delay.asm
new file mode 100644 (file)
index 0000000..9d31bf2
--- /dev/null
@@ -0,0 +1,29 @@
+;;; 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
+               
+
+
+
diff --git a/as10k1/examples/emu_constants.asm b/as10k1/examples/emu_constants.asm
new file mode 100644 (file)
index 0000000..d385104
--- /dev/null
@@ -0,0 +1,117 @@
+;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
diff --git a/as10k1/examples/eq2.asm b/as10k1/examples/eq2.asm
new file mode 100644 (file)
index 0000000..89522a3
--- /dev/null
@@ -0,0 +1,69 @@
+;;; 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
+       
diff --git a/as10k1/examples/eq5.asm b/as10k1/examples/eq5.asm
new file mode 100644 (file)
index 0000000..f6866d3
--- /dev/null
@@ -0,0 +1,60 @@
+       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
+
+
+
diff --git a/as10k1/examples/fir.asm b/as10k1/examples/fir.asm
new file mode 100644 (file)
index 0000000..12d7ade
--- /dev/null
@@ -0,0 +1,39 @@
+;;; 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
+
+
+
+
+
+
+
+
diff --git a/as10k1/examples/flanger.asm b/as10k1/examples/flanger.asm
new file mode 100644 (file)
index 0000000..04a7f4f
--- /dev/null
@@ -0,0 +1,83 @@
+;;; 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
+
+
+
+
+
diff --git a/as10k1/examples/sine.asm b/as10k1/examples/sine.asm
new file mode 100644 (file)
index 0000000..1265c9f
--- /dev/null
@@ -0,0 +1,29 @@
+       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
+
+
+
+
+
+
+
+
diff --git a/as10k1/examples/tremolo.asm b/as10k1/examples/tremolo.asm
new file mode 100644 (file)
index 0000000..fd4033d
--- /dev/null
@@ -0,0 +1,51 @@
+;;; 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
+                       
diff --git a/as10k1/examples/vibrato.asm b/as10k1/examples/vibrato.asm
new file mode 100644 (file)
index 0000000..387067e
--- /dev/null
@@ -0,0 +1,31 @@
+;;; 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
+       
+
+
+
+
diff --git a/as10k1/examples/vol_ctrl.asm b/as10k1/examples/vol_ctrl.asm
new file mode 100644 (file)
index 0000000..463638c
--- /dev/null
@@ -0,0 +1,13 @@
+       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
+       
+       
+               
+       
diff --git a/as10k1/list.h b/as10k1/list.h
new file mode 100644 (file)
index 0000000..ad70a5b
--- /dev/null
@@ -0,0 +1,88 @@
+/* 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
diff --git a/as10k1/macro.c b/as10k1/macro.c
new file mode 100644 (file)
index 0000000..574b634
--- /dev/null
@@ -0,0 +1,206 @@
+/***************************************************************************
+                          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);
+                }
+               
+        }
+        
+} 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/as10k1/output.doc b/as10k1/output.doc
new file mode 100644 (file)
index 0000000..fe38ded
--- /dev/null
@@ -0,0 +1,50 @@
+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
diff --git a/as10k1/parse.c b/as10k1/parse.c
new file mode 100644 (file)
index 0000000..8523717
--- /dev/null
@@ -0,0 +1,463 @@
+/***************************************************************************
+                          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");
+       
+       
+}
diff --git a/as10k1/parse.h b/as10k1/parse.h
new file mode 100644 (file)
index 0000000..be71daa
--- /dev/null
@@ -0,0 +1,115 @@
+/***************************************************************************
+                          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
+
diff --git a/as10k1/proto.h b/as10k1/proto.h
new file mode 100644 (file)
index 0000000..7f8a736
--- /dev/null
@@ -0,0 +1,44 @@
+#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
+
+
+
+
+
+
+
diff --git a/as10k1/types.h b/as10k1/types.h
new file mode 100644 (file)
index 0000000..3aa7564
--- /dev/null
@@ -0,0 +1,136 @@
+#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