mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-10-28 05:40:23 -04:00
Added as10k1 tool (EMU10K1 FX8010 DSP assembler).
This commit is contained in:
parent
a4569af2bb
commit
f2d80b5b5d
28 changed files with 3523 additions and 0 deletions
280
as10k1/COPYING
Normal file
280
as10k1/COPYING
Normal file
|
|
@ -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.
|
||||
|
||||
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.)
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
10
as10k1/Makefile.am
Normal file
10
as10k1/Makefile.am
Normal file
|
|
@ -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
|
||||
432
as10k1/README
Normal file
432
as10k1/README
Normal file
|
|
@ -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?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
546
as10k1/as10k1.c
Normal file
546
as10k1/as10k1.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
60
as10k1/as10k1.h
Normal file
60
as10k1/as10k1.h
Normal file
|
|
@ -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;
|
||||
|
||||
|
||||
438
as10k1/assemble.c
Normal file
438
as10k1/assemble.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9
as10k1/configure.in
Normal file
9
as10k1/configure.in
Normal file
|
|
@ -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)
|
||||
24
as10k1/cvscompile
Normal file
24
as10k1/cvscompile
Normal file
|
|
@ -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
|
||||
11
as10k1/examples/Makefile
Normal file
11
as10k1/examples/Makefile
Normal file
|
|
@ -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
|
||||
3
as10k1/examples/blank.asm
Normal file
3
as10k1/examples/blank.asm
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
;;; A blank file for clearing programs from the emu10k1
|
||||
|
||||
end
|
||||
87
as10k1/examples/chorus.asm
Normal file
87
as10k1/examples/chorus.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
29
as10k1/examples/delay.asm
Normal file
29
as10k1/examples/delay.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
117
as10k1/examples/emu_constants.asm
Normal file
117
as10k1/examples/emu_constants.asm
Normal file
|
|
@ -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
|
||||
69
as10k1/examples/eq2.asm
Normal file
69
as10k1/examples/eq2.asm
Normal file
|
|
@ -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
|
||||
|
||||
60
as10k1/examples/eq5.asm
Normal file
60
as10k1/examples/eq5.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
39
as10k1/examples/fir.asm
Normal file
39
as10k1/examples/fir.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
83
as10k1/examples/flanger.asm
Normal file
83
as10k1/examples/flanger.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
29
as10k1/examples/sine.asm
Normal file
29
as10k1/examples/sine.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
51
as10k1/examples/tremolo.asm
Normal file
51
as10k1/examples/tremolo.asm
Normal file
|
|
@ -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
|
||||
|
||||
31
as10k1/examples/vibrato.asm
Normal file
31
as10k1/examples/vibrato.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
13
as10k1/examples/vol_ctrl.asm
Normal file
13
as10k1/examples/vol_ctrl.asm
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
88
as10k1/list.h
Normal file
88
as10k1/list.h
Normal file
|
|
@ -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
|
||||
206
as10k1/macro.c
Normal file
206
as10k1/macro.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
50
as10k1/output.doc
Normal file
50
as10k1/output.doc
Normal file
|
|
@ -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
|
||||
463
as10k1/parse.c
Normal file
463
as10k1/parse.c
Normal file
|
|
@ -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");
|
||||
|
||||
|
||||
}
|
||||
115
as10k1/parse.h
Normal file
115
as10k1/parse.h
Normal file
|
|
@ -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
|
||||
|
||||
44
as10k1/proto.h
Normal file
44
as10k1/proto.h
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
136
as10k1/types.h
Normal file
136
as10k1/types.h
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue