mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-10-29 05:40:25 -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