mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-19 18:00:23 +08:00
NASM 0.98p3
This commit is contained in:
parent
87bc61964c
commit
eba20a73f2
94
Changes
94
Changes
@ -442,3 +442,97 @@ corruption at ends of long PUBDEF records.
|
||||
|
||||
Separated DOS archives into main-program and documentation to reduce
|
||||
download size.
|
||||
|
||||
0.98 not released yet
|
||||
---------------------
|
||||
|
||||
Fixed a bug whereby STRUC didn't work at all in RDF.
|
||||
|
||||
Fixed a problem with group specification in PUBDEFs in OBJ.
|
||||
|
||||
Improved ease of adding new output formats. Contribution due to
|
||||
Fox Cutter.
|
||||
|
||||
Fixed a bug in relocations in the `bin' format: was showing up when
|
||||
a relocatable reference crossed an 8192-byte boundary in any output
|
||||
section.
|
||||
|
||||
Fixed a bug in local labels: local-label lookups were inconsistent
|
||||
between passes one and two if an EQU occurred between the definition
|
||||
of a global label and the subsequent use of a local label local to
|
||||
that global.
|
||||
|
||||
Fixed a seg-fault in the preprocessor (again) which happened when
|
||||
you use a blank line as the first line of a multi-line macro
|
||||
definition and then defined a label on the same line as a call to
|
||||
that macro.
|
||||
|
||||
Fixed a stale-pointer bug in the handling of the NASM environment
|
||||
variable. Thanks to Thomas McWilliams.
|
||||
|
||||
ELF had a hard limit on the number of sections which caused
|
||||
segfaults when transgressed. Fixed.
|
||||
|
||||
Added ability for ndisasm to read from stdin by using `-' as the
|
||||
filename.
|
||||
|
||||
ndisasm wasn't outputting the TO keyword. Fixed.
|
||||
|
||||
Fixed error cascade on bogus expression in %if - an error in
|
||||
evaluation was causing the entire %if to be discarded, thus creating
|
||||
trouble later when the %else or %endif was encountered.
|
||||
|
||||
Forward reference tracking was instruction-granular not operand-
|
||||
granular, which was causing 286-specific code to be generated
|
||||
needlessly on code of the form `shr word [forwardref],1'. Thanks to
|
||||
Jim Hague for sending a patch.
|
||||
|
||||
All messages now appear on stdout, as sending them to stderr serves
|
||||
no useful purpose other than to make redirection difficult.
|
||||
|
||||
Fixed the problem with EQUs pointing to an external symbol - this
|
||||
now generates an error message.
|
||||
|
||||
Allowed multiple size prefixes to an operand, of which only the first
|
||||
is taken into account.
|
||||
|
||||
Incorporated John Fine's changes, including fixes of a large number
|
||||
of preprocessor bugs, some small problems in OBJ, and a reworking of
|
||||
label handling to define labels before their line is assembled, rather
|
||||
than after.
|
||||
|
||||
Reformatted a lot of the source code to be more readable. Included
|
||||
'coding.txt' as a guideline for how to format code for contributors.
|
||||
|
||||
Stopped nested %reps causing a panic - they now cause a slightly more
|
||||
friendly error message instead.
|
||||
|
||||
Fixed floating point constant problems (patch by Pedro Gimeno)
|
||||
|
||||
Fixed the return value of insn_size() not being checked for -1, indicating
|
||||
an error.
|
||||
|
||||
Incorporated 3D now instructions.
|
||||
|
||||
Fixed the 'mov eax, eax + ebx' bug.
|
||||
|
||||
Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
|
||||
|
||||
Incorporated John Fine's command line parsing changes
|
||||
|
||||
Incorporated David Lindauer's OMF debug support
|
||||
|
||||
Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
|
||||
specification warning when sizes agree).
|
||||
|
||||
Released NASM 0.98 Pre-release 1
|
||||
|
||||
fixed bug in outcoff.c to do with truncating section names longer
|
||||
than 8 characters, referencing beyond end of string; 0.98 pre-release 2
|
||||
|
||||
added response file support, improved command line handling, new layout
|
||||
help screen
|
||||
|
||||
fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
|
||||
related bugs, updated Wishlist; 0.98 Prerelease 3.
|
||||
|
||||
|
225
Wishlist
225
Wishlist
@ -1,23 +1,168 @@
|
||||
NASM Wishlist
|
||||
=============
|
||||
|
||||
- forward-reference tracking is instruction-granular not operand-
|
||||
granular. Bummer.
|
||||
Numbers on right hand side are version numbers that it would be nice to
|
||||
have this done by. ? means I haven't looked at it yet.
|
||||
|
||||
- see if BITS can be made to do anything sensible in obj (eg set the
|
||||
- Create a binary RDF tools distribution. Should probably be distributed 0.98
|
||||
seperately.
|
||||
|
||||
- Check misc/ide.cfg into RCS as Watcom IDE enhancement thingy. 0.98
|
||||
(nop@dlc.fi)
|
||||
|
||||
- Package the Linux Assembler HOWTO. 0.98
|
||||
|
||||
- AMD 3dNow extensions need documenting. 0.98
|
||||
|
||||
- prototypes of lrotate don't match in test/*. Fix. 0.98
|
||||
|
||||
- Build djgpp binaries for 0.98 onwards. Look into PMODE/W as a stub 0.98
|
||||
- it might be a lot better than CWSDPMI. It's in PMW133.ZIP.
|
||||
|
||||
- Fix `%error' giving error messages twice. 0.99
|
||||
Not especially important, as changes planned for 1.1x below will make
|
||||
the preprocessor be only called once.
|
||||
|
||||
- Sort out problems with OBJ: 0.99
|
||||
* TLINK32 doesn't seem to like SEGDEF32 et al. So for that, we
|
||||
should avoid xxx32 records wherever we can.
|
||||
* However, didn't we change _to_ using xxx32 at some stage? Try
|
||||
to remember why and when.
|
||||
* Apparently Delphi's linker has trouble with two or more
|
||||
globals being defined inside a PUBDEF32. Don't even know if it
|
||||
_can_ cope with a PUBDEF16.
|
||||
* Might need extra flags. *sigh*
|
||||
|
||||
- Symbol table output may possibly be useful. 0.99
|
||||
Ken Martwick (kenm@efn.org) wants the following format:
|
||||
labelname type offset(hex) repetition count
|
||||
Possibly include xref addresses after repetition count?
|
||||
|
||||
- There are various other bugs in outelf.c that make certain kinds 0.99
|
||||
of relocation not work. See zbrown.asm. Looks like we may have to do
|
||||
a major rewrite of parts of it. Compare some NASM code output with
|
||||
equivalent GAS code output. Look at the ELF spec. Generally fix things.
|
||||
|
||||
- NASM is currently using a kludge in ELF that involves defining 0.99
|
||||
a symbol at a zero absolute offset. This isn't needed, as the
|
||||
documented solution to the problem that this solves is to use
|
||||
SHN_UNDEF.
|
||||
|
||||
- Debug information, in all formats it can be usefully done in. 0.99
|
||||
* including line-number record support.
|
||||
* "George C. Lindauer" <gclind01@starbase.spd.louisville.edu>
|
||||
wants to have some say in how this goes through.
|
||||
* Andrew Crabtree <andrewc@rosemail.rose.hp.com> wants to help out.
|
||||
|
||||
- Think about a line-continuation character. 0.99
|
||||
|
||||
- Consider allowing declaration of two labels on the same line,
|
||||
syntax 'label1[:] label2[:] ... instruction'. Need to investigate
|
||||
feasibility. 0.99
|
||||
|
||||
- Quoting of quotes by doubling them, in string and char constants. 0.99
|
||||
|
||||
- Two-operand syntax for SEGMENT/SECTION macro to avoid warnings 0.99
|
||||
of ignored section parameters on reissue of __SECT__.
|
||||
Or maybe skip the warning if the given parameters are identical to
|
||||
what was actually stored. Investigate.
|
||||
|
||||
- Apparently we are not missing a PSRAQ instruction, because it
|
||||
doesn't exist. Check that it doesn't exist as an undocumented
|
||||
instruction, or something stupid like that. 0.99
|
||||
|
||||
- Any assembled form starting 0x80 can also start 0x82. ndisasm 1.00
|
||||
should know this. New special code in instruction encodings,
|
||||
probably.
|
||||
|
||||
- Pointing an EQU at an external symbol now generates an error. There 1.05
|
||||
may be a better way of handling this; we should look into it.
|
||||
Ideally, the label mechanism should be changed to cope with one
|
||||
label being declared relative to another - that may work, but could be
|
||||
a pain to implement (or is it? it may be easy enough that you just
|
||||
need to declare a new offset in the same segment...) This should be done
|
||||
before v1.0 is released. There is a comment regarding this in labels.c,
|
||||
towards the end of the file, which discusses ways of fixing this.
|
||||
|
||||
- nested %rep used to cause a panic. Now a more informative error 1.10
|
||||
message is produced. This problem whould be fixed before v1.0.
|
||||
See comment in switch() statement block for PP_REP in do_directive()
|
||||
in preproc.c (line 1585, or thereabouts)
|
||||
|
||||
- Contribution: zgraeme.tar contains improved hash table routines ?
|
||||
contributed by Graeme Defty <graeme@HK.Super.NET> for use in the
|
||||
label manager.
|
||||
|
||||
- Contribution: zsyntax.zip contains a syntax-highlighting mode for ?
|
||||
NASM, for use with the Aurora text editor (??).
|
||||
|
||||
- Contribution: zvim.zip contains a syntax-highlighting mode for ?
|
||||
NASM, for use with vim.
|
||||
|
||||
- Contribution: zkendal1.zip and zkendal2.zip contain Kendall ?
|
||||
Bennett's (<KendallB@scitechsoft.com>) alternative syntax stuff,
|
||||
providing an alternative syntax mode for NASM which allows a macro
|
||||
set to be written that allows the same source files to be
|
||||
assembled with NASM and TASM.
|
||||
|
||||
- Add the UD2 instruction. ?
|
||||
|
||||
- Add the four instructions documented in 24368901.pdf (Intel's own ?
|
||||
document).
|
||||
|
||||
- Some means of avoiding MOV memoffs,EAX which apparently the 1.10?
|
||||
Pentium pairing detector thinks modifies EAX. Similar means of
|
||||
choosing instruction encodings where necessary.
|
||||
|
||||
- The example of ..@ makes it clear that a ..@ label isn't just ?
|
||||
local, but doesn't make it clear that it isn't just global either.
|
||||
|
||||
- hpa wants an evaluator operator for ceil(log2(x)). ?
|
||||
|
||||
- Extra reloc types in ELF: R_386_16 type 20, PC16 is 21, 8 is 22, PC8 is 23.
|
||||
Add support for the 16s at least. ?
|
||||
|
||||
|
||||
- Lazy section creation or selective section output, in COFF/win32 ?
|
||||
at least and probably other formats: don't bother to emit a section
|
||||
if it contains no data. Particularly the default auto-created
|
||||
section. We believe zero-length sections crash at least WLINK (in
|
||||
win32).
|
||||
|
||||
- Make the flags field in `struct itemplate' in insns.h a long ?
|
||||
instead of an int.
|
||||
|
||||
- Implement %ifref to check whether a single-line macro has ever been ?
|
||||
expanded since (last re) definition. Or maybe not. We'll see.
|
||||
|
||||
- add pointer to \k{insLEAVE} and \k{insENTER} in chapters about ?
|
||||
mixed-language programming.
|
||||
|
||||
- Some equivalent to TASM's GLOBAL directive, ie something which ?
|
||||
defines a symbol as external if it doesn't end up being defined
|
||||
but defines it as public if it does end up being defined.
|
||||
|
||||
- Documentation doesn't explain about C++ name mangling. ?
|
||||
|
||||
- see if BITS can be made to do anything sensible in obj (eg set the ?
|
||||
default new-segment property to Use32).
|
||||
|
||||
- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and
|
||||
- OBJ: coalesce consecutive offset and segment fixups for the same ?
|
||||
location into full-32bit-pointer fixups. This is apparently
|
||||
necessary because some twazzock in the PowerBASIC development
|
||||
team didn't deign to support the OMF spec the way the rest of the
|
||||
world sees it.
|
||||
|
||||
- Allow % to be separated from the rest of a preproc directive, for ?
|
||||
alternative directive indentation styles.
|
||||
|
||||
- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and ?
|
||||
__NASM_MINOR__.
|
||||
|
||||
- Warn on TIMES combined with multi-line macros. TIMES gets applied
|
||||
- Warn on TIMES combined with multi-line macros. TIMES gets applied 1.00
|
||||
to first line only - should bring to users' attention.
|
||||
|
||||
- Add support for lcc 4.0.
|
||||
* If-when this happens, remember to bump the `supported lcc
|
||||
version' number in Readme.
|
||||
|
||||
- Re-work the evaluator, again, with a per-object-format fixup
|
||||
- Re-work the evaluator, again, with a per-object-format fixup 1.10
|
||||
routine, so as to be able to cope with section offsets "really"
|
||||
being pure numbers; should be able to allow at _least_ the two
|
||||
common idioms
|
||||
@ -28,17 +173,33 @@ NASM Wishlist
|
||||
had to. (_Always_ returning UNKNOWN on pass one, though a lovely
|
||||
clean design, breaks the first of the above examples.)
|
||||
|
||||
- Preprocessor identifier concatenation?
|
||||
- Preprocessor identifier concatenation? 1.10
|
||||
|
||||
- Arbitrary section names in `bin'.
|
||||
- Arbitrary section names in `bin'. ?
|
||||
Is this necessary? Is it even desirable?
|
||||
|
||||
- Ability to read from a pipe. Obviously not useful under dos, so
|
||||
- Ability to read from a pipe. Obviously not useful under dos, so 1.10
|
||||
memory problems with storing entire input file aren't a problem
|
||||
either.
|
||||
|
||||
- Subsection support?
|
||||
Related topic: file caching under DOS/32 bit... 1.10?
|
||||
maybe even implement discardable buffers that get thrown away
|
||||
when we get a NULL returned from malloc(). Only really useful under
|
||||
DOS. Think about it.
|
||||
|
||||
- A good ALIGN mechanism, similar to GAS's. GAS pads out space by
|
||||
Another related topic: possibly spool out the pre-processed 1.10?
|
||||
stuff to a file, to avoid having to re-process it. Possible problems
|
||||
with preprocessor values not known on pass 1? Have a look...
|
||||
|
||||
Or maybe we can spool out a pre-parsed version...? 1.10
|
||||
Need to investigate feasibility. Does the results from the parser
|
||||
change from pass 1 to pass 2? Would it be feasible to alter it so that
|
||||
the parser returns an invariant result, and this is then processed
|
||||
afterwards to resolve label references, etc?
|
||||
|
||||
- Subsection support? ?
|
||||
|
||||
- A good ALIGN mechanism, similar to GAS's. GAS pads out space by 1.10?
|
||||
means of the following (32-bit) instructions:
|
||||
8DB42600000000 lea esi,[esi+0x0]
|
||||
8DB600000000 lea esi,[esi+0x0]
|
||||
@ -55,7 +216,7 @@ NASM Wishlist
|
||||
Also re-work the macro form so that when given one argument in a
|
||||
code section it calls this feature.
|
||||
|
||||
- Possibly a means whereby FP constants can be specified as
|
||||
- Possibly a means whereby FP constants can be specified as ?
|
||||
immediate operands to non-FP instructions.
|
||||
* Possible syntax: MOV EAX,FLOAT 1.2 to get a single-precision FP
|
||||
constant. Then maybe MOV EAX,HI_FLOAT 1.2 and MOV EAX,LO_FLOAT
|
||||
@ -67,37 +228,41 @@ NASM Wishlist
|
||||
chunks, one-byte chunks, even stranger chunks, and pieces of
|
||||
ten-byte reals to be bandied around as well.
|
||||
|
||||
- A UNION macro might be quite cool, now that ABSOLUTE is sane
|
||||
- A UNION macro might be quite cool, now that ABSOLUTE is sane ?
|
||||
enough to be able to handle it.
|
||||
|
||||
- An equivalent to gcc's ## stringify operator, plus string
|
||||
- An equivalent to gcc's ## stringify operator, plus string ?
|
||||
concatenation, somehow implemented without undue ugliness, so as
|
||||
to be able to do `%include "/my/path/%1"' in a macro, or something
|
||||
similar...
|
||||
|
||||
- Actually _do_ something with the processor, privileged and
|
||||
undocumented flags in the instruction table.
|
||||
- Actually _do_ something with the processor, privileged and 1.10
|
||||
undocumented flags in the instruction table. When this happens,
|
||||
consider allowing PMULHRW to map to either of the Cyrix or AMD
|
||||
versions?
|
||||
|
||||
- Maybe NEC V20/V30 instructions?
|
||||
- Maybe NEC V20/V30 instructions? ?
|
||||
|
||||
- Yet more object formats.
|
||||
* Possibly direct support for .EXE files?
|
||||
* Possibly direct support for .EXE files? 1.10
|
||||
|
||||
- Debug information, in all formats it can be usefully done in.
|
||||
* including line-number record support.
|
||||
- Symbol map in binary format. Format-specific options... 1.10?
|
||||
|
||||
- Symbol map in binary format. Format-specific options...
|
||||
|
||||
- REDESIGN: Think about EQU dependency, and about start-point
|
||||
- REDESIGN: Think about EQU dependency, and about start-point 1.20?
|
||||
specification in OBJ. Possibly re-think directive support.
|
||||
|
||||
- Think about a wrapper program like gcc? Possibly invent a _patch_
|
||||
- Think about a wrapper program like gcc? Possibly invent a _patch_ 2.00?
|
||||
for gcc so that it can take .asm files on the command line?
|
||||
|
||||
- If a wrapper happens, think about adding an option to cause the
|
||||
- If a wrapper happens, think about adding an option to cause the ?
|
||||
resulting executable file to be executed immediately, thus
|
||||
allowing NASM source files to have #!... (probably silly)
|
||||
|
||||
- Multi-platform support? If so: definitely Alpha; possibly Java
|
||||
- Multi-platform support? If so: definitely Alpha; possibly Java ?
|
||||
byte code; probably ARM/StrongARM; maybe Sparc; maybe Mips; maybe
|
||||
Vax. Perhaps Z80 and 6502, just for a laugh?
|
||||
|
||||
- Consider a 'verbose' option that prints information about the resulting ?
|
||||
object file onto stdout.
|
||||
|
||||
|
||||
|
876
assemble.c
876
assemble.c
File diff suppressed because it is too large
Load Diff
41
disasm.c
41
disasm.c
@ -33,7 +33,8 @@ extern struct itemplate **itable[];
|
||||
#define SEG_NODISP 64
|
||||
#define SEG_SIGNED 128
|
||||
|
||||
static int whichreg(long regflags, int regval) {
|
||||
static int whichreg(long regflags, int regval)
|
||||
{
|
||||
static int reg32[] = {
|
||||
R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI };
|
||||
static int reg16[] = {
|
||||
@ -98,7 +99,8 @@ static int whichreg(long regflags, int regval) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *whichcond(int condval) {
|
||||
static char *whichcond(int condval)
|
||||
{
|
||||
static int conds[] = {
|
||||
C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A,
|
||||
C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G
|
||||
@ -110,7 +112,8 @@ static char *whichcond(int condval) {
|
||||
* Process an effective address (ModRM) specification.
|
||||
*/
|
||||
static unsigned char *do_ea (unsigned char *data, int modrm, int asize,
|
||||
int segsize, operand *op) {
|
||||
int segsize, operand *op)
|
||||
{
|
||||
int mod, rm, scale, index, base;
|
||||
|
||||
mod = (modrm >> 6) & 03;
|
||||
@ -249,11 +252,13 @@ static unsigned char *do_ea (unsigned char *data, int modrm, int asize,
|
||||
* stream in data. Return the number of bytes matched if so.
|
||||
*/
|
||||
static int matches (unsigned char *r, unsigned char *data, int asize,
|
||||
int osize, int segsize, insn *ins) {
|
||||
unsigned char *origdata = data;
|
||||
int a_used = FALSE, o_used = FALSE;
|
||||
int osize, int segsize, insn *ins)
|
||||
{
|
||||
unsigned char * origdata = data;
|
||||
int a_used = FALSE, o_used = FALSE;
|
||||
|
||||
while (*r) {
|
||||
while (*r)
|
||||
{
|
||||
int c = *r++;
|
||||
if (c >= 01 && c <= 03) {
|
||||
while (c--)
|
||||
@ -440,7 +445,8 @@ static int matches (unsigned char *r, unsigned char *data, int asize,
|
||||
}
|
||||
|
||||
long disasm (unsigned char *data, char *output, int segsize, long offset,
|
||||
int autosync) {
|
||||
int autosync)
|
||||
{
|
||||
struct itemplate **p;
|
||||
int length = 0;
|
||||
char *segover;
|
||||
@ -486,7 +492,8 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
|
||||
works = TRUE;
|
||||
for (p = itable[*data]; *p; p++)
|
||||
if ( (length = matches((unsigned char *)((*p)->code), data,
|
||||
asize, osize, segsize, &ins)) ) {
|
||||
asize, osize, segsize, &ins)) )
|
||||
{
|
||||
works = TRUE;
|
||||
/*
|
||||
* Final check to make sure the types of r/m match up.
|
||||
@ -507,11 +514,17 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
|
||||
((((*p)->opd[i] & (REGISTER | FPUREG)) ||
|
||||
(ins.oprs[i].segment & SEG_RMREG)) &&
|
||||
!whichreg ((*p)->opd[i], ins.oprs[i].basereg)))
|
||||
|
||||
{
|
||||
works = FALSE;
|
||||
/*
|
||||
* FIXME: can we do a break here?
|
||||
*/
|
||||
}
|
||||
|
||||
if (works)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!length || !works)
|
||||
return 0; /* no instruction was matched */
|
||||
|
||||
@ -570,9 +583,12 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
|
||||
colon = FALSE;
|
||||
|
||||
if (((*p)->opd[i] & (REGISTER | FPUREG)) ||
|
||||
(ins.oprs[i].segment & SEG_RMREG)) {
|
||||
(ins.oprs[i].segment & SEG_RMREG))
|
||||
{
|
||||
ins.oprs[i].basereg = whichreg ((*p)->opd[i],
|
||||
ins.oprs[i].basereg);
|
||||
if ( (*p)->opd[i] & TO )
|
||||
slen += sprintf(output+slen, "to ");
|
||||
slen += sprintf(output+slen, "%s",
|
||||
reg_names[ins.oprs[i].basereg-EXPR_REG_START]);
|
||||
} else if (!(UNITY & ~(*p)->opd[i])) {
|
||||
@ -680,7 +696,8 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
|
||||
return length;
|
||||
}
|
||||
|
||||
long eatbyte (unsigned char *data, char *output) {
|
||||
long eatbyte (unsigned char *data, char *output)
|
||||
{
|
||||
sprintf(output, "db 0x%02X", *data);
|
||||
return 1;
|
||||
}
|
||||
|
241
eval.c
241
eval.c
@ -17,37 +17,56 @@
|
||||
#include "nasm.h"
|
||||
#include "nasmlib.h"
|
||||
#include "eval.h"
|
||||
#include "labels.h"
|
||||
|
||||
static expr **tempexprs = NULL;
|
||||
static int ntempexprs, tempexprs_size = 0;
|
||||
#define TEMPEXPRS_DELTA 128
|
||||
|
||||
static expr *tempexpr;
|
||||
static int ntempexpr, tempexpr_size;
|
||||
#define TEMPEXPR_DELTA 8
|
||||
|
||||
static scanner scan;
|
||||
static scanner scan; /* Address of scanner routine */
|
||||
static efunc error; /* Address of error reporting routine */
|
||||
static lfunc labelfunc; /* Address of label routine */
|
||||
|
||||
static struct ofmt *outfmt; /* Structure of addresses of output routines */
|
||||
|
||||
static expr **tempexprs = NULL;
|
||||
static int ntempexprs;
|
||||
static int tempexprs_size = 0;
|
||||
|
||||
static expr *tempexpr;
|
||||
static int ntempexpr;
|
||||
static int tempexpr_size;
|
||||
|
||||
static struct tokenval *tokval; /* The current token */
|
||||
static int i; /* The t_type of tokval */
|
||||
|
||||
static void *scpriv;
|
||||
static struct tokenval *tokval;
|
||||
static efunc error;
|
||||
static int i;
|
||||
static int seg, ofs;
|
||||
static char *label = NULL, special_empty_string[] = "";
|
||||
static lfunc labelfunc;
|
||||
static struct ofmt *outfmt;
|
||||
static int *forward;
|
||||
static loc_t *location; /* Pointer to current line's segment,offset */
|
||||
static int *opflags;
|
||||
|
||||
static struct eval_hints *hint;
|
||||
|
||||
/*
|
||||
* Unimportant cleanup is done to avoid confusing people who are trying
|
||||
* to debug real memory leaks
|
||||
*/
|
||||
void eval_cleanup(void)
|
||||
{
|
||||
while (ntempexprs)
|
||||
nasm_free (tempexprs[--ntempexprs]);
|
||||
nasm_free (tempexprs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a temporary expression.
|
||||
*/
|
||||
static void begintemp(void) {
|
||||
static void begintemp(void)
|
||||
{
|
||||
tempexpr = NULL;
|
||||
tempexpr_size = ntempexpr = 0;
|
||||
}
|
||||
|
||||
static void addtotemp(long type, long value) {
|
||||
static void addtotemp(long type, long value)
|
||||
{
|
||||
while (ntempexpr >= tempexpr_size) {
|
||||
tempexpr_size += TEMPEXPR_DELTA;
|
||||
tempexpr = nasm_realloc(tempexpr,
|
||||
@ -57,7 +76,8 @@ static void addtotemp(long type, long value) {
|
||||
tempexpr[ntempexpr++].value = value;
|
||||
}
|
||||
|
||||
static expr *finishtemp(void) {
|
||||
static expr *finishtemp(void)
|
||||
{
|
||||
addtotemp (0L, 0L); /* terminate */
|
||||
while (ntempexprs >= tempexprs_size) {
|
||||
tempexprs_size += TEMPEXPRS_DELTA;
|
||||
@ -72,7 +92,8 @@ static expr *finishtemp(void) {
|
||||
* absolute segment types: we preserve them during addition _only_
|
||||
* if one of the segments is a truly pure scalar.
|
||||
*/
|
||||
static expr *add_vectors(expr *p, expr *q) {
|
||||
static expr *add_vectors(expr *p, expr *q)
|
||||
{
|
||||
int preserve;
|
||||
|
||||
preserve = is_really_simple(p) || is_really_simple(q);
|
||||
@ -81,7 +102,8 @@ static expr *add_vectors(expr *p, expr *q) {
|
||||
|
||||
while (p->type && q->type &&
|
||||
p->type < EXPR_SEGBASE+SEG_ABS &&
|
||||
q->type < EXPR_SEGBASE+SEG_ABS) {
|
||||
q->type < EXPR_SEGBASE+SEG_ABS)
|
||||
{
|
||||
int lasttype;
|
||||
|
||||
if (p->type > q->type) {
|
||||
@ -91,7 +113,9 @@ static expr *add_vectors(expr *p, expr *q) {
|
||||
addtotemp(p->type, p->value);
|
||||
lasttype = p++->type;
|
||||
} else { /* *p and *q have same type */
|
||||
addtotemp(p->type, p->value + q->value);
|
||||
long sum = p->value + q->value;
|
||||
if (sum)
|
||||
addtotemp(p->type, sum);
|
||||
lasttype = p->type;
|
||||
p++, q++;
|
||||
}
|
||||
@ -100,12 +124,14 @@ static expr *add_vectors(expr *p, expr *q) {
|
||||
}
|
||||
}
|
||||
while (p->type &&
|
||||
(preserve || p->type < EXPR_SEGBASE+SEG_ABS)) {
|
||||
(preserve || p->type < EXPR_SEGBASE+SEG_ABS))
|
||||
{
|
||||
addtotemp(p->type, p->value);
|
||||
p++;
|
||||
}
|
||||
while (q->type &&
|
||||
(preserve || q->type < EXPR_SEGBASE+SEG_ABS)) {
|
||||
(preserve || q->type < EXPR_SEGBASE+SEG_ABS))
|
||||
{
|
||||
addtotemp(q->type, q->value);
|
||||
q++;
|
||||
}
|
||||
@ -125,7 +151,8 @@ static expr *add_vectors(expr *p, expr *q) {
|
||||
* multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
|
||||
* as the base register.
|
||||
*/
|
||||
static expr *scalar_mult(expr *vect, long scalar, int affect_hints) {
|
||||
static expr *scalar_mult(expr *vect, long scalar, int affect_hints)
|
||||
{
|
||||
expr *p = vect;
|
||||
|
||||
while (p->type && p->type < EXPR_SEGBASE+SEG_ABS) {
|
||||
@ -140,13 +167,15 @@ static expr *scalar_mult(expr *vect, long scalar, int affect_hints) {
|
||||
return vect;
|
||||
}
|
||||
|
||||
static expr *scalarvect (long scalar) {
|
||||
static expr *scalarvect (long scalar)
|
||||
{
|
||||
begintemp();
|
||||
addtotemp(EXPR_SIMPLE, scalar);
|
||||
return finishtemp();
|
||||
}
|
||||
|
||||
static expr *unknown_expr (void) {
|
||||
static expr *unknown_expr (void)
|
||||
{
|
||||
begintemp();
|
||||
addtotemp(EXPR_UNKNOWN, 1L);
|
||||
return finishtemp();
|
||||
@ -157,7 +186,8 @@ static expr *unknown_expr (void) {
|
||||
* value. Return NULL, as usual, if an error occurs. Report the
|
||||
* error too.
|
||||
*/
|
||||
static expr *segment_part (expr *e) {
|
||||
static expr *segment_part (expr *e)
|
||||
{
|
||||
long seg;
|
||||
|
||||
if (is_unknown(e))
|
||||
@ -228,22 +258,27 @@ static expr *expr4(int), *expr5(int), *expr6(int);
|
||||
|
||||
static expr *(*bexpr)(int);
|
||||
|
||||
static expr *rexp0(int critical) {
|
||||
static expr *rexp0(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = rexp1(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == TOKEN_DBL_OR) {
|
||||
|
||||
while (i == TOKEN_DBL_OR)
|
||||
{
|
||||
i = scan(scpriv, tokval);
|
||||
f = rexp1(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
error(ERR_NONFATAL, "`|' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`|' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
|
||||
if (is_just_unknown(e) || is_just_unknown(f))
|
||||
e = unknown_expr();
|
||||
else
|
||||
@ -252,22 +287,27 @@ static expr *rexp0(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *rexp1(int critical) {
|
||||
static expr *rexp1(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = rexp2(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == TOKEN_DBL_XOR) {
|
||||
|
||||
while (i == TOKEN_DBL_XOR)
|
||||
{
|
||||
i = scan(scpriv, tokval);
|
||||
f = rexp2(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`^' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
|
||||
if (is_just_unknown(e) || is_just_unknown(f))
|
||||
e = unknown_expr();
|
||||
else
|
||||
@ -276,19 +316,22 @@ static expr *rexp1(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *rexp2(int critical) {
|
||||
static expr *rexp2(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = rexp3(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == TOKEN_DBL_AND) {
|
||||
while (i == TOKEN_DBL_AND)
|
||||
{
|
||||
i = scan(scpriv, tokval);
|
||||
f = rexp3(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`&' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
@ -300,22 +343,28 @@ static expr *rexp2(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *rexp3(int critical) {
|
||||
static expr *rexp3(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
long v;
|
||||
|
||||
e = expr0(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
|
||||
i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) {
|
||||
i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE)
|
||||
{
|
||||
int j = i;
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr0(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
e = add_vectors (e, scalar_mult(f, -1L, FALSE));
|
||||
switch (j) {
|
||||
|
||||
switch (j)
|
||||
{
|
||||
case TOKEN_EQ: case TOKEN_NE:
|
||||
if (is_unknown(e))
|
||||
v = -1; /* means unknown */
|
||||
@ -343,6 +392,7 @@ static expr *rexp3(int critical) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (v == -1)
|
||||
e = unknown_expr();
|
||||
else
|
||||
@ -351,22 +401,26 @@ static expr *rexp3(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr0(int critical) {
|
||||
static expr *expr0(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr1(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == '|') {
|
||||
|
||||
while (i == '|')
|
||||
{
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr1(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
error(ERR_NONFATAL, "`|' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`|' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
if (is_just_unknown(e) || is_just_unknown(f))
|
||||
e = unknown_expr();
|
||||
else
|
||||
@ -375,19 +429,22 @@ static expr *expr0(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr1(int critical) {
|
||||
static expr *expr1(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr2(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
while (i == '^') {
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr2(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`^' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
@ -399,19 +456,22 @@ static expr *expr1(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr2(int critical) {
|
||||
static expr *expr2(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr3(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
while (i == '&') {
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr3(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "`&' operator may only be applied to"
|
||||
" scalar values");
|
||||
}
|
||||
@ -423,20 +483,24 @@ static expr *expr2(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr3(int critical) {
|
||||
static expr *expr3(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr4(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == TOKEN_SHL || i == TOKEN_SHR) {
|
||||
|
||||
while (i == TOKEN_SHL || i == TOKEN_SHR)
|
||||
{
|
||||
int j = i;
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr4(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f))) {
|
||||
!(is_simple(f) || is_just_unknown(f)))
|
||||
{
|
||||
error(ERR_NONFATAL, "shift operator may only be applied to"
|
||||
" scalar values");
|
||||
} else if (is_just_unknown(e) || is_just_unknown(f)) {
|
||||
@ -454,13 +518,15 @@ static expr *expr3(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr4(int critical) {
|
||||
static expr *expr4(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr5(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == '+' || i == '-') {
|
||||
while (i == '+' || i == '-')
|
||||
{
|
||||
int j = i;
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr5(critical);
|
||||
@ -478,21 +544,24 @@ static expr *expr4(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr5(int critical) {
|
||||
static expr *expr5(int critical)
|
||||
{
|
||||
expr *e, *f;
|
||||
|
||||
e = expr6(critical);
|
||||
if (!e)
|
||||
return NULL;
|
||||
while (i == '*' || i == '/' || i == '%' ||
|
||||
i == TOKEN_SDIV || i == TOKEN_SMOD) {
|
||||
i == TOKEN_SDIV || i == TOKEN_SMOD)
|
||||
{
|
||||
int j = i;
|
||||
i = scan(scpriv, tokval);
|
||||
f = expr6(critical);
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
|
||||
!(is_simple(f) || is_just_unknown(f)))) {
|
||||
!(is_simple(f) || is_just_unknown(f))))
|
||||
{
|
||||
error(ERR_NONFATAL, "division operator may only be applied to"
|
||||
" scalar values");
|
||||
return NULL;
|
||||
@ -548,7 +617,8 @@ static expr *expr5(int critical) {
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr *expr6(int critical) {
|
||||
static expr *expr6(int critical)
|
||||
{
|
||||
long type;
|
||||
expr *e;
|
||||
long label_seg, label_ofs;
|
||||
@ -597,8 +667,10 @@ static expr *expr6(int critical) {
|
||||
}
|
||||
i = scan(scpriv, tokval);
|
||||
return e;
|
||||
} else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
|
||||
i == TOKEN_HERE || i == TOKEN_BASE) {
|
||||
}
|
||||
else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
|
||||
i == TOKEN_HERE || i == TOKEN_BASE)
|
||||
{
|
||||
begintemp();
|
||||
switch (i) {
|
||||
case TOKEN_NUM:
|
||||
@ -613,11 +685,11 @@ static expr *expr6(int critical) {
|
||||
case TOKEN_HERE:
|
||||
case TOKEN_BASE:
|
||||
/*
|
||||
* If "label" begins with "%", this indicates that no
|
||||
* If !location->known, this indicates that no
|
||||
* symbol, Here or Base references are valid because we
|
||||
* are in preprocess-only mode.
|
||||
*/
|
||||
if (*label == '%') {
|
||||
if (!location->known) {
|
||||
error(ERR_NONFATAL,
|
||||
"%s not supported in preprocess-only mode",
|
||||
(i == TOKEN_ID ? "symbol references" :
|
||||
@ -641,11 +713,11 @@ static expr *expr6(int critical) {
|
||||
*/
|
||||
type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
|
||||
if (i == TOKEN_BASE) {
|
||||
label_seg = seg;
|
||||
label_seg = location->segment;
|
||||
label_ofs = 0;
|
||||
} else if (i == TOKEN_HERE || !strcmp(tokval->t_charptr, label)) {
|
||||
label_seg = seg;
|
||||
label_ofs = ofs;
|
||||
} else if (i == TOKEN_HERE) {
|
||||
label_seg = location->segment;
|
||||
label_ofs = location->offset;
|
||||
} else if (!labelfunc(tokval->t_charptr,&label_seg,&label_ofs)) {
|
||||
if (critical == 2) {
|
||||
error (ERR_NONFATAL, "symbol `%s' undefined",
|
||||
@ -656,16 +728,19 @@ static expr *expr6(int critical) {
|
||||
tokval->t_charptr);
|
||||
return NULL;
|
||||
} else {
|
||||
if (forward)
|
||||
*forward = TRUE;
|
||||
if (opflags)
|
||||
*opflags |= 1;
|
||||
type = EXPR_UNKNOWN;
|
||||
label_seg = NO_SEG;
|
||||
label_ofs = 1;
|
||||
}
|
||||
}
|
||||
addtotemp(type, label_ofs);
|
||||
if (label_seg!=NO_SEG)
|
||||
if (label_seg!=NO_SEG) {
|
||||
addtotemp(EXPR_SEGBASE + label_seg, 1L);
|
||||
if (opflags && is_extern (tokval->t_charptr))
|
||||
*opflags |= OPFLAG_EXTERN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i = scan(scpriv, tokval);
|
||||
@ -676,26 +751,17 @@ static expr *expr6(int critical) {
|
||||
}
|
||||
}
|
||||
|
||||
void eval_global_info (struct ofmt *output, lfunc lookup_label) {
|
||||
void eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp)
|
||||
{
|
||||
outfmt = output;
|
||||
labelfunc = lookup_label;
|
||||
}
|
||||
|
||||
void eval_info (char *labelname, long segment, long offset) {
|
||||
if (label != special_empty_string)
|
||||
nasm_free (label);
|
||||
if (labelname)
|
||||
label = nasm_strdup(labelname);
|
||||
else {
|
||||
label = special_empty_string;
|
||||
seg = segment;
|
||||
ofs = offset;
|
||||
}
|
||||
location = locp;
|
||||
}
|
||||
|
||||
expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
|
||||
int *fwref, int critical, efunc report_error,
|
||||
struct eval_hints *hints) {
|
||||
struct eval_hints *hints)
|
||||
{
|
||||
expr *e;
|
||||
expr *f = NULL;
|
||||
|
||||
@ -713,7 +779,7 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
|
||||
scpriv = scprivate;
|
||||
tokval = tv;
|
||||
error = report_error;
|
||||
forward = fwref;
|
||||
opflags = fwref;
|
||||
|
||||
if (tokval->t_type == TOKEN_INVALID)
|
||||
i = scan(scpriv, tokval);
|
||||
@ -748,7 +814,8 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
|
||||
value = reloc_seg(f);
|
||||
if (value == NO_SEG)
|
||||
value = reloc_value(f) | SEG_ABS;
|
||||
else if (!(value & SEG_ABS) && !(value % 2) && critical) {
|
||||
else if (!(value & SEG_ABS) && !(value % 2) && critical)
|
||||
{
|
||||
error(ERR_NONFATAL, "invalid right-hand operand to WRT");
|
||||
return NULL;
|
||||
}
|
||||
|
12
eval.h
12
eval.h
@ -14,15 +14,7 @@
|
||||
* providing segment-base details, and what function can be used to
|
||||
* look labels up.
|
||||
*/
|
||||
void eval_global_info (struct ofmt *output, lfunc lookup_label);
|
||||
|
||||
/*
|
||||
* Called to set the information the evaluator needs: the value of
|
||||
* $ is set from `segment' and `offset' if `labelname' is NULL, and
|
||||
* otherwise the name of the current line's label is set from
|
||||
* `labelname' instead.
|
||||
*/
|
||||
void eval_info (char *labelname, long segment, long offset);
|
||||
void eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp);
|
||||
|
||||
/*
|
||||
* The evaluator itself.
|
||||
@ -31,4 +23,6 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
|
||||
int *fwref, int critical, efunc report_error,
|
||||
struct eval_hints *hints);
|
||||
|
||||
void eval_cleanup(void);
|
||||
|
||||
#endif
|
||||
|
38
float.c
38
float.c
@ -25,9 +25,10 @@
|
||||
* => we only have to worry about _one_ bit shift to the left
|
||||
*/
|
||||
|
||||
static int multiply(unsigned short *to, unsigned short *from) {
|
||||
static int multiply(unsigned short *to, unsigned short *from)
|
||||
{
|
||||
unsigned long temp[MANT_WORDS*2];
|
||||
int i, j;
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<MANT_WORDS*2; i++)
|
||||
temp[i] = 0;
|
||||
@ -56,11 +57,14 @@ static int multiply(unsigned short *to, unsigned short *from) {
|
||||
}
|
||||
|
||||
static void flconvert(char *string, unsigned short *mant, long *exponent,
|
||||
efunc error) {
|
||||
char digits[MANT_DIGITS], *p, *q, *r;
|
||||
unsigned short mult[MANT_WORDS], *m, bit;
|
||||
long tenpwr, twopwr;
|
||||
int extratwos, started, seendot;
|
||||
efunc error)
|
||||
{
|
||||
char digits[MANT_DIGITS];
|
||||
char *p, *q, *r;
|
||||
unsigned short mult[MANT_WORDS], bit;
|
||||
unsigned short * m;
|
||||
long tenpwr, twopwr;
|
||||
int extratwos, started, seendot;
|
||||
|
||||
p = digits;
|
||||
tenpwr = 0;
|
||||
@ -179,9 +183,10 @@ static void flconvert(char *string, unsigned short *mant, long *exponent,
|
||||
/*
|
||||
* Shift a mantissa to the right by i (i < 16) bits.
|
||||
*/
|
||||
static void shr(unsigned short *mant, int i) {
|
||||
static void shr(unsigned short *mant, int i)
|
||||
{
|
||||
unsigned short n = 0, m;
|
||||
int j;
|
||||
int j;
|
||||
|
||||
for (j=0; j<MANT_WORDS; j++) {
|
||||
m = (mant[j] << (16-i)) & 0xFFFF;
|
||||
@ -193,7 +198,8 @@ static void shr(unsigned short *mant, int i) {
|
||||
/*
|
||||
* Round a mantissa off after i words.
|
||||
*/
|
||||
static int round(unsigned short *mant, int i) {
|
||||
static int round(unsigned short *mant, int i)
|
||||
{
|
||||
if (mant[i] & 0x8000) {
|
||||
do {
|
||||
++mant[--i];
|
||||
@ -207,7 +213,8 @@ static int round(unsigned short *mant, int i) {
|
||||
#define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
|
||||
|
||||
static int to_double(char *str, long sign, unsigned char *result,
|
||||
efunc error) {
|
||||
efunc error)
|
||||
{
|
||||
unsigned short mant[MANT_WORDS];
|
||||
long exponent;
|
||||
|
||||
@ -267,7 +274,8 @@ static int to_double(char *str, long sign, unsigned char *result,
|
||||
}
|
||||
|
||||
static int to_float(char *str, long sign, unsigned char *result,
|
||||
efunc error) {
|
||||
efunc error)
|
||||
{
|
||||
unsigned short mant[MANT_WORDS];
|
||||
long exponent;
|
||||
|
||||
@ -320,7 +328,8 @@ static int to_float(char *str, long sign, unsigned char *result,
|
||||
}
|
||||
|
||||
static int to_ldoub(char *str, long sign, unsigned char *result,
|
||||
efunc error) {
|
||||
efunc error)
|
||||
{
|
||||
unsigned short mant[MANT_WORDS];
|
||||
long exponent;
|
||||
|
||||
@ -379,7 +388,8 @@ static int to_ldoub(char *str, long sign, unsigned char *result,
|
||||
}
|
||||
|
||||
int float_const (char *number, long sign, unsigned char *result, int bytes,
|
||||
efunc error) {
|
||||
efunc error)
|
||||
{
|
||||
if (bytes == 4)
|
||||
return to_float (number, sign, result, error);
|
||||
else if (bytes == 8)
|
||||
|
88
insns.dat
88
insns.dat
@ -125,6 +125,7 @@ BTS reg32,reg32 \321\300\2\x0F\xAB\101 386
|
||||
BTS rm16,imm \320\300\2\x0F\xBA\205\25 386
|
||||
BTS rm32,imm \321\300\2\x0F\xBA\205\25 386
|
||||
CALL imm \322\1\xE8\64 8086
|
||||
CALL imm|near \322\1\xE8\64 8086
|
||||
CALL imm|far \322\1\x9A\34\37 8086,ND
|
||||
CALL imm:imm \322\1\x9A\35\30 8086
|
||||
CALL imm16:imm \320\1\x9A\31\30 8086
|
||||
@ -274,6 +275,7 @@ FDIVR fpureg \1\xD8\10\xF8 8086,FPU
|
||||
FDIVR fpu0,fpureg \1\xD8\11\xF8 8086,FPU
|
||||
FDIVRP fpureg \1\xDE\10\xF0 8086,FPU
|
||||
FDIVRP fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
|
||||
FEMMS void \2\x0F\x0E PENT,MMX,FPU
|
||||
FENI void \3\x9B\xDB\xE0 8086,FPU
|
||||
FFREE fpureg \1\xDD\10\xC0 8086,FPU
|
||||
FIADD mem32 \300\1\xDA\200 8086,FPU
|
||||
@ -447,6 +449,7 @@ JCXZ imm \320\1\xE3\50 8086
|
||||
JECXZ imm \321\1\xE3\50 386
|
||||
JMP imm|short \1\xEB\50 8086
|
||||
JMP imm \322\1\xE9\64 8086
|
||||
JMP imm|near \322\1\xE9\64 8086
|
||||
JMP imm|far \322\1\xEA\34\37 8086,ND
|
||||
JMP imm:imm \322\1\xEA\35\30 8086
|
||||
JMP imm16:imm \320\1\xEA\31\30 8086
|
||||
@ -619,9 +622,9 @@ OR rm32,imm \321\300\1\x81\201\41 386,SM
|
||||
OR mem,imm8 \300\1\x80\201\21 8086,SM
|
||||
OR mem,imm16 \320\300\1\x81\201\31 8086,SM
|
||||
OR mem,imm32 \321\300\1\x81\201\41 386,SM
|
||||
OUT imm,reg_al \1\xE6\24 8086
|
||||
OUT imm,reg_ax \320\1\xE7\24 8086
|
||||
OUT imm,reg_eax \321\1\xE7\24 386
|
||||
OUT imm,reg_al \1\xE6\24 8086,SB
|
||||
OUT imm,reg_ax \320\1\xE7\24 8086,SB
|
||||
OUT imm,reg_eax \321\1\xE7\24 386,SB
|
||||
OUT reg_dx,reg_al \1\xEE 8086
|
||||
OUT reg_dx,reg_ax \320\1\xEF 8086
|
||||
OUT reg_dx,reg_eax \321\1\xEF 386
|
||||
@ -656,6 +659,8 @@ PANDN mmxreg,mem \301\2\x0F\xDF\110 PENT,MMX,SM
|
||||
PANDN mmxreg,mmxreg \2\x0F\xDF\110 PENT,MMX
|
||||
PAVEB mmxreg,mem \301\2\x0F\x50\110 PENT,MMX,SM,CYRIX
|
||||
PAVEB mmxreg,mmxreg \2\x0F\x50\110 PENT,MMX,CYRIX
|
||||
PAVGUSB mmxreg,mem \301\2\x0F\x0F\110\01\xBF PENT,MMX,SM,FPU
|
||||
PAVGUSB mmxreg,mmxreg \2\x0F\x0F\110\01\xBF PENT,MMX,FPU
|
||||
PCMPEQB mmxreg,mem \301\2\x0F\x74\110 PENT,MMX,SM
|
||||
PCMPEQB mmxreg,mmxreg \2\x0F\x74\110 PENT,MMX
|
||||
PCMPEQD mmxreg,mem \301\2\x0F\x76\110 PENT,MMX,SM
|
||||
@ -669,15 +674,51 @@ PCMPGTD mmxreg,mmxreg \2\x0F\x66\110 PENT,MMX
|
||||
PCMPGTW mmxreg,mem \301\2\x0F\x65\110 PENT,MMX,SM
|
||||
PCMPGTW mmxreg,mmxreg \2\x0F\x65\110 PENT,MMX
|
||||
PDISTIB mmxreg,mem \301\2\x0F\x54\110 PENT,MMX,SM,CYRIX
|
||||
PF2ID mmxreg,mem \301\2\x0F\x0F\110\01\x1D PENT,MMX,SM,FPU
|
||||
PF2ID mmxreg,mmxreg \2\x0F\x0F\110\01\x1D PENT,MMX,FPU
|
||||
PFACC mmxreg,mem \301\2\x0F\x0F\110\01\xAE PENT,MMX,SM,FPU
|
||||
PFACC mmxreg,mmxreg \2\x0F\x0F\110\01\xAE PENT,MMX,FPU
|
||||
PFADD mmxreg,mem \301\2\x0F\x0F\110\01\x9E PENT,MMX,SM,FPU
|
||||
PFADD mmxreg,mmxreg \2\x0F\x0F\110\01\x9E PENT,MMX,FPU
|
||||
PFCMPEQ mmxreg,mem \301\2\x0F\x0F\110\01\xB0 PENT,MMX,SM,FPU
|
||||
PFCMPEQ mmxreg,mmxreg \2\x0F\x0F\110\01\xB0 PENT,MMX,FPU
|
||||
PFCMPGE mmxreg,mem \301\2\x0F\x0F\110\01\x90 PENT,MMX,SM,FPU
|
||||
PFCMPGE mmxreg,mmxreg \2\x0F\x0F\110\01\x90 PENT,MMX,FPU
|
||||
PFCMPGT mmxreg,mem \301\2\x0F\x0F\110\01\xA0 PENT,MMX,SM,FPU
|
||||
PFCMPGT mmxreg,mmxreg \2\x0F\x0F\110\01\xA0 PENT,MMX,FPU
|
||||
PFMAX mmxreg,mem \301\2\x0F\x0F\110\01\xA4 PENT,MMX,SM,FPU
|
||||
PFMAX mmxreg,mmxreg \2\x0F\x0F\110\01\xA4 PENT,MMX,FPU
|
||||
PFMIN mmxreg,mem \301\2\x0F\x0F\110\01\x94 PENT,MMX,SM,FPU
|
||||
PFMIN mmxreg,mmxreg \2\x0F\x0F\110\01\x94 PENT,MMX,FPU
|
||||
PFMUL mmxreg,mem \301\2\x0F\x0F\110\01\xB4 PENT,MMX,SM,FPU
|
||||
PFMUL mmxreg,mmxreg \2\x0F\x0F\110\01\xB4 PENT,MMX,FPU
|
||||
PFRCP mmxreg,mem \301\2\x0F\x0F\110\01\x96 PENT,MMX,SM,FPU
|
||||
PFRCP mmxreg,mmxreg \2\x0F\x0F\110\01\x96 PENT,MMX,FPU
|
||||
PFRCPIT1 mmxreg,mem \301\2\x0F\x0F\110\01\xA6 PENT,MMX,SM,FPU
|
||||
PFRCPIT1 mmxreg,mmxreg \2\x0F\x0F\110\01\xA6 PENT,MMX,FPU
|
||||
PFRCPIT2 mmxreg,mem \301\2\x0F\x0F\110\01\xB6 PENT,MMX,SM,FPU
|
||||
PFRCPIT2 mmxreg,mmxreg \2\x0F\x0F\110\01\xB6 PENT,MMX,FPU
|
||||
PFRSQIT1 mmxreg,mem \301\2\x0F\x0F\110\01\xA7 PENT,MMX,SM,FPU
|
||||
PFRSQIT1 mmxreg,mmxreg \2\x0F\x0F\110\01\xA7 PENT,MMX,FPU
|
||||
PFRSQRT mmxreg,mem \301\2\x0F\x0F\110\01\x97 PENT,MMX,SM,FPU
|
||||
PFRSQRT mmxreg,mmxreg \2\x0F\x0F\110\01\x97 PENT,MMX,FPU
|
||||
PFSUB mmxreg,mem \301\2\x0F\x0F\110\01\x9A PENT,MMX,SM,FPU
|
||||
PFSUB mmxreg,mmxreg \2\x0F\x0F\110\01\x9A PENT,MMX,FPU
|
||||
PFSUBR mmxreg,mem \301\2\x0F\x0F\110\01\xAA PENT,MMX,SM,FPU
|
||||
PFSUBR mmxreg,mmxreg \2\x0F\x0F\110\01\xAA PENT,MMX,FPU
|
||||
PI2FD mmxreg,mem \301\2\x0F\x0F\110\01\x0D PENT,MMX,SM,FPU
|
||||
PI2FD mmxreg,mmxreg \2\x0F\x0F\110\01\x0D PENT,MMX,FPU
|
||||
PMACHRIW mmxreg,mem \301\2\x0F\x5E\110 PENT,MMX,SM,CYRIX
|
||||
PMADDWD mmxreg,mem \301\2\x0F\xF5\110 PENT,MMX,SM
|
||||
PMADDWD mmxreg,mmxreg \2\x0F\xF5\110 PENT,MMX
|
||||
PMAGW mmxreg,mem \301\2\x0F\x52\110 PENT,MMX,SM,CYRIX
|
||||
PMAGW mmxreg,mmxreg \2\x0F\x52\110 PENT,MMX,CYRIX
|
||||
PMULHRW mmxreg,mem \301\2\x0F\x59\110 PENT,MMX,SM,CYRIX
|
||||
PMULHRW mmxreg,mmxreg \2\x0F\x59\110 PENT,MMX,CYRIX
|
||||
PMULHRIW mmxreg,mem \301\2\x0F\x5D\110 PENT,MMX,SM,CYRIX
|
||||
PMULHRIW mmxreg,mmxreg \2\x0F\x5D\110 PENT,MMX,CYRIX
|
||||
PMULHRWA mmxreg,mem \301\2\x0F\x0F\110\1\xB7 PENT,MMX,SM,FPU
|
||||
PMULHRWA mmxreg,mmxreg \2\x0F\x0F\110\1\xB7 PENT,MMX,FPU
|
||||
PMULHRWC mmxreg,mem \301\2\x0F\x59\110 PENT,MMX,SM,CYRIX
|
||||
PMULHRWC mmxreg,mmxreg \2\x0F\x59\110 PENT,MMX,CYRIX
|
||||
PMULHW mmxreg,mem \301\2\x0F\xE5\110 PENT,MMX,SM
|
||||
PMULHW mmxreg,mmxreg \2\x0F\xE5\110 PENT,MMX
|
||||
PMULLW mmxreg,mem \301\2\x0F\xD5\110 PENT,MMX,SM
|
||||
@ -701,6 +742,8 @@ POPFD void \321\1\x9D 386
|
||||
POPFW void \320\1\x9D 186
|
||||
POR mmxreg,mem \301\2\x0F\xEB\110 PENT,MMX,SM
|
||||
POR mmxreg,mmxreg \2\x0F\xEB\110 PENT,MMX
|
||||
PREFETCH mem \2\x0F\x0D\200 PENT,MMX,SM,FPU
|
||||
PREFETCHW mem \2\x0F\x0D\201 PENT,MMX,SM,FPU
|
||||
PSLLD mmxreg,mem \301\2\x0F\xF2\110 PENT,MMX,SM
|
||||
PSLLD mmxreg,mmxreg \2\x0F\xF2\110 PENT,MMX
|
||||
PSLLD mmxreg,imm \2\x0F\x72\206\25 PENT,MMX
|
||||
@ -772,19 +815,19 @@ PXOR mmxreg,mem \301\2\x0F\xEF\110 PENT,MMX,SM
|
||||
PXOR mmxreg,mmxreg \2\x0F\xEF\110 PENT,MMX
|
||||
RCL rm8,unity \300\1\xD0\202 8086
|
||||
RCL rm8,reg_cl \300\1\xD2\202 8086
|
||||
RCL rm8,imm \300\1\xC0\202\25 286,SB
|
||||
RCL rm8,imm \300\1\xC0\202\25 186,SB
|
||||
RCL rm16,unity \320\300\1\xD1\202 8086
|
||||
RCL rm16,reg_cl \320\300\1\xD3\202 8086
|
||||
RCL rm16,imm \320\300\1\xC1\202\25 286,SB
|
||||
RCL rm16,imm \320\300\1\xC1\202\25 186,SB
|
||||
RCL rm32,unity \321\300\1\xD1\202 386
|
||||
RCL rm32,reg_cl \321\300\1\xD3\202 386
|
||||
RCL rm32,imm \321\300\1\xC1\202\25 386,SB
|
||||
RCR rm8,unity \300\1\xD0\203 8086
|
||||
RCR rm8,reg_cl \300\1\xD2\203 8086
|
||||
RCR rm8,imm \300\1\xC0\203\25 286,SB
|
||||
RCR rm8,imm \300\1\xC0\203\25 186,SB
|
||||
RCR rm16,unity \320\300\1\xD1\203 8086
|
||||
RCR rm16,reg_cl \320\300\1\xD3\203 8086
|
||||
RCR rm16,imm \320\300\1\xC1\203\25 286,SB
|
||||
RCR rm16,imm \320\300\1\xC1\203\25 186,SB
|
||||
RCR rm32,unity \321\300\1\xD1\203 386
|
||||
RCR rm32,reg_cl \321\300\1\xD3\203 386
|
||||
RCR rm32,imm \321\300\1\xC1\203\25 386,SB
|
||||
@ -804,19 +847,19 @@ RETN void \1\xC3 8086
|
||||
RETN imm \1\xC2\30 8086
|
||||
ROL rm8,unity \300\1\xD0\200 8086
|
||||
ROL rm8,reg_cl \300\1\xD2\200 8086
|
||||
ROL rm8,imm \300\1\xC0\200\25 286,SB
|
||||
ROL rm8,imm \300\1\xC0\200\25 186,SB
|
||||
ROL rm16,unity \320\300\1\xD1\200 8086
|
||||
ROL rm16,reg_cl \320\300\1\xD3\200 8086
|
||||
ROL rm16,imm \320\300\1\xC1\200\25 286,SB
|
||||
ROL rm16,imm \320\300\1\xC1\200\25 186,SB
|
||||
ROL rm32,unity \321\300\1\xD1\200 386
|
||||
ROL rm32,reg_cl \321\300\1\xD3\200 386
|
||||
ROL rm32,imm \321\300\1\xC1\200\25 386,SB
|
||||
ROR rm8,unity \300\1\xD0\201 8086
|
||||
ROR rm8,reg_cl \300\1\xD2\201 8086
|
||||
ROR rm8,imm \300\1\xC0\201\25 286,SB
|
||||
ROR rm8,imm \300\1\xC0\201\25 186,SB
|
||||
ROR rm16,unity \320\300\1\xD1\201 8086
|
||||
ROR rm16,reg_cl \320\300\1\xD3\201 8086
|
||||
ROR rm16,imm \320\300\1\xC1\201\25 286,SB
|
||||
ROR rm16,imm \320\300\1\xC1\201\25 186,SB
|
||||
ROR rm32,unity \321\300\1\xD1\201 386
|
||||
ROR rm32,reg_cl \321\300\1\xD3\201 386
|
||||
ROR rm32,imm \321\300\1\xC1\201\25 386,SB
|
||||
@ -824,20 +867,20 @@ RSM void \2\x0F\xAA PENT
|
||||
SAHF void \1\x9E 8086
|
||||
SAL rm8,unity \300\1\xD0\204 8086,ND
|
||||
SAL rm8,reg_cl \300\1\xD2\204 8086,ND
|
||||
SAL rm8,imm \300\1\xC0\204\25 286,ND,SB
|
||||
SAL rm8,imm \300\1\xC0\204\25 186,ND,SB
|
||||
SAL rm16,unity \320\300\1\xD1\204 8086,ND
|
||||
SAL rm16,reg_cl \320\300\1\xD3\204 8086,ND
|
||||
SAL rm16,imm \320\300\1\xC1\204\25 286,ND,SB
|
||||
SAL rm16,imm \320\300\1\xC1\204\25 186,ND,SB
|
||||
SAL rm32,unity \321\300\1\xD1\204 386,ND
|
||||
SAL rm32,reg_cl \321\300\1\xD3\204 386,ND
|
||||
SAL rm32,imm \321\300\1\xC1\204\25 386,ND,SB
|
||||
SALC void \1\xD6 8086,UNDOC
|
||||
SAR rm8,unity \300\1\xD0\207 8086
|
||||
SAR rm8,reg_cl \300\1\xD2\207 8086
|
||||
SAR rm8,imm \300\1\xC0\207\25 286,SB
|
||||
SAR rm8,imm \300\1\xC0\207\25 186,SB
|
||||
SAR rm16,unity \320\300\1\xD1\207 8086
|
||||
SAR rm16,reg_cl \320\300\1\xD3\207 8086
|
||||
SAR rm16,imm \320\300\1\xC1\207\25 286,SB
|
||||
SAR rm16,imm \320\300\1\xC1\207\25 186,SB
|
||||
SAR rm32,unity \321\300\1\xD1\207 386
|
||||
SAR rm32,reg_cl \321\300\1\xD3\207 386
|
||||
SAR rm32,imm \321\300\1\xC1\207\25 386,SB
|
||||
@ -870,10 +913,10 @@ SCASW void \320\1\xAF 8086
|
||||
SGDT mem \300\2\x0F\x01\200 286,PRIV
|
||||
SHL rm8,unity \300\1\xD0\204 8086
|
||||
SHL rm8,reg_cl \300\1\xD2\204 8086
|
||||
SHL rm8,imm \300\1\xC0\204\25 286,SB
|
||||
SHL rm8,imm \300\1\xC0\204\25 186,SB
|
||||
SHL rm16,unity \320\300\1\xD1\204 8086
|
||||
SHL rm16,reg_cl \320\300\1\xD3\204 8086
|
||||
SHL rm16,imm \320\300\1\xC1\204\25 286,SB
|
||||
SHL rm16,imm \320\300\1\xC1\204\25 186,SB
|
||||
SHL rm32,unity \321\300\1\xD1\204 386
|
||||
SHL rm32,reg_cl \321\300\1\xD3\204 386
|
||||
SHL rm32,imm \321\300\1\xC1\204\25 386,SB
|
||||
@ -887,10 +930,10 @@ SHLD mem,reg32,reg_cl \300\321\2\x0F\xA5\101 386,SM
|
||||
SHLD reg32,reg32,reg_cl \300\321\2\x0F\xA5\101 386
|
||||
SHR rm8,unity \300\1\xD0\205 8086
|
||||
SHR rm8,reg_cl \300\1\xD2\205 8086
|
||||
SHR rm8,imm \300\1\xC0\205\25 286,SB
|
||||
SHR rm8,imm \300\1\xC0\205\25 186,SB
|
||||
SHR rm16,unity \320\300\1\xD1\205 8086
|
||||
SHR rm16,reg_cl \320\300\1\xD3\205 8086
|
||||
SHR rm16,imm \320\300\1\xC1\205\25 286,SB
|
||||
SHR rm16,imm \320\300\1\xC1\205\25 186,SB
|
||||
SHR rm32,unity \321\300\1\xD1\205 386
|
||||
SHR rm32,reg_cl \321\300\1\xD3\205 386
|
||||
SHR rm32,imm \321\300\1\xC1\205\25 386,SB
|
||||
@ -948,6 +991,9 @@ TEST mem,reg16 \320\300\1\x85\101 8086,SM
|
||||
TEST reg16,reg16 \320\300\1\x85\101 8086
|
||||
TEST mem,reg32 \321\300\1\x85\101 386,SM
|
||||
TEST reg32,reg32 \321\300\1\x85\101 386
|
||||
TEST reg8,mem \301\1\x84\110 8086,SM
|
||||
TEST reg16,mem \320\301\1\x85\110 8086,SM
|
||||
TEST reg32,mem \321\301\1\x85\110 386,SM
|
||||
TEST reg_al,imm \1\xA8\21 8086,SM
|
||||
TEST reg_ax,imm \320\1\xA9\31 8086,SM
|
||||
TEST reg_eax,imm \321\1\xA9\41 386,SM
|
||||
|
117
labels.c
117
labels.c
@ -43,7 +43,7 @@ union label { /* actual label structures */
|
||||
struct {
|
||||
long segment, offset;
|
||||
char *label, *special;
|
||||
int is_global;
|
||||
int is_global, is_norm;
|
||||
} defn;
|
||||
struct {
|
||||
long movingon, dummy;
|
||||
@ -74,7 +74,8 @@ static int initialised = FALSE;
|
||||
* given label name. Creates a new one, if it isn't found, and if
|
||||
* `create' is TRUE.
|
||||
*/
|
||||
static union label *find_label (char *label, int create) {
|
||||
static union label *find_label (char *label, int create)
|
||||
{
|
||||
int hash = 0;
|
||||
char *p, *prev;
|
||||
int prevlen;
|
||||
@ -117,11 +118,13 @@ static union label *find_label (char *label, int create) {
|
||||
lfree[hash]->defn.special = NULL;
|
||||
lfree[hash]->defn.is_global = NOT_DEFINED_YET;
|
||||
return lfree[hash]++;
|
||||
} else
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lookup_label (char *label, long *segment, long *offset) {
|
||||
int lookup_label (char *label, long *segment, long *offset)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
if (!initialised)
|
||||
@ -132,11 +135,13 @@ int lookup_label (char *label, long *segment, long *offset) {
|
||||
*segment = lptr->defn.segment;
|
||||
*offset = lptr->defn.offset;
|
||||
return 1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_extern (char *label) {
|
||||
int is_extern (char *label)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
if (!initialised)
|
||||
@ -149,22 +154,48 @@ int is_extern (char *label) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void define_label_stub (char *label, efunc error) {
|
||||
void redefine_label (char *label, long segment, long offset, char *special,
|
||||
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
/* This routine possibly ought to check for phase errors. Most assemblers
|
||||
* check for phase errors at this point. I don't know whether phase errors
|
||||
* are even possible, nor whether they are checked somewhere else
|
||||
*/
|
||||
|
||||
(void) segment; /* Don't warn that this parameter is unused */
|
||||
(void) offset; /* Don't warn that this parameter is unused */
|
||||
(void) special; /* Don't warn that this parameter is unused */
|
||||
(void) is_norm; /* Don't warn that this parameter is unused */
|
||||
(void) isextrn; /* Don't warn that this parameter is unused */
|
||||
(void) ofmt; /* Don't warn that this parameter is unused */
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!strncmp(label, "debugdump", 9))
|
||||
fprintf(stderr, "debug: redefine_label (%s, %ld, %08lx, %s, %d, %d)\n",
|
||||
label, segment, offset, special, is_norm, isextrn);
|
||||
#endif
|
||||
|
||||
if (!islocal(label)) {
|
||||
lptr = find_label (label, 1);
|
||||
if (!lptr)
|
||||
error (ERR_PANIC, "can't find label `%s' on pass two", label);
|
||||
if (*label != '.')
|
||||
if (*label != '.' && lptr->defn.is_norm)
|
||||
prevlabel = lptr->defn.label;
|
||||
}
|
||||
}
|
||||
|
||||
void define_label (char *label, long segment, long offset, char *special,
|
||||
int is_norm, int isextrn, struct ofmt *ofmt, efunc error) {
|
||||
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!strncmp(label, "debugdump", 9))
|
||||
fprintf(stderr, "debug: define_label (%s, %ld, %08lx, %s, %d, %d)\n",
|
||||
label, segment, offset, special, is_norm, isextrn);
|
||||
#endif
|
||||
lptr = find_label (label, 1);
|
||||
if (lptr->defn.is_global & DEFINED_BIT) {
|
||||
error(ERR_NONFATAL, "symbol `%s' redefined", label);
|
||||
@ -182,14 +213,19 @@ void define_label (char *label, long segment, long offset, char *special,
|
||||
|
||||
lptr->defn.segment = segment;
|
||||
lptr->defn.offset = offset;
|
||||
lptr->defn.is_norm = (label[0] != '.' && is_norm);
|
||||
|
||||
ofmt->symdef (lptr->defn.label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
ofmt->current_dfmt->debug_deflabel (label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
}
|
||||
|
||||
void define_common (char *label, long segment, long size, char *special,
|
||||
struct ofmt *ofmt, efunc error) {
|
||||
struct ofmt *ofmt, efunc error)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
lptr = find_label (label, 1);
|
||||
@ -210,9 +246,12 @@ void define_common (char *label, long segment, long size, char *special,
|
||||
|
||||
ofmt->symdef (lptr->defn.label, segment, size, 2,
|
||||
special ? special : lptr->defn.special);
|
||||
ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
|
||||
special ? special : lptr->defn.special);
|
||||
}
|
||||
|
||||
void declare_as_global (char *label, char *special, efunc error) {
|
||||
void declare_as_global (char *label, char *special, efunc error)
|
||||
{
|
||||
union label *lptr;
|
||||
|
||||
if (islocal(label)) {
|
||||
@ -237,7 +276,8 @@ void declare_as_global (char *label, char *special, efunc error) {
|
||||
}
|
||||
}
|
||||
|
||||
int init_labels (void) {
|
||||
int init_labels (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<LABEL_HASHES; i++) {
|
||||
@ -248,7 +288,9 @@ int init_labels (void) {
|
||||
lfree[i] = ltab[i];
|
||||
}
|
||||
|
||||
perm_head = perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
|
||||
perm_head =
|
||||
perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
|
||||
|
||||
if (!perm_head)
|
||||
return -1;
|
||||
|
||||
@ -263,7 +305,8 @@ int init_labels (void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_labels (void) {
|
||||
void cleanup_labels (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
initialised = FALSE;
|
||||
@ -288,7 +331,8 @@ void cleanup_labels (void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void init_block (union label *blk) {
|
||||
static void init_block (union label *blk)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j=0; j<LABEL_BLOCK-1; j++)
|
||||
@ -297,7 +341,8 @@ static void init_block (union label *blk) {
|
||||
blk[LABEL_BLOCK-1].admin.next = NULL;
|
||||
}
|
||||
|
||||
static char *perm_copy (char *string1, char *string2) {
|
||||
static char *perm_copy (char *string1, char *string2)
|
||||
{
|
||||
char *p, *q;
|
||||
int len = strlen(string1)+strlen(string2)+1;
|
||||
|
||||
@ -310,8 +355,46 @@ static char *perm_copy (char *string1, char *string2) {
|
||||
}
|
||||
p = q = perm_tail->data + perm_tail->usage;
|
||||
while ( (*q = *string1++) ) q++;
|
||||
while ( (*q++ = *string2++) );
|
||||
while ( (*q++ = *string2++) ) ;
|
||||
perm_tail->usage = q - perm_tail->data;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notes regarding bug involving redefinition of external segments.
|
||||
*
|
||||
* Up to and including v0.97, the following code didn't work. From 0.97
|
||||
* developers release 2 onwards, it will generate an error.
|
||||
*
|
||||
* EXTERN extlabel
|
||||
* newlabel EQU extlabel + 1
|
||||
*
|
||||
* The results of allowing this code through are that two import records
|
||||
* are generated, one for 'extlabel' and one for 'newlabel'.
|
||||
*
|
||||
* The reason for this is an inadequacy in the defined interface between
|
||||
* the label manager and the output formats. The problem lies in how the
|
||||
* output format driver tells that a label is an external label for which
|
||||
* a label import record must be produced. Most (all except bin?) produce
|
||||
* the record if the segment number of the label is not one of the internal
|
||||
* segments that the output driver is producing.
|
||||
*
|
||||
* A simple fix to this would be to make the output formats keep track of
|
||||
* which symbols they've produced import records for, and make them not
|
||||
* produce import records for segments that are already defined.
|
||||
*
|
||||
* The best way, which is slightly harder but reduces duplication of code
|
||||
* and should therefore make the entire system smaller and more stable is
|
||||
* to change the interface between assembler, define_label(), and
|
||||
* the output module. The changes that are needed are:
|
||||
*
|
||||
* The semantics of the 'isextern' flag passed to define_label() need
|
||||
* examining. This information may or may not tell us what we need to
|
||||
* know (ie should we be generating an import record at this point for this
|
||||
* label). If these aren't the semantics, the semantics should be changed
|
||||
* to this.
|
||||
*
|
||||
* The output module interface needs changing, so that the `isextern' flag
|
||||
* is passed to the module, so that it can be easily tested for.
|
||||
*/
|
||||
|
3
labels.h
3
labels.h
@ -10,9 +10,10 @@ int lookup_label (char *label, long *segment, long *offset);
|
||||
int is_extern (char *label);
|
||||
void define_label (char *label, long segment, long offset, char *special,
|
||||
int is_norm, int isextrn, struct ofmt *ofmt, efunc error);
|
||||
void redefine_label (char *label, long segment, long offset, char *special,
|
||||
int is_norm, int isextrn, struct ofmt *ofmt, efunc error);
|
||||
void define_common (char *label, long segment, long size, char *special,
|
||||
struct ofmt *ofmt, efunc error);
|
||||
void define_label_stub (char *label, efunc error);
|
||||
void declare_as_global (char *label, char *special, efunc error);
|
||||
int init_labels (void);
|
||||
void cleanup_labels (void);
|
||||
|
84
listing.c
84
listing.c
@ -50,31 +50,39 @@ static int listlevel, listlevel_e;
|
||||
|
||||
static FILE *listfp;
|
||||
|
||||
static void list_emit (void) {
|
||||
static void list_emit (void)
|
||||
{
|
||||
if (!listlinep && !listdata[0])
|
||||
return;
|
||||
|
||||
fprintf(listfp, "%6ld ", ++listlineno);
|
||||
|
||||
if (listdata[0])
|
||||
fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT+1, listdata);
|
||||
else
|
||||
fprintf(listfp, "%*s", LIST_HEXBIT+10, "");
|
||||
|
||||
if (listlevel_e)
|
||||
fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e);
|
||||
else if (listlinep)
|
||||
fprintf(listfp, " ");
|
||||
|
||||
if (listlinep)
|
||||
fprintf(listfp, " %s", listline);
|
||||
|
||||
fputc('\n', listfp);
|
||||
listlinep = FALSE;
|
||||
listdata[0] = '\0';
|
||||
}
|
||||
|
||||
static void list_init (char *fname, efunc error) {
|
||||
static void list_init (char *fname, efunc error)
|
||||
{
|
||||
listfp = fopen (fname, "w");
|
||||
if (!listfp) {
|
||||
error (ERR_NONFATAL, "unable to open listing file `%s'", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
*listline = '\0';
|
||||
listlineno = 0;
|
||||
listp = TRUE;
|
||||
@ -86,19 +94,23 @@ static void list_init (char *fname, efunc error) {
|
||||
mistack->inhibiting = TRUE;
|
||||
}
|
||||
|
||||
static void list_cleanup (void) {
|
||||
static void list_cleanup (void)
|
||||
{
|
||||
if (!listp)
|
||||
return;
|
||||
|
||||
while (mistack) {
|
||||
MacroInhibit *temp = mistack;
|
||||
mistack = temp->next;
|
||||
nasm_free (temp);
|
||||
}
|
||||
|
||||
list_emit();
|
||||
fclose (listfp);
|
||||
}
|
||||
|
||||
static void list_out (long offset, char *str) {
|
||||
static void list_out (long offset, char *str)
|
||||
{
|
||||
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
|
||||
strcat(listdata, "-");
|
||||
list_emit();
|
||||
@ -108,7 +120,8 @@ static void list_out (long offset, char *str) {
|
||||
strcat(listdata, str);
|
||||
}
|
||||
|
||||
static void list_output (long offset, void *data, unsigned long type) {
|
||||
static void list_output (long offset, void *data, unsigned long type)
|
||||
{
|
||||
long typ, size;
|
||||
|
||||
if (!listp || suppress)
|
||||
@ -117,20 +130,25 @@ static void list_output (long offset, void *data, unsigned long type) {
|
||||
typ = type & OUT_TYPMASK;
|
||||
size = type & OUT_SIZMASK;
|
||||
|
||||
if (typ == OUT_RAWDATA) {
|
||||
if (typ == OUT_RAWDATA)
|
||||
{
|
||||
unsigned char *p = data;
|
||||
char q[3];
|
||||
while (size--) {
|
||||
while (size--)
|
||||
{
|
||||
HEX (q, *p);
|
||||
q[2] = '\0';
|
||||
list_out (offset++, q);
|
||||
p++;
|
||||
}
|
||||
} else if (typ == OUT_ADDRESS) {
|
||||
}
|
||||
else if (typ == OUT_ADDRESS)
|
||||
{
|
||||
unsigned long d = *(long *)data;
|
||||
char q[11];
|
||||
unsigned char p[4], *r = p;
|
||||
if (size == 4) {
|
||||
if (size == 4)
|
||||
{
|
||||
q[0] = '['; q[9] = ']'; q[10] = '\0';
|
||||
WRITELONG (r, d);
|
||||
HEX (q+1, p[0]);
|
||||
@ -138,14 +156,17 @@ static void list_output (long offset, void *data, unsigned long type) {
|
||||
HEX (q+5, p[2]);
|
||||
HEX (q+7, p[3]);
|
||||
list_out (offset, q);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
q[0] = '['; q[5] = ']'; q[6] = '\0';
|
||||
WRITESHORT (r, d);
|
||||
HEX (q+1, p[0]);
|
||||
HEX (q+3, p[1]);
|
||||
list_out (offset, q);
|
||||
}
|
||||
} else if (typ == OUT_REL2ADR) {
|
||||
}
|
||||
else if (typ == OUT_REL2ADR)
|
||||
{
|
||||
unsigned long d = *(long *)data;
|
||||
char q[11];
|
||||
unsigned char p[4], *r = p;
|
||||
@ -154,7 +175,9 @@ static void list_output (long offset, void *data, unsigned long type) {
|
||||
HEX (q+1, p[0]);
|
||||
HEX (q+3, p[1]);
|
||||
list_out (offset, q);
|
||||
} else if (typ == OUT_REL4ADR) {
|
||||
}
|
||||
else if (typ == OUT_REL4ADR)
|
||||
{
|
||||
unsigned long d = *(long *)data;
|
||||
char q[11];
|
||||
unsigned char p[4], *r = p;
|
||||
@ -165,17 +188,22 @@ static void list_output (long offset, void *data, unsigned long type) {
|
||||
HEX (q+5, p[2]);
|
||||
HEX (q+7, p[3]);
|
||||
list_out (offset, q);
|
||||
} else if (typ == OUT_RESERVE) {
|
||||
}
|
||||
else if (typ == OUT_RESERVE)
|
||||
{
|
||||
char q[20];
|
||||
sprintf(q, "<res %08lX>", size);
|
||||
list_out (offset, q);
|
||||
}
|
||||
}
|
||||
|
||||
static void list_line (int type, char *line) {
|
||||
static void list_line (int type, char *line)
|
||||
{
|
||||
if (!listp)
|
||||
return;
|
||||
if (mistack && mistack->inhibiting) {
|
||||
|
||||
if (mistack && mistack->inhibiting)
|
||||
{
|
||||
if (type == LIST_MACRO)
|
||||
return;
|
||||
else { /* pop the m i stack */
|
||||
@ -191,22 +219,29 @@ static void list_line (int type, char *line) {
|
||||
listlevel_e = listlevel;
|
||||
}
|
||||
|
||||
static void list_uplevel (int type) {
|
||||
static void list_uplevel (int type)
|
||||
{
|
||||
if (!listp)
|
||||
return;
|
||||
if (type == LIST_INCBIN || type == LIST_TIMES) {
|
||||
if (type == LIST_INCBIN || type == LIST_TIMES)
|
||||
{
|
||||
suppress |= (type == LIST_INCBIN ? 1 : 2);
|
||||
list_out (listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
|
||||
return;
|
||||
}
|
||||
|
||||
listlevel++;
|
||||
if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
|
||||
|
||||
if (mistack && mistack->inhibiting && type == LIST_INCLUDE)
|
||||
{
|
||||
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
|
||||
temp->next = mistack;
|
||||
temp->level = listlevel;
|
||||
temp->inhibiting = FALSE;
|
||||
mistack = temp;
|
||||
} else if (type == LIST_MACRO_NOLIST) {
|
||||
}
|
||||
else if (type == LIST_MACRO_NOLIST)
|
||||
{
|
||||
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
|
||||
temp->next = mistack;
|
||||
temp->level = listlevel;
|
||||
@ -215,15 +250,20 @@ static void list_uplevel (int type) {
|
||||
}
|
||||
}
|
||||
|
||||
static void list_downlevel (int type) {
|
||||
static void list_downlevel (int type)
|
||||
{
|
||||
if (!listp)
|
||||
return;
|
||||
if (type == LIST_INCBIN || type == LIST_TIMES) {
|
||||
|
||||
if (type == LIST_INCBIN || type == LIST_TIMES)
|
||||
{
|
||||
suppress &= ~(type == LIST_INCBIN ? 1 : 2);
|
||||
return;
|
||||
}
|
||||
|
||||
listlevel--;
|
||||
while (mistack && mistack->level > listlevel) {
|
||||
while (mistack && mistack->level > listlevel)
|
||||
{
|
||||
MacroInhibit *temp = mistack;
|
||||
mistack = temp->next;
|
||||
nasm_free (temp);
|
||||
|
20
names.c
20
names.c
@ -28,7 +28,9 @@ static char *insn_names[] = { /* instruction names, as strings */
|
||||
"fcmovbe", "fcmove", "fcmovnb", "fcmovnbe", "fcmovne",
|
||||
"fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp",
|
||||
"fcompp", "fcos", "fdecstp", "fdisi", "fdiv", "fdivp", "fdivr",
|
||||
"fdivrp", "feni", "ffree", "fiadd", "ficom", "ficomp", "fidiv",
|
||||
"fdivrp",
|
||||
"femms",
|
||||
"feni", "ffree", "fiadd", "ficom", "ficomp", "fidiv",
|
||||
"fidivr", "fild", "fimul", "fincstp", "finit", "fist", "fistp",
|
||||
"fisub", "fisubr", "fld", "fld1", "fldcw", "fldenv", "fldl2e",
|
||||
"fldl2t", "fldlg2", "fldln2", "fldpi", "fldz", "fmul", "fmulp",
|
||||
@ -40,7 +42,7 @@ static char *insn_names[] = { /* instruction names, as strings */
|
||||
"fucomi", "fucomip", "fucomp", "fucompp", "fxam", "fxch",
|
||||
"fxtract", "fyl2x", "fyl2xp1", "hlt", "ibts", "icebp", "idiv",
|
||||
"imul", "in", "inc", "incbin", "insb", "insd", "insw", "int",
|
||||
"int1", "int01", "int3", "into", "invd", "invlpg", "iret",
|
||||
"int01", "int1", "int3", "into", "invd", "invlpg", "iret",
|
||||
"iretd", "iretw", "jcxz", "jecxz", "jmp", "lahf", "lar", "lds",
|
||||
"lea", "leave", "les", "lfs", "lgdt", "lgs", "lidt", "lldt",
|
||||
"lmsw", "loadall", "loadall286", "lodsb", "lodsd", "lodsw",
|
||||
@ -49,12 +51,18 @@ static char *insn_names[] = { /* instruction names, as strings */
|
||||
"movsx", "movzx", "mul", "neg", "nop", "not", "or", "out",
|
||||
"outsb", "outsd", "outsw", "packssdw", "packsswb", "packuswb",
|
||||
"paddb", "paddd", "paddsb", "paddsiw", "paddsw", "paddusb",
|
||||
"paddusw", "paddw", "pand", "pandn", "paveb", "pcmpeqb",
|
||||
"paddusw", "paddw", "pand", "pandn", "paveb",
|
||||
"pavgusb", "pcmpeqb",
|
||||
"pcmpeqd", "pcmpeqw", "pcmpgtb", "pcmpgtd", "pcmpgtw",
|
||||
"pdistib", "pmachriw", "pmaddwd", "pmagw", "pmulhrw",
|
||||
"pmulhriw", "pmulhw", "pmullw", "pmvgezb", "pmvlzb", "pmvnzb",
|
||||
"pdistib",
|
||||
"pf2id", "pfacc", "pfadd", "pfcmpeq", "pfcmpge", "pfcmpgt",
|
||||
"pfmax", "pfmin", "pfmul", "pfrcp", "pfrcpit1", "pfrcpit2",
|
||||
"pfrsqit1", "pfrsqrt", "pfsub", "pfsubr", "pi2fd",
|
||||
"pmachriw", "pmaddwd", "pmagw", "pmulhriw", "pmulhrwa", "pmulhrwc",
|
||||
"pmulhw", "pmullw", "pmvgezb", "pmvlzb", "pmvnzb",
|
||||
"pmvzb", "pop", "popa", "popad", "popaw", "popf", "popfd",
|
||||
"popfw", "por", "pslld", "psllq", "psllw", "psrad", "psraw",
|
||||
"popfw", "por",
|
||||
"prefetch", "prefetchw", "pslld", "psllq", "psllw", "psrad", "psraw",
|
||||
"psrld", "psrlq", "psrlw", "psubb", "psubd", "psubsb",
|
||||
"psubsiw", "psubsw", "psubusb", "psubusw", "psubw", "punpckhbw",
|
||||
"punpckhdq", "punpckhwd", "punpcklbw", "punpckldq", "punpcklwd",
|
||||
|
186
nasm.h
186
nasm.h
@ -12,8 +12,8 @@
|
||||
#define NASM_NASM_H
|
||||
|
||||
#define NASM_MAJOR_VER 0
|
||||
#define NASM_MINOR_VER 97
|
||||
#define NASM_VER "0.97"
|
||||
#define NASM_MINOR_VER 98
|
||||
#define NASM_VER "0.98 pre-release 3"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
@ -72,9 +72,6 @@ typedef void (*efunc) (int severity, char *fmt, ...);
|
||||
#define ERR_MASK 0x0F /* mask off the above codes */
|
||||
#define ERR_NOFILE 0x10 /* don't give source file name/line */
|
||||
#define ERR_USAGE 0x20 /* print a usage message */
|
||||
#define ERR_OFFBY1 0x40 /* report error as being on the line
|
||||
* we're just _about_ to read, not
|
||||
* the one we've just read */
|
||||
#define ERR_PASS1 0x80 /* only print this error on pass one */
|
||||
|
||||
/*
|
||||
@ -205,6 +202,12 @@ enum { /* token types, other than chars */
|
||||
TOKEN_FLOAT /* floating-point constant */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
long segment;
|
||||
long offset;
|
||||
int known;
|
||||
} loc_t;
|
||||
|
||||
/*
|
||||
* Expression-evaluator datatype. Expressions, within the
|
||||
* evaluator, are stored as an array of these beasts, terminated by
|
||||
@ -260,13 +263,6 @@ typedef expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
|
||||
int *fwref, int critical, efunc error,
|
||||
struct eval_hints *hints);
|
||||
|
||||
/*
|
||||
* There's also an auxiliary routine through which the evaluator
|
||||
* needs to hear about the value of $ and the label (if any)
|
||||
* defined on the current line.
|
||||
*/
|
||||
typedef void (*evalinfofunc) (char *labelname, long segment, long offset);
|
||||
|
||||
/*
|
||||
* Special values for expr->type. ASSUMPTION MADE HERE: the number
|
||||
* of distinct register names (i.e. possible "type" fields for an
|
||||
@ -311,11 +307,13 @@ typedef struct {
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* isidstart matches any character that may start an identifier, and isidchar
|
||||
/*
|
||||
* isidstart matches any character that may start an identifier, and isidchar
|
||||
* matches any character that may appear at places other than the start of an
|
||||
* identifier. E.g. a period may only appear at the start of an identifier
|
||||
* (for local labels), whereas a number may appear anywhere *but* at the
|
||||
* start. */
|
||||
* start.
|
||||
*/
|
||||
|
||||
#define isidstart(c) ( isalpha(c) || (c)=='_' || (c)=='.' || (c)=='?' \
|
||||
|| (c)=='@' )
|
||||
@ -439,7 +437,9 @@ enum { /* instruction names */
|
||||
I_FCMOVBE, I_FCMOVE, I_FCMOVNB, I_FCMOVNBE, I_FCMOVNE,
|
||||
I_FCMOVNU, I_FCMOVU, I_FCOM, I_FCOMI, I_FCOMIP, I_FCOMP,
|
||||
I_FCOMPP, I_FCOS, I_FDECSTP, I_FDISI, I_FDIV, I_FDIVP, I_FDIVR,
|
||||
I_FDIVRP, I_FENI, I_FFREE, I_FIADD, I_FICOM, I_FICOMP, I_FIDIV,
|
||||
I_FDIVRP,
|
||||
I_FEMMS,
|
||||
I_FENI, I_FFREE, I_FIADD, I_FICOM, I_FICOMP, I_FIDIV,
|
||||
I_FIDIVR, I_FILD, I_FIMUL, I_FINCSTP, I_FINIT, I_FIST, I_FISTP,
|
||||
I_FISUB, I_FISUBR, I_FLD, I_FLD1, I_FLDCW, I_FLDENV, I_FLDL2E,
|
||||
I_FLDL2T, I_FLDLG2, I_FLDLN2, I_FLDPI, I_FLDZ, I_FMUL, I_FMULP,
|
||||
@ -451,7 +451,7 @@ enum { /* instruction names */
|
||||
I_FUCOMI, I_FUCOMIP, I_FUCOMP, I_FUCOMPP, I_FXAM, I_FXCH,
|
||||
I_FXTRACT, I_FYL2X, I_FYL2XP1, I_HLT, I_IBTS, I_ICEBP, I_IDIV,
|
||||
I_IMUL, I_IN, I_INC, I_INCBIN, I_INSB, I_INSD, I_INSW, I_INT,
|
||||
I_INT1, I_INT01, I_INT3, I_INTO, I_INVD, I_INVLPG, I_IRET,
|
||||
I_INT01, I_INT1, I_INT3, I_INTO, I_INVD, I_INVLPG, I_IRET,
|
||||
I_IRETD, I_IRETW, I_JCXZ, I_JECXZ, I_JMP, I_LAHF, I_LAR, I_LDS,
|
||||
I_LEA, I_LEAVE, I_LES, I_LFS, I_LGDT, I_LGS, I_LIDT, I_LLDT,
|
||||
I_LMSW, I_LOADALL, I_LOADALL286, I_LODSB, I_LODSD, I_LODSW,
|
||||
@ -460,12 +460,18 @@ enum { /* instruction names */
|
||||
I_MOVSX, I_MOVZX, I_MUL, I_NEG, I_NOP, I_NOT, I_OR, I_OUT,
|
||||
I_OUTSB, I_OUTSD, I_OUTSW, I_PACKSSDW, I_PACKSSWB, I_PACKUSWB,
|
||||
I_PADDB, I_PADDD, I_PADDSB, I_PADDSIW, I_PADDSW, I_PADDUSB,
|
||||
I_PADDUSW, I_PADDW, I_PAND, I_PANDN, I_PAVEB, I_PCMPEQB,
|
||||
I_PADDUSW, I_PADDW, I_PAND, I_PANDN, I_PAVEB,
|
||||
I_PAVGUSB, I_PCMPEQB,
|
||||
I_PCMPEQD, I_PCMPEQW, I_PCMPGTB, I_PCMPGTD, I_PCMPGTW,
|
||||
I_PDISTIB, I_PMACHRIW, I_PMADDWD, I_PMAGW, I_PMULHRW,
|
||||
I_PMULHRIW, I_PMULHW, I_PMULLW, I_PMVGEZB, I_PMVLZB, I_PMVNZB,
|
||||
I_PDISTIB,
|
||||
I_PF2ID, I_PFACC, I_PFADD, I_PFCMPEQ, I_PFCMPGE, I_PFCMPGT,
|
||||
I_PFMAX, I_PFMIN, I_PFMUL, I_PFRCP, I_PFRCPIT1, I_PFRCPIT2,
|
||||
I_PFRSQIT1, I_PFRSQRT, I_PFSUB, I_PFSUBR, I_PI2FD,
|
||||
I_PMACHRIW, I_PMADDWD, I_PMAGW, I_PMULHRIW, I_PMULHRWA,
|
||||
I_PMULHRWC, I_PMULHW, I_PMULLW, I_PMVGEZB, I_PMVLZB, I_PMVNZB,
|
||||
I_PMVZB, I_POP, I_POPA, I_POPAD, I_POPAW, I_POPF, I_POPFD,
|
||||
I_POPFW, I_POR, I_PSLLD, I_PSLLQ, I_PSLLW, I_PSRAD, I_PSRAW,
|
||||
I_POPFW, I_POR, I_PREFETCH, I_PREFETCHW,
|
||||
I_PSLLD, I_PSLLQ, I_PSLLW, I_PSRAD, I_PSRAW,
|
||||
I_PSRLD, I_PSRLQ, I_PSRLW, I_PSUBB, I_PSUBD, I_PSUBSB,
|
||||
I_PSUBSIW, I_PSUBSW, I_PSUBUSB, I_PSUBUSW, I_PSUBW, I_PUNPCKHBW,
|
||||
I_PUNPCKHDQ, I_PUNPCKHWD, I_PUNPCKLBW, I_PUNPCKLDQ, I_PUNPCKLWD,
|
||||
@ -480,6 +486,8 @@ enum { /* instruction names */
|
||||
I_XOR, I_CMOVcc, I_Jcc, I_SETcc
|
||||
};
|
||||
|
||||
#define MAX_KEYWORD 9 /* max length of any instruction, register name etc. */
|
||||
|
||||
enum { /* condition code names */
|
||||
C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE,
|
||||
C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP,
|
||||
@ -522,8 +530,12 @@ typedef struct { /* operand to an instruction */
|
||||
long offset; /* any immediate number */
|
||||
long wrt; /* segment base it's relative to */
|
||||
int eaflags; /* special EA flags */
|
||||
int opflags; /* see OPFLAG_* defines below */
|
||||
} operand;
|
||||
|
||||
#define OPFLAG_FORWARD 1 /* operand is a forward reference */
|
||||
#define OPFLAG_EXTERN 2 /* operand is an external reference */
|
||||
|
||||
typedef struct extop { /* extended operand */
|
||||
struct extop *next; /* linked list */
|
||||
long type; /* defined above */
|
||||
@ -542,13 +554,16 @@ typedef struct { /* an instruction itself */
|
||||
int nprefix; /* number of entries in above */
|
||||
int opcode; /* the opcode - not just the string */
|
||||
int condition; /* the condition code, if Jcc/SETcc */
|
||||
int operands; /* how many operands? 0-3 */
|
||||
int operands; /* how many operands? 0-3
|
||||
* (more if db et al) */
|
||||
operand oprs[3]; /* the operands, defined as above */
|
||||
extop *eops; /* extended operands */
|
||||
int eops_float; /* true if DD and floating */
|
||||
long times; /* repeat count (TIMES prefix) */
|
||||
int forw_ref; /* is there a forward reference? */
|
||||
} insn;
|
||||
|
||||
enum geninfo { GI_SWITCH };
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* The data structure defining an output format driver, and the
|
||||
@ -568,6 +583,27 @@ struct ofmt {
|
||||
*/
|
||||
char *shortname;
|
||||
|
||||
/*
|
||||
* this is reserved for out module specific help.
|
||||
* It is set to NULL in all the out modules but is not implemented
|
||||
* in the main program
|
||||
*/
|
||||
char *helpstring;
|
||||
|
||||
/*
|
||||
* this is a pointer to the first element of the debug information
|
||||
*/
|
||||
struct dfmt **debug_formats;
|
||||
|
||||
/*
|
||||
* and a pointer to the element that is being used
|
||||
* note: this is set to the default at compile time and changed if the
|
||||
* -F option is selected. If developing a set of new debug formats for
|
||||
* an output format, be sure to set this to whatever default you want
|
||||
*
|
||||
*/
|
||||
struct dfmt *current_dfmt;
|
||||
|
||||
/*
|
||||
* This, if non-NULL, is a NULL-terminated list of `char *'s
|
||||
* pointing to extra standard macros supplied by the object
|
||||
@ -586,6 +622,15 @@ struct ofmt {
|
||||
*/
|
||||
void (*init) (FILE *fp, efunc error, ldfunc ldef, evalfunc eval);
|
||||
|
||||
/*
|
||||
* This procedure is called to pass generic information to the
|
||||
* object file. The first parameter gives the information type
|
||||
* (currently only command line switches)
|
||||
* and the second parameter gives the value. This function returns
|
||||
* 1 if recognized, 0 if unrecognized
|
||||
*/
|
||||
int (*setinfo)(enum geninfo type, char **string);
|
||||
|
||||
/*
|
||||
* This procedure is called by assemble() to write actual
|
||||
* generated code or data to the object file. Typically it
|
||||
@ -705,7 +750,7 @@ struct ofmt {
|
||||
* One thing the cleanup routine should always do is to close
|
||||
* the output file pointer.
|
||||
*/
|
||||
void (*cleanup) (void);
|
||||
void (*cleanup) (int debuginfo);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -734,6 +779,103 @@ struct ofmt {
|
||||
#define OUT_TYPMASK 0xF0000000UL
|
||||
#define OUT_SIZMASK 0x0FFFFFFFUL
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* The data structure defining a debug format driver, and the
|
||||
* interfaces to the functions therein.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct dfmt {
|
||||
|
||||
/*
|
||||
* This is a short (one-liner) description of the type of
|
||||
* output generated by the driver.
|
||||
*/
|
||||
char *fullname;
|
||||
|
||||
/*
|
||||
* This is a single keyword used to select the driver.
|
||||
*/
|
||||
char *shortname;
|
||||
|
||||
|
||||
/*
|
||||
* init - called initially to set up local pointer to object format,
|
||||
* void pointer to implementation defined data, file pointer (which
|
||||
* probably won't be used, but who knows?), and error function.
|
||||
*/
|
||||
void (*init) (struct ofmt * of, void * id, FILE * fp, efunc error);
|
||||
|
||||
/*
|
||||
* linenum - called any time there is output with a change of
|
||||
* line number or file.
|
||||
*/
|
||||
void (*linenum) (const char * filename, long linenumber, long segto);
|
||||
|
||||
/*
|
||||
* debug_deflabel - called whenever a label is defined. Parameters
|
||||
* are the same as to 'symdef()' in the output format. This function
|
||||
* would be called before the output format version.
|
||||
*/
|
||||
|
||||
void (*debug_deflabel) (char * name, long segment, long offset,
|
||||
int is_global, char * special);
|
||||
/*
|
||||
* debug_directive - called whenever a DEBUG directive other than 'LINE'
|
||||
* is encountered. 'directive' contains the first parameter to the
|
||||
* DEBUG directive, and params contains the rest. For example,
|
||||
* 'DEBUG VAR _somevar:int' would translate to a call to this
|
||||
* function with 'directive' equal to "VAR" and 'params' equal to
|
||||
* "_somevar:int".
|
||||
*/
|
||||
void (*debug_directive) (const char * directive, const char * params);
|
||||
|
||||
/*
|
||||
* typevalue - called whenever the assembler wishes to register a type
|
||||
* for the last defined label. This routine MUST detect if a type was
|
||||
* already registered and not re-register it.
|
||||
*/
|
||||
void (*debug_typevalue) (long type);
|
||||
|
||||
/*
|
||||
* debug_output - called whenever output is required
|
||||
* 'type' is the type of info required, and this is format-specific
|
||||
*/
|
||||
void (*debug_output) (int type, void *param);
|
||||
|
||||
/*
|
||||
* cleanup - called after processing of file is complete
|
||||
*/
|
||||
void (*cleanup) (void);
|
||||
|
||||
};
|
||||
/*
|
||||
* The type definition macros
|
||||
* for debugging
|
||||
*
|
||||
* low 3 bits: reserved
|
||||
* next 5 bits: type
|
||||
* next 24 bits: number of elements for arrays (0 for labels)
|
||||
*/
|
||||
|
||||
#define TY_UNKNOWN 0x00
|
||||
#define TY_LABEL 0x08
|
||||
#define TY_BYTE 0x10
|
||||
#define TY_WORD 0x18
|
||||
#define TY_DWORD 0x20
|
||||
#define TY_FLOAT 0x28
|
||||
#define TY_QWORD 0x30
|
||||
#define TY_TBYTE 0x38
|
||||
#define TY_COMMON 0xE0
|
||||
#define TY_SEG 0xE8
|
||||
#define TY_EXTERN 0xF0
|
||||
#define TY_EQU 0xF8
|
||||
|
||||
#define TYM_TYPE(x) ((x) & 0xF8)
|
||||
#define TYM_ELEMENTS(x) (((x) & 0xFFFFFF00) >> 8)
|
||||
|
||||
#define TYS_ELEMENTS(x) ((x) << 8)
|
||||
/*
|
||||
* -----
|
||||
* Other
|
||||
|
360
nasmlib.c
360
nasmlib.c
@ -20,7 +20,8 @@ static efunc nasm_malloc_error;
|
||||
static FILE *logfp;
|
||||
#endif
|
||||
|
||||
void nasm_set_malloc_error (efunc error) {
|
||||
void nasm_set_malloc_error (efunc error)
|
||||
{
|
||||
nasm_malloc_error = error;
|
||||
#ifdef LOGALLOC
|
||||
logfp = fopen ("malloc.log", "w");
|
||||
@ -124,7 +125,8 @@ char *nasm_strndup (char *s, size_t len)
|
||||
return p;
|
||||
}
|
||||
|
||||
int nasm_stricmp (char *s1, char *s2) {
|
||||
int nasm_stricmp (const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 && toupper(*s1) == toupper(*s2))
|
||||
s1++, s2++;
|
||||
if (!*s1 && !*s2)
|
||||
@ -135,7 +137,8 @@ int nasm_stricmp (char *s1, char *s2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nasm_strnicmp (char *s1, char *s2, int n) {
|
||||
int nasm_strnicmp (const char *s1, const char *s2, int n)
|
||||
{
|
||||
while (n > 0 && *s1 && toupper(*s1) == toupper(*s2))
|
||||
s1++, s2++, n--;
|
||||
if ((!*s1 && !*s2) || n==0)
|
||||
@ -149,15 +152,29 @@ int nasm_strnicmp (char *s1, char *s2, int n) {
|
||||
#define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
|
||||
#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
|
||||
|
||||
long readnum (char *str, int *error) {
|
||||
long readnum (char *str, int *error)
|
||||
{
|
||||
char *r = str, *q;
|
||||
long radix;
|
||||
unsigned long result, checklimit;
|
||||
int digit, last;
|
||||
int warn = FALSE;
|
||||
int sign = 1;
|
||||
|
||||
*error = FALSE;
|
||||
|
||||
while (isspace(*r)) r++; /* find start of number */
|
||||
|
||||
/*
|
||||
* If the number came from make_tok_num (as a result of an %assign), it
|
||||
* might have a '-' built into it (rather than in a preceeding token).
|
||||
*/
|
||||
if (*r == '-')
|
||||
{
|
||||
r++;
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
q = r;
|
||||
|
||||
while (lib_isnumchar(*q)) q++; /* find end of number */
|
||||
@ -199,15 +216,26 @@ long readnum (char *str, int *error) {
|
||||
*/
|
||||
checklimit = 0x80000000UL / (radix>>1);
|
||||
|
||||
/*
|
||||
* Calculate the highest allowable value for the last digit
|
||||
* of a 32 bit constant... in radix 10, it is 6, otherwise it is 0
|
||||
*/
|
||||
last = (radix == 10 ? 6 : 0);
|
||||
|
||||
result = 0;
|
||||
while (*r && r < q) {
|
||||
if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) {
|
||||
if (*r<'0' || (*r>'9' && *r<'A') || (digit = numvalue(*r)) >= radix)
|
||||
{
|
||||
*error = TRUE;
|
||||
return 0;
|
||||
}
|
||||
if (result >= checklimit)
|
||||
if (result > checklimit ||
|
||||
(result == checklimit && digit >= last))
|
||||
{
|
||||
warn = TRUE;
|
||||
result = radix * result + numvalue(*r);
|
||||
}
|
||||
|
||||
result = radix * result + digit;
|
||||
r++;
|
||||
}
|
||||
|
||||
@ -216,25 +244,46 @@ long readnum (char *str, int *error) {
|
||||
"numeric constant %s does not fit in 32 bits",
|
||||
str);
|
||||
|
||||
return result;
|
||||
return result*sign;
|
||||
}
|
||||
|
||||
long readstrnum (char *str, int length, int *warn)
|
||||
{
|
||||
long charconst = 0;
|
||||
int i;
|
||||
|
||||
*warn = FALSE;
|
||||
|
||||
str += length;
|
||||
for (i=0; i<length; i++) {
|
||||
if (charconst & 0xff000000UL) {
|
||||
*warn = TRUE;
|
||||
}
|
||||
charconst = (charconst<<8) + (unsigned char) *--str;
|
||||
}
|
||||
return charconst;
|
||||
}
|
||||
|
||||
static long next_seg;
|
||||
|
||||
void seg_init(void) {
|
||||
void seg_init(void)
|
||||
{
|
||||
next_seg = 0;
|
||||
}
|
||||
|
||||
long seg_alloc(void) {
|
||||
long seg_alloc(void)
|
||||
{
|
||||
return (next_seg += 2) - 2;
|
||||
}
|
||||
|
||||
void fwriteshort (int data, FILE *fp) {
|
||||
void fwriteshort (int data, FILE *fp)
|
||||
{
|
||||
fputc ((int) (data & 255), fp);
|
||||
fputc ((int) ((data >> 8) & 255), fp);
|
||||
}
|
||||
|
||||
void fwritelong (long data, FILE *fp) {
|
||||
void fwritelong (long data, FILE *fp)
|
||||
{
|
||||
fputc ((int) (data & 255), fp);
|
||||
fputc ((int) ((data >> 8) & 255), fp);
|
||||
fputc ((int) ((data >> 16) & 255), fp);
|
||||
@ -242,7 +291,8 @@ void fwritelong (long data, FILE *fp) {
|
||||
}
|
||||
|
||||
void standard_extension (char *inname, char *outname, char *extension,
|
||||
efunc error) {
|
||||
efunc error)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
if (*outname) /* file name already exists, */
|
||||
@ -268,47 +318,13 @@ void standard_extension (char *inname, char *outname, char *extension,
|
||||
strcpy(p, extension);
|
||||
}
|
||||
|
||||
#define RAA_BLKSIZE 4096 /* this many longs allocated at once */
|
||||
#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
|
||||
|
||||
typedef struct RAA RAA;
|
||||
typedef union RAA_UNION RAA_UNION;
|
||||
typedef struct RAA_LEAF RAA_LEAF;
|
||||
typedef struct RAA_BRANCH RAA_BRANCH;
|
||||
|
||||
struct RAA {
|
||||
/*
|
||||
* Number of layers below this one to get to the real data. 0
|
||||
* means this structure is a leaf, holding RAA_BLKSIZE real
|
||||
* data items; 1 and above mean it's a branch, holding
|
||||
* RAA_LAYERSIZE pointers to the next level branch or leaf
|
||||
* structures.
|
||||
*/
|
||||
int layers;
|
||||
/*
|
||||
* Number of real data items spanned by one position in the
|
||||
* `data' array at this level. This number is 1, trivially, for
|
||||
* a leaf (level 0): for a level 1 branch it should be
|
||||
* RAA_BLKSIZE, and for a level 2 branch it's
|
||||
* RAA_LAYERSIZE*RAA_BLKSIZE.
|
||||
*/
|
||||
long stepsize;
|
||||
union RAA_UNION {
|
||||
struct RAA_LEAF {
|
||||
long data[RAA_BLKSIZE];
|
||||
} l;
|
||||
struct RAA_BRANCH {
|
||||
struct RAA *data[RAA_LAYERSIZE];
|
||||
} b;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
|
||||
#define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
|
||||
|
||||
#define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
|
||||
|
||||
static struct RAA *real_raa_init (int layers) {
|
||||
static struct RAA *real_raa_init (int layers)
|
||||
{
|
||||
struct RAA *r;
|
||||
|
||||
if (layers == 0) {
|
||||
@ -327,11 +343,13 @@ static struct RAA *real_raa_init (int layers) {
|
||||
return r;
|
||||
}
|
||||
|
||||
struct RAA *raa_init (void) {
|
||||
struct RAA *raa_init (void)
|
||||
{
|
||||
return real_raa_init (0);
|
||||
}
|
||||
|
||||
void raa_free (struct RAA *r) {
|
||||
void raa_free (struct RAA *r)
|
||||
{
|
||||
if (r->layers == 0)
|
||||
nasm_free (r);
|
||||
else {
|
||||
@ -342,7 +360,8 @@ void raa_free (struct RAA *r) {
|
||||
}
|
||||
}
|
||||
|
||||
long raa_read (struct RAA *r, long posn) {
|
||||
long raa_read (struct RAA *r, long posn)
|
||||
{
|
||||
if (posn > r->stepsize * LAYERSIZ(r))
|
||||
return 0L;
|
||||
while (r->layers > 0) {
|
||||
@ -356,7 +375,8 @@ long raa_read (struct RAA *r, long posn) {
|
||||
return r->u.l.data[posn];
|
||||
}
|
||||
|
||||
struct RAA *raa_write (struct RAA *r, long posn, long value) {
|
||||
struct RAA *raa_write (struct RAA *r, long posn, long value)
|
||||
{
|
||||
struct RAA *result;
|
||||
|
||||
if (posn < 0)
|
||||
@ -396,17 +416,8 @@ struct RAA *raa_write (struct RAA *r, long posn, long value) {
|
||||
|
||||
#define SAA_MAXLEN 8192
|
||||
|
||||
struct SAA {
|
||||
/*
|
||||
* members `end' and `elem_len' are only valid in first link in
|
||||
* list; `rptr' and `rpos' are used for reading
|
||||
*/
|
||||
struct SAA *next, *end, *rptr;
|
||||
long elem_len, length, posn, start, rpos;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct SAA *saa_init (long elem_len) {
|
||||
struct SAA *saa_init (long elem_len)
|
||||
{
|
||||
struct SAA *s;
|
||||
|
||||
if (elem_len > SAA_MAXLEN)
|
||||
@ -423,7 +434,8 @@ struct SAA *saa_init (long elem_len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
void saa_free (struct SAA *s) {
|
||||
void saa_free (struct SAA *s)
|
||||
{
|
||||
struct SAA *t;
|
||||
|
||||
while (s) {
|
||||
@ -434,7 +446,8 @@ void saa_free (struct SAA *s) {
|
||||
}
|
||||
}
|
||||
|
||||
void *saa_wstruct (struct SAA *s) {
|
||||
void *saa_wstruct (struct SAA *s)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (s->end->length - s->end->posn < s->elem_len) {
|
||||
@ -452,7 +465,8 @@ void *saa_wstruct (struct SAA *s) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void saa_wbytes (struct SAA *s, void *data, long len) {
|
||||
void saa_wbytes (struct SAA *s, void *data, long len)
|
||||
{
|
||||
char *d = data;
|
||||
|
||||
while (len > 0) {
|
||||
@ -480,12 +494,14 @@ void saa_wbytes (struct SAA *s, void *data, long len) {
|
||||
}
|
||||
}
|
||||
|
||||
void saa_rewind (struct SAA *s) {
|
||||
void saa_rewind (struct SAA *s)
|
||||
{
|
||||
s->rptr = s;
|
||||
s->rpos = 0L;
|
||||
}
|
||||
|
||||
void *saa_rstruct (struct SAA *s) {
|
||||
void *saa_rstruct (struct SAA *s)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!s->rptr)
|
||||
@ -503,7 +519,8 @@ void *saa_rstruct (struct SAA *s) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void *saa_rbytes (struct SAA *s, long *len) {
|
||||
void *saa_rbytes (struct SAA *s, long *len)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!s->rptr)
|
||||
@ -516,7 +533,8 @@ void *saa_rbytes (struct SAA *s, long *len) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void saa_rnbytes (struct SAA *s, void *data, long len) {
|
||||
void saa_rnbytes (struct SAA *s, void *data, long len)
|
||||
{
|
||||
char *d = data;
|
||||
|
||||
while (len > 0) {
|
||||
@ -541,26 +559,27 @@ void saa_rnbytes (struct SAA *s, void *data, long len) {
|
||||
}
|
||||
}
|
||||
|
||||
void saa_fread (struct SAA *s, long posn, void *data, long len) {
|
||||
void saa_fread (struct SAA *s, long posn, void *data, long len)
|
||||
{
|
||||
struct SAA *p;
|
||||
long pos;
|
||||
char *cdata = data;
|
||||
|
||||
if (!s->rptr || posn > s->rptr->start + s->rpos)
|
||||
if (!s->rptr || posn < s->rptr->start)
|
||||
saa_rewind (s);
|
||||
while (posn >= s->rptr->start + s->rptr->posn) {
|
||||
s->rptr = s->rptr->next;
|
||||
if (!s->rptr)
|
||||
p = s->rptr;
|
||||
while (posn >= p->start + p->posn) {
|
||||
p = p->next;
|
||||
if (!p)
|
||||
return; /* what else can we do?! */
|
||||
}
|
||||
|
||||
p = s->rptr;
|
||||
pos = posn - s->rptr->start;
|
||||
pos = posn - p->start;
|
||||
while (len) {
|
||||
long l = s->rptr->posn - pos;
|
||||
long l = p->posn - pos;
|
||||
if (l > len)
|
||||
l = len;
|
||||
memcpy (cdata, s->rptr->data+pos, l);
|
||||
memcpy (cdata, p->data+pos, l);
|
||||
len -= l;
|
||||
cdata += l;
|
||||
p = p->next;
|
||||
@ -568,28 +587,30 @@ void saa_fread (struct SAA *s, long posn, void *data, long len) {
|
||||
return;
|
||||
pos = 0L;
|
||||
}
|
||||
s->rptr = p;
|
||||
}
|
||||
|
||||
void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
|
||||
void saa_fwrite (struct SAA *s, long posn, void *data, long len)
|
||||
{
|
||||
struct SAA *p;
|
||||
long pos;
|
||||
char *cdata = data;
|
||||
|
||||
if (!s->rptr || posn > s->rptr->start + s->rpos)
|
||||
if (!s->rptr || posn < s->rptr->start)
|
||||
saa_rewind (s);
|
||||
while (posn >= s->rptr->start + s->rptr->posn) {
|
||||
s->rptr = s->rptr->next;
|
||||
if (!s->rptr)
|
||||
p = s->rptr;
|
||||
while (posn >= p->start + p->posn) {
|
||||
p = p->next;
|
||||
if (!p)
|
||||
return; /* what else can we do?! */
|
||||
}
|
||||
|
||||
p = s->rptr;
|
||||
pos = posn - s->rptr->start;
|
||||
pos = posn - p->start;
|
||||
while (len) {
|
||||
long l = s->rptr->posn - pos;
|
||||
long l = p->posn - pos;
|
||||
if (l > len)
|
||||
l = len;
|
||||
memcpy (s->rptr->data+pos, cdata, l);
|
||||
memcpy (p->data+pos, cdata, l);
|
||||
len -= l;
|
||||
cdata += l;
|
||||
p = p->next;
|
||||
@ -597,9 +618,11 @@ void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
|
||||
return;
|
||||
pos = 0L;
|
||||
}
|
||||
s->rptr = p;
|
||||
}
|
||||
|
||||
void saa_fpwrite (struct SAA *s, FILE *fp) {
|
||||
void saa_fpwrite (struct SAA *s, FILE *fp)
|
||||
{
|
||||
char *data;
|
||||
long len;
|
||||
|
||||
@ -632,16 +655,29 @@ static char **stdscan_tempstorage = NULL;
|
||||
static int stdscan_tempsize = 0, stdscan_templen = 0;
|
||||
#define STDSCAN_TEMP_DELTA 256
|
||||
|
||||
static void stdscan_pop(void) {
|
||||
static void stdscan_pop(void)
|
||||
{
|
||||
nasm_free (stdscan_tempstorage[--stdscan_templen]);
|
||||
}
|
||||
|
||||
void stdscan_reset(void) {
|
||||
void stdscan_reset(void)
|
||||
{
|
||||
while (stdscan_templen > 0)
|
||||
stdscan_pop();
|
||||
}
|
||||
|
||||
static char *stdscan_copy(char *p, int len) {
|
||||
/*
|
||||
* Unimportant cleanup is done to avoid confusing people who are trying
|
||||
* to debug real memory leaks
|
||||
*/
|
||||
void nasmlib_cleanup (void)
|
||||
{
|
||||
stdscan_reset();
|
||||
nasm_free (stdscan_tempstorage);
|
||||
}
|
||||
|
||||
static char *stdscan_copy(char *p, int len)
|
||||
{
|
||||
char *text;
|
||||
|
||||
text = nasm_malloc(len+1);
|
||||
@ -659,8 +695,11 @@ static char *stdscan_copy(char *p, int len) {
|
||||
}
|
||||
|
||||
char *stdscan_bufptr = NULL;
|
||||
int stdscan (void *private_data, struct tokenval *tv) {
|
||||
char ourcopy[256], *r, *s;
|
||||
int stdscan (void *private_data, struct tokenval *tv)
|
||||
{
|
||||
char ourcopy[MAX_KEYWORD+1], *r, *s;
|
||||
|
||||
(void) private_data; /* Don't warn that this parameter is unused */
|
||||
|
||||
while (isspace(*stdscan_bufptr)) stdscan_bufptr++;
|
||||
if (!*stdscan_bufptr)
|
||||
@ -682,11 +721,12 @@ int stdscan (void *private_data, struct tokenval *tv) {
|
||||
while (isidchar(*stdscan_bufptr)) stdscan_bufptr++;
|
||||
tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
|
||||
|
||||
if (is_sym || stdscan_bufptr-r > MAX_KEYWORD)
|
||||
return tv->t_type = TOKEN_ID;/* bypass all other checks */
|
||||
|
||||
for (s=tv->t_charptr, r=ourcopy; *s; s++)
|
||||
*r++ = tolower (*s);
|
||||
*r = '\0';
|
||||
if (is_sym)
|
||||
return tv->t_type = TOKEN_ID;/* bypass all other checks */
|
||||
/* right, so we have an identifier sitting in temp storage. now,
|
||||
* is it actually a register or instruction name, or what? */
|
||||
if ((tv->t_integer=bsi(ourcopy, reg_names,
|
||||
@ -743,7 +783,10 @@ int stdscan (void *private_data, struct tokenval *tv) {
|
||||
* a floating point constant
|
||||
*/
|
||||
stdscan_bufptr++;
|
||||
while (isnumchar(*stdscan_bufptr)) {
|
||||
while (isnumchar(*stdscan_bufptr) ||
|
||||
((stdscan_bufptr[-1] == 'e' || stdscan_bufptr[-1] == 'E')
|
||||
&& (*stdscan_bufptr == '-' || *stdscan_bufptr == '+')) )
|
||||
{
|
||||
stdscan_bufptr++;
|
||||
}
|
||||
tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
|
||||
@ -759,16 +802,15 @@ int stdscan (void *private_data, struct tokenval *tv) {
|
||||
} else if (*stdscan_bufptr == '\'' ||
|
||||
*stdscan_bufptr == '"') {/* a char constant */
|
||||
char quote = *stdscan_bufptr++, *r;
|
||||
int rn_warn;
|
||||
r = tv->t_charptr = stdscan_bufptr;
|
||||
while (*stdscan_bufptr && *stdscan_bufptr != quote) stdscan_bufptr++;
|
||||
tv->t_inttwo = stdscan_bufptr - r; /* store full version */
|
||||
if (!*stdscan_bufptr)
|
||||
return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */
|
||||
tv->t_integer = 0;
|
||||
r = stdscan_bufptr++; /* skip over final quote */
|
||||
while (quote != *--r) {
|
||||
tv->t_integer = (tv->t_integer<<8) + (unsigned char) *r;
|
||||
}
|
||||
stdscan_bufptr++; /* skip over final quote */
|
||||
tv->t_integer = readstrnum(r, tv->t_inttwo, &rn_warn);
|
||||
/* FIXME: rn_warn is not checked! */
|
||||
return tv->t_type = TOKEN_NUM;
|
||||
} else if (*stdscan_bufptr == ';') { /* a comment has happened - stay */
|
||||
return tv->t_type = 0;
|
||||
@ -816,7 +858,8 @@ int stdscan (void *private_data, struct tokenval *tv) {
|
||||
* Return TRUE if the argument is a simple scalar. (Or a far-
|
||||
* absolute, which counts.)
|
||||
*/
|
||||
int is_simple (expr *vect) {
|
||||
int is_simple (expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value)
|
||||
vect++;
|
||||
if (!vect->type)
|
||||
@ -834,7 +877,8 @@ int is_simple (expr *vect) {
|
||||
* Return TRUE if the argument is a simple scalar, _NOT_ a far-
|
||||
* absolute.
|
||||
*/
|
||||
int is_really_simple (expr *vect) {
|
||||
int is_really_simple (expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value)
|
||||
vect++;
|
||||
if (!vect->type)
|
||||
@ -852,7 +896,8 @@ int is_really_simple (expr *vect) {
|
||||
* Return TRUE if the argument is relocatable (i.e. a simple
|
||||
* scalar, plus at most one segment-base, plus possibly a WRT).
|
||||
*/
|
||||
int is_reloc (expr *vect) {
|
||||
int is_reloc (expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value) /* skip initial value-0 terms */
|
||||
vect++;
|
||||
if (!vect->type) /* trivially return TRUE if nothing */
|
||||
@ -886,7 +931,8 @@ int is_reloc (expr *vect) {
|
||||
/*
|
||||
* Return TRUE if the argument contains an `unknown' part.
|
||||
*/
|
||||
int is_unknown(expr *vect) {
|
||||
int is_unknown(expr *vect)
|
||||
{
|
||||
while (vect->type && vect->type < EXPR_UNKNOWN)
|
||||
vect++;
|
||||
return (vect->type == EXPR_UNKNOWN);
|
||||
@ -896,7 +942,8 @@ int is_unknown(expr *vect) {
|
||||
* Return TRUE if the argument contains nothing but an `unknown'
|
||||
* part.
|
||||
*/
|
||||
int is_just_unknown(expr *vect) {
|
||||
int is_just_unknown(expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value)
|
||||
vect++;
|
||||
return (vect->type == EXPR_UNKNOWN);
|
||||
@ -906,7 +953,8 @@ int is_just_unknown(expr *vect) {
|
||||
* Return the scalar part of a relocatable vector. (Including
|
||||
* simple scalar vectors - those qualify as relocatable.)
|
||||
*/
|
||||
long reloc_value (expr *vect) {
|
||||
long reloc_value (expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value)
|
||||
vect++;
|
||||
if (!vect->type) return 0;
|
||||
@ -920,7 +968,8 @@ long reloc_value (expr *vect) {
|
||||
* Return the segment number of a relocatable vector, or NO_SEG for
|
||||
* simple scalars.
|
||||
*/
|
||||
long reloc_seg (expr *vect) {
|
||||
long reloc_seg (expr *vect)
|
||||
{
|
||||
while (vect->type && (vect->type == EXPR_WRT || !vect->value))
|
||||
vect++;
|
||||
if (vect->type == EXPR_SIMPLE) {
|
||||
@ -938,7 +987,8 @@ long reloc_seg (expr *vect) {
|
||||
* Return the WRT segment number of a relocatable vector, or NO_SEG
|
||||
* if no WRT part is present.
|
||||
*/
|
||||
long reloc_wrt (expr *vect) {
|
||||
long reloc_wrt (expr *vect)
|
||||
{
|
||||
while (vect->type && vect->type < EXPR_WRT)
|
||||
vect++;
|
||||
if (vect->type == EXPR_WRT) {
|
||||
@ -950,7 +1000,8 @@ long reloc_wrt (expr *vect) {
|
||||
/*
|
||||
* Binary search.
|
||||
*/
|
||||
int bsi (char *string, char **array, int size) {
|
||||
int bsi (char *string, char **array, int size)
|
||||
{
|
||||
int i = -1, j = size; /* always, i < index < j */
|
||||
while (j-i >= 2) {
|
||||
int k = (i+j)/2;
|
||||
@ -964,3 +1015,88 @@ int bsi (char *string, char **array, int size) {
|
||||
}
|
||||
return -1; /* we haven't got it :( */
|
||||
}
|
||||
|
||||
static char *file_name = NULL;
|
||||
static long line_number = 0;
|
||||
|
||||
char *src_set_fname(char *newname)
|
||||
{
|
||||
char *oldname = file_name;
|
||||
file_name = newname;
|
||||
return oldname;
|
||||
}
|
||||
|
||||
long src_set_linnum(long newline)
|
||||
{
|
||||
long oldline = line_number;
|
||||
line_number = newline;
|
||||
return oldline;
|
||||
}
|
||||
|
||||
long src_get_linnum(void)
|
||||
{
|
||||
return line_number;
|
||||
}
|
||||
|
||||
int src_get(long *xline, char **xname)
|
||||
{
|
||||
if (!file_name || !*xname || strcmp(*xname, file_name))
|
||||
{
|
||||
nasm_free(*xname);
|
||||
*xname = file_name ? nasm_strdup(file_name) : NULL;
|
||||
*xline = line_number;
|
||||
return -2;
|
||||
}
|
||||
if (*xline != line_number)
|
||||
{
|
||||
long tmp = line_number - *xline;
|
||||
*xline = line_number;
|
||||
return tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nasm_quote(char **str)
|
||||
{
|
||||
int ln=strlen(*str);
|
||||
char q=(*str)[0];
|
||||
char *p;
|
||||
if (ln>1 && (*str)[ln-1]==q && (q=='"' || q=='\''))
|
||||
return;
|
||||
q = '"';
|
||||
if (strchr(*str,q))
|
||||
q = '\'';
|
||||
p = nasm_malloc(ln+3);
|
||||
strcpy(p+1, *str);
|
||||
nasm_free(*str);
|
||||
p[ln+1] = p[0] = q;
|
||||
p[ln+2] = 0;
|
||||
*str = p;
|
||||
}
|
||||
|
||||
char *nasm_strcat(char *one, char *two)
|
||||
{
|
||||
char *rslt;
|
||||
int l1=strlen(one);
|
||||
rslt = nasm_malloc(l1+strlen(two)+1);
|
||||
strcpy(rslt, one);
|
||||
strcpy(rslt+l1, two);
|
||||
return rslt;
|
||||
}
|
||||
|
||||
void null_debug_routine()
|
||||
{
|
||||
}
|
||||
struct dfmt null_debug_form = {
|
||||
"Null debug format",
|
||||
"null",
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
null_debug_routine,
|
||||
};
|
||||
|
||||
struct dfmt *null_debug_arr[2] = { &null_debug_form, NULL };
|
||||
|
79
nasmlib.h
79
nasmlib.h
@ -1,4 +1,4 @@
|
||||
/* nasmlib.c header file for nasmlib.h
|
||||
/* nasmlib.h header file for nasmlib.c
|
||||
*
|
||||
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
* Julian Hall. All rights reserved. The software is
|
||||
@ -51,8 +51,8 @@ char *nasm_strndup_log (char *, int, char *, size_t);
|
||||
* ANSI doesn't guarantee the presence of `stricmp' or
|
||||
* `strcasecmp'.
|
||||
*/
|
||||
int nasm_stricmp (char *, char *);
|
||||
int nasm_strnicmp (char *, char *, int);
|
||||
int nasm_stricmp (const char *, const char *);
|
||||
int nasm_strnicmp (const char *, const char *, int);
|
||||
|
||||
/*
|
||||
* Convert a string into a number, using NASM number rules. Sets
|
||||
@ -60,6 +60,14 @@ int nasm_strnicmp (char *, char *, int);
|
||||
*/
|
||||
long readnum(char *str, int *error);
|
||||
|
||||
/*
|
||||
* Convert a character constant into a number. Sets
|
||||
* `*warn' to TRUE if an overflow occurs, and FALSE otherwise.
|
||||
* str points to and length covers the middle of the string,
|
||||
* without the quotes.
|
||||
*/
|
||||
long readstrnum(char *str, int length, int *warn);
|
||||
|
||||
/*
|
||||
* seg_init: Initialise the segment-number allocator.
|
||||
* seg_alloc: allocate a hitherto unused segment number.
|
||||
@ -108,7 +116,41 @@ void fwritelong (long data, FILE *fp);
|
||||
* chunk.
|
||||
*/
|
||||
|
||||
struct RAA;
|
||||
#define RAA_BLKSIZE 4096 /* this many longs allocated at once */
|
||||
#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
|
||||
|
||||
typedef struct RAA RAA;
|
||||
typedef union RAA_UNION RAA_UNION;
|
||||
typedef struct RAA_LEAF RAA_LEAF;
|
||||
typedef struct RAA_BRANCH RAA_BRANCH;
|
||||
|
||||
struct RAA {
|
||||
/*
|
||||
* Number of layers below this one to get to the real data. 0
|
||||
* means this structure is a leaf, holding RAA_BLKSIZE real
|
||||
* data items; 1 and above mean it's a branch, holding
|
||||
* RAA_LAYERSIZE pointers to the next level branch or leaf
|
||||
* structures.
|
||||
*/
|
||||
int layers;
|
||||
/*
|
||||
* Number of real data items spanned by one position in the
|
||||
* `data' array at this level. This number is 1, trivially, for
|
||||
* a leaf (level 0): for a level 1 branch it should be
|
||||
* RAA_BLKSIZE, and for a level 2 branch it's
|
||||
* RAA_LAYERSIZE*RAA_BLKSIZE.
|
||||
*/
|
||||
long stepsize;
|
||||
union RAA_UNION {
|
||||
struct RAA_LEAF {
|
||||
long data[RAA_BLKSIZE];
|
||||
} l;
|
||||
struct RAA_BRANCH {
|
||||
struct RAA *data[RAA_LAYERSIZE];
|
||||
} b;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct RAA *raa_init (void);
|
||||
void raa_free (struct RAA *);
|
||||
@ -125,7 +167,15 @@ struct RAA *raa_write (struct RAA *r, long posn, long value);
|
||||
* of a given size.
|
||||
*/
|
||||
|
||||
struct SAA;
|
||||
struct SAA {
|
||||
/*
|
||||
* members `end' and `elem_len' are only valid in first link in
|
||||
* list; `rptr' and `rpos' are used for reading
|
||||
*/
|
||||
struct SAA *next, *end, *rptr;
|
||||
long elem_len, length, posn, start, rpos;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct SAA *saa_init (long elem_len); /* 1 == byte */
|
||||
void saa_free (struct SAA *);
|
||||
@ -169,4 +219,23 @@ long reloc_wrt(expr *);
|
||||
*/
|
||||
int bsi (char *string, char **array, int size);
|
||||
|
||||
|
||||
char *src_set_fname(char *newname);
|
||||
long src_set_linnum(long newline);
|
||||
long src_get_linnum(void);
|
||||
/*
|
||||
* src_get may be used if you simply want to know the source file and line.
|
||||
* It is also used if you maintain private status about the source location
|
||||
* It return 0 if the information was the same as the last time you
|
||||
* checked, -1 if the name changed and (new-old) if just the line changed.
|
||||
*/
|
||||
int src_get(long *xline, char **xname);
|
||||
|
||||
void nasm_quote(char **str);
|
||||
char *nasm_strcat(char *one, char *two);
|
||||
void nasmlib_cleanup(void);
|
||||
|
||||
void null_debug_routine();
|
||||
extern struct dfmt null_debug_form;
|
||||
extern struct dfmt *null_debug_arr[2];
|
||||
#endif
|
||||
|
41
ndisasm.c
41
ndisasm.c
@ -33,7 +33,8 @@ static const char *help =
|
||||
static void output_ins (unsigned long, unsigned char *, int, char *);
|
||||
static void skip (unsigned long dist, FILE *fp);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned char buffer[INSN_MAX * 2], *p, *q;
|
||||
char outbuf[256];
|
||||
char *pname = *argv;
|
||||
@ -52,7 +53,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
while (--argc) {
|
||||
char *v, *vv, *p = *++argv;
|
||||
if (*p == '-') {
|
||||
if (*p == '-' && p[1]) {
|
||||
p++;
|
||||
while (*p) switch (tolower(*p)) {
|
||||
case 'a': /* auto or intelligent sync */
|
||||
@ -170,12 +171,16 @@ int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: unable to open `%s': %s\n",
|
||||
pname, filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(filename, "-")) {
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: unable to open `%s': %s\n",
|
||||
pname, filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
fp = stdin;
|
||||
|
||||
if (initskip > 0)
|
||||
skip (initskip, fp);
|
||||
|
||||
@ -191,9 +196,12 @@ int main(int argc, char **argv) {
|
||||
unsigned long to_read = buffer+sizeof(buffer)-p;
|
||||
if (to_read > nextsync-offset-(p-q))
|
||||
to_read = nextsync-offset-(p-q);
|
||||
lenread = fread (p, 1, to_read, fp);
|
||||
if (lenread == 0)
|
||||
eof = TRUE; /* help along systems with bad feof */
|
||||
if (to_read) {
|
||||
lenread = fread (p, 1, to_read, fp);
|
||||
if (lenread == 0)
|
||||
eof = TRUE; /* help along systems with bad feof */
|
||||
} else
|
||||
lenread = 0;
|
||||
p += lenread;
|
||||
if (offset == nextsync) {
|
||||
if (synclen) {
|
||||
@ -222,12 +230,16 @@ int main(int argc, char **argv) {
|
||||
q = buffer;
|
||||
}
|
||||
} while (lenread > 0 || !(eof || feof(fp)));
|
||||
fclose (fp);
|
||||
|
||||
if (fp != stdin)
|
||||
fclose (fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void output_ins (unsigned long offset, unsigned char *data,
|
||||
int datalen, char *insn) {
|
||||
int datalen, char *insn)
|
||||
{
|
||||
int bytes;
|
||||
printf("%08lX ", offset);
|
||||
|
||||
@ -256,7 +268,8 @@ static void output_ins (unsigned long offset, unsigned char *data,
|
||||
* Skip a certain amount of data in a file, either by seeking if
|
||||
* possible, or if that fails then by reading and discarding.
|
||||
*/
|
||||
static void skip (unsigned long dist, FILE *fp) {
|
||||
static void skip (unsigned long dist, FILE *fp)
|
||||
{
|
||||
char buffer[256]; /* should fit on most stacks :-) */
|
||||
|
||||
/*
|
||||
|
73
outaout.c
73
outaout.c
@ -116,7 +116,8 @@ static long aout_gotpc_sect, aout_gotoff_sect;
|
||||
static long aout_got_sect, aout_plt_sect;
|
||||
static long aout_sym_sect;
|
||||
|
||||
static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
aoutfp = fp;
|
||||
error = errfunc;
|
||||
evaluate = eval;
|
||||
@ -140,7 +141,8 @@ static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
|
||||
#ifdef OF_AOUT
|
||||
|
||||
static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
bsd = FALSE;
|
||||
aoutg_init (fp, errfunc, ldef, eval);
|
||||
|
||||
@ -154,7 +156,8 @@ static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
|
||||
extern struct ofmt of_aoutb;
|
||||
|
||||
static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
bsd = TRUE;
|
||||
aoutg_init (fp, errfunc, ldef, eval);
|
||||
|
||||
@ -174,9 +177,12 @@ static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
|
||||
#endif
|
||||
|
||||
static void aout_cleanup(void) {
|
||||
static void aout_cleanup(int debuginfo)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
aout_pad_sections();
|
||||
aout_fixup_relocs(&stext);
|
||||
aout_fixup_relocs(&sdata);
|
||||
@ -199,7 +205,8 @@ static void aout_cleanup(void) {
|
||||
saa_free (strs);
|
||||
}
|
||||
|
||||
static long aout_section_names (char *name, int pass, int *bits) {
|
||||
static long aout_section_names (char *name, int pass, int *bits)
|
||||
{
|
||||
/*
|
||||
* Default to 32 bits.
|
||||
*/
|
||||
@ -220,7 +227,8 @@ static long aout_section_names (char *name, int pass, int *bits) {
|
||||
}
|
||||
|
||||
static void aout_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
int pos = strslen+4;
|
||||
struct Symbol *sym;
|
||||
int special_used = FALSE;
|
||||
@ -384,7 +392,8 @@ static void aout_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
|
||||
static void aout_add_reloc (struct Section *sect, long segment,
|
||||
int reltype, int bytes) {
|
||||
int reltype, int bytes)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
|
||||
@ -429,7 +438,8 @@ static void aout_add_reloc (struct Section *sect, long segment,
|
||||
*/
|
||||
static long aout_add_gsym_reloc (struct Section *sect,
|
||||
long segment, long offset,
|
||||
int type, int bytes, int exact) {
|
||||
int type, int bytes, int exact)
|
||||
{
|
||||
struct Symbol *sym, *sm, *shead;
|
||||
struct Reloc *r;
|
||||
|
||||
@ -500,7 +510,8 @@ static long aout_add_gsym_reloc (struct Section *sect,
|
||||
* offset from the `asym' symbol rather than the section.
|
||||
*/
|
||||
static long aout_add_gotoff_reloc (struct Section *sect, long segment,
|
||||
long offset, int bytes) {
|
||||
long offset, int bytes)
|
||||
{
|
||||
struct Reloc *r;
|
||||
struct Symbol *asym;
|
||||
|
||||
@ -534,7 +545,8 @@ static long aout_add_gotoff_reloc (struct Section *sect, long segment,
|
||||
}
|
||||
|
||||
static void aout_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
struct Section *s;
|
||||
long realbytes = type & OUT_SIZMASK;
|
||||
long addr;
|
||||
@ -695,7 +707,8 @@ static void aout_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
}
|
||||
|
||||
static void aout_pad_sections(void) {
|
||||
static void aout_pad_sections(void)
|
||||
{
|
||||
static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 };
|
||||
/*
|
||||
* Pad each of the text and data sections with NOPs until their
|
||||
@ -716,7 +729,8 @@ static void aout_pad_sections(void) {
|
||||
* the relocation table, _after_ the final size of each section is
|
||||
* known, and fix up the relocations pointed to.
|
||||
*/
|
||||
static void aout_fixup_relocs(struct Section *sect) {
|
||||
static void aout_fixup_relocs(struct Section *sect)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
saa_rewind (sect->data);
|
||||
@ -748,7 +762,8 @@ static void aout_fixup_relocs(struct Section *sect) {
|
||||
}
|
||||
}
|
||||
|
||||
static void aout_write(void) {
|
||||
static void aout_write(void)
|
||||
{
|
||||
/*
|
||||
* Emit the a.out header.
|
||||
*/
|
||||
@ -786,7 +801,8 @@ static void aout_write(void) {
|
||||
saa_fpwrite (strs, aoutfp);
|
||||
}
|
||||
|
||||
static void aout_write_relocs (struct Reloc *r) {
|
||||
static void aout_write_relocs (struct Reloc *r)
|
||||
{
|
||||
while (r) {
|
||||
unsigned long word2;
|
||||
|
||||
@ -805,7 +821,8 @@ static void aout_write_relocs (struct Reloc *r) {
|
||||
}
|
||||
}
|
||||
|
||||
static void aout_write_syms (void) {
|
||||
static void aout_write_syms (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
saa_rewind (syms);
|
||||
@ -835,28 +852,38 @@ static void aout_write_syms (void) {
|
||||
}
|
||||
|
||||
static void aout_sect_write (struct Section *sect,
|
||||
unsigned char *data, unsigned long len) {
|
||||
unsigned char *data, unsigned long len)
|
||||
{
|
||||
saa_wbytes (sect->data, data, len);
|
||||
sect->len += len;
|
||||
}
|
||||
|
||||
static long aout_segbase (long segment) {
|
||||
static long aout_segbase (long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int aout_directive (char *directive, char *value, int pass) {
|
||||
static int aout_directive (char *directive, char *value, int pass)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aout_filename (char *inname, char *outname, efunc error) {
|
||||
static void aout_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
standard_extension (inname, outname, ".o", error);
|
||||
}
|
||||
|
||||
static char *aout_stdmac[] = {
|
||||
"%define __SECT__ [section .text]",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int aout_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* OF_AOUT || OF_AOUTB */
|
||||
|
||||
#ifdef OF_AOUT
|
||||
@ -864,8 +891,12 @@ static char *aout_stdmac[] = {
|
||||
struct ofmt of_aout = {
|
||||
"Linux a.out object files",
|
||||
"aout",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
aout_stdmac,
|
||||
aout_init,
|
||||
aout_set_info,
|
||||
aout_out,
|
||||
aout_deflabel,
|
||||
aout_section_names,
|
||||
@ -882,8 +913,12 @@ struct ofmt of_aout = {
|
||||
struct ofmt of_aoutb = {
|
||||
"NetBSD/FreeBSD a.out object files",
|
||||
"aoutb",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
aout_stdmac,
|
||||
aoutb_init,
|
||||
aout_set_info,
|
||||
aout_out,
|
||||
aout_deflabel,
|
||||
aout_section_names,
|
||||
|
60
outas86.c
60
outas86.c
@ -80,7 +80,8 @@ static void as86_write_section (struct Section *, int);
|
||||
static int as86_add_string (char *name);
|
||||
static void as86_sect_write(struct Section *, unsigned char *, unsigned long);
|
||||
|
||||
static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
as86fp = fp;
|
||||
error = errfunc;
|
||||
(void) ldef; /* placate optimisers */
|
||||
@ -105,9 +106,12 @@ static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
as86_add_string (as86_module);
|
||||
}
|
||||
|
||||
static void as86_cleanup(void) {
|
||||
static void as86_cleanup(int debuginfo)
|
||||
{
|
||||
struct Piece *p;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
as86_write();
|
||||
fclose (as86fp);
|
||||
saa_free (stext.data);
|
||||
@ -127,7 +131,8 @@ static void as86_cleanup(void) {
|
||||
saa_free (strs);
|
||||
}
|
||||
|
||||
static long as86_section_names (char *name, int pass, int *bits) {
|
||||
static long as86_section_names (char *name, int pass, int *bits)
|
||||
{
|
||||
/*
|
||||
* Default is 16 bits.
|
||||
*/
|
||||
@ -147,7 +152,8 @@ static long as86_section_names (char *name, int pass, int *bits) {
|
||||
return NO_SEG;
|
||||
}
|
||||
|
||||
static int as86_add_string (char *name) {
|
||||
static int as86_add_string (char *name)
|
||||
{
|
||||
int pos = strslen;
|
||||
int length = strlen(name);
|
||||
|
||||
@ -158,7 +164,8 @@ static int as86_add_string (char *name) {
|
||||
}
|
||||
|
||||
static void as86_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
struct Symbol *sym;
|
||||
|
||||
if (special)
|
||||
@ -207,7 +214,8 @@ static void as86_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
|
||||
static void as86_add_piece (struct Section *sect, int type, long offset,
|
||||
long segment, long bytes, int relative) {
|
||||
long segment, long bytes, int relative)
|
||||
{
|
||||
struct Piece *p;
|
||||
|
||||
sect->len += bytes;
|
||||
@ -237,7 +245,8 @@ static void as86_add_piece (struct Section *sect, int type, long offset,
|
||||
}
|
||||
|
||||
static void as86_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
struct Section *s;
|
||||
long realbytes = type & OUT_SIZMASK;
|
||||
long offset;
|
||||
@ -339,7 +348,8 @@ static void as86_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
}
|
||||
|
||||
static void as86_write(void) {
|
||||
static void as86_write(void)
|
||||
{
|
||||
int i;
|
||||
long symlen, seglen, segsize;
|
||||
|
||||
@ -430,7 +440,8 @@ static void as86_write(void) {
|
||||
fputc (0, as86fp); /* termination */
|
||||
}
|
||||
|
||||
static void as86_set_rsize (int size) {
|
||||
static void as86_set_rsize (int size)
|
||||
{
|
||||
if (as86_reloc_size != size) {
|
||||
switch (as86_reloc_size = size) {
|
||||
case 1: fputc (0x01, as86fp); break;
|
||||
@ -441,7 +452,8 @@ static void as86_set_rsize (int size) {
|
||||
}
|
||||
}
|
||||
|
||||
static void as86_write_section (struct Section *sect, int index) {
|
||||
static void as86_write_section (struct Section *sect, int index)
|
||||
{
|
||||
struct Piece *p;
|
||||
unsigned long s;
|
||||
long length;
|
||||
@ -512,20 +524,24 @@ static void as86_write_section (struct Section *sect, int index) {
|
||||
}
|
||||
|
||||
static void as86_sect_write (struct Section *sect,
|
||||
unsigned char *data, unsigned long len) {
|
||||
unsigned char *data, unsigned long len)
|
||||
{
|
||||
saa_wbytes (sect->data, data, len);
|
||||
sect->datalen += len;
|
||||
}
|
||||
|
||||
static long as86_segbase (long segment) {
|
||||
static long as86_segbase (long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int as86_directive (char *directive, char *value, int pass) {
|
||||
static int as86_directive (char *directive, char *value, int pass)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void as86_filename (char *inname, char *outname, efunc error) {
|
||||
static void as86_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ( (p = strrchr (inname, '.')) != NULL) {
|
||||
@ -539,16 +555,30 @@ static void as86_filename (char *inname, char *outname, efunc error) {
|
||||
|
||||
static char *as86_stdmac[] = {
|
||||
"%define __SECT__ [section .text]",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int as86_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void as86_linenumber (char *name, long segment, long offset, int is_main,
|
||||
int lineno)
|
||||
{
|
||||
}
|
||||
struct ofmt of_as86 = {
|
||||
"Linux as86 (bin86 version 0.3) object files",
|
||||
"as86",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
as86_stdmac,
|
||||
as86_init,
|
||||
as86_set_info,
|
||||
as86_out,
|
||||
as86_deflabel,
|
||||
as86_deflabel,
|
||||
as86_section_names,
|
||||
as86_segbase,
|
||||
as86_directive,
|
||||
|
57
outbin.c
57
outbin.c
@ -42,7 +42,8 @@ static long data_align, bss_align;
|
||||
static long start_point;
|
||||
|
||||
static void add_reloc (struct Section *s, long bytes, long secref,
|
||||
long secrel) {
|
||||
long secrel)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
r = *reloctail = nasm_malloc(sizeof(struct Reloc));
|
||||
@ -55,9 +56,12 @@ static void add_reloc (struct Section *s, long bytes, long secref,
|
||||
r->target = s;
|
||||
}
|
||||
|
||||
static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
fp = afp;
|
||||
|
||||
(void) eval; /* Don't warn that this parameter is unused */
|
||||
|
||||
error = errfunc;
|
||||
(void) ldef; /* placate optimisers */
|
||||
|
||||
@ -74,10 +78,13 @@ static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
data_align = bss_align = 4;
|
||||
}
|
||||
|
||||
static void bin_cleanup (void) {
|
||||
static void bin_cleanup (int debuginfo)
|
||||
{
|
||||
struct Reloc *r;
|
||||
long datapos, datagap, bsspos;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
datapos = start_point + textsect.length;
|
||||
datapos = (datapos + data_align-1) & ~(data_align-1);
|
||||
datagap = datapos - (start_point + textsect.length);
|
||||
@ -87,7 +94,8 @@ static void bin_cleanup (void) {
|
||||
saa_rewind (textsect.contents);
|
||||
saa_rewind (datasect.contents);
|
||||
|
||||
for (r = relocs; r; r = r->next) {
|
||||
for (r = relocs; r; r = r->next)
|
||||
{
|
||||
unsigned char *p, *q, mydata[4];
|
||||
long l;
|
||||
|
||||
@ -141,7 +149,8 @@ static void bin_cleanup (void) {
|
||||
}
|
||||
|
||||
static void bin_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
unsigned char *p, mydata[4];
|
||||
struct Section *s;
|
||||
long realbytes;
|
||||
@ -221,8 +230,10 @@ static void bin_out (long segto, void *data, unsigned long type,
|
||||
s->length += type;
|
||||
} else
|
||||
bsslen += type;
|
||||
} else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
|
||||
(type & OUT_TYPMASK) == OUT_REL4ADR) {
|
||||
}
|
||||
else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
|
||||
(type & OUT_TYPMASK) == OUT_REL4ADR)
|
||||
{
|
||||
realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
|
||||
if (segment != NO_SEG &&
|
||||
segment != textsect.index &&
|
||||
@ -251,7 +262,11 @@ static void bin_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
|
||||
static void bin_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
|
||||
(void) segment; /* Don't warn that this parameter is unused */
|
||||
(void) offset; /* Don't warn that this parameter is unused */
|
||||
|
||||
if (special)
|
||||
error (ERR_NONFATAL, "binary format does not support any"
|
||||
@ -268,11 +283,14 @@ static void bin_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
}
|
||||
|
||||
static long bin_secname (char *name, int pass, int *bits) {
|
||||
static long bin_secname (char *name, int pass, int *bits)
|
||||
{
|
||||
int sec_index;
|
||||
long *sec_align;
|
||||
char *p;
|
||||
|
||||
(void) pass; /* Don't warn that this parameter is unused */
|
||||
|
||||
/*
|
||||
* Default is 16 bits.
|
||||
*/
|
||||
@ -318,13 +336,17 @@ static long bin_secname (char *name, int pass, int *bits) {
|
||||
return sec_index;
|
||||
}
|
||||
|
||||
static long bin_segbase (long segment) {
|
||||
static long bin_segbase (long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int bin_directive (char *directive, char *value, int pass) {
|
||||
static int bin_directive (char *directive, char *value, int pass)
|
||||
{
|
||||
int rn_error;
|
||||
|
||||
(void) pass; /* Don't warn that this parameter is unused */
|
||||
|
||||
if (!strcmp(directive, "org")) {
|
||||
start_point = readnum (value, &rn_error);
|
||||
if (rn_error)
|
||||
@ -334,7 +356,8 @@ static int bin_directive (char *directive, char *value, int pass) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bin_filename (char *inname, char *outname, efunc error) {
|
||||
static void bin_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
standard_extension (inname, outname, "", error);
|
||||
}
|
||||
|
||||
@ -343,14 +366,24 @@ static char *bin_stdmac[] = {
|
||||
"%imacro org 1+.nolist",
|
||||
"[org %1]",
|
||||
"%endmacro",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int bin_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct ofmt of_bin = {
|
||||
"flat-form binary files (e.g. DOS .COM, .SYS)",
|
||||
"bin",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
bin_stdmac,
|
||||
bin_init,
|
||||
bin_set_info,
|
||||
bin_out,
|
||||
bin_deflabel,
|
||||
bin_secname,
|
||||
|
84
outcoff.c
84
outcoff.c
@ -127,21 +127,24 @@ static void coff_section_header (char *, long, long, long, long, int, long);
|
||||
static void coff_write_relocs (struct Section *);
|
||||
static void coff_write_symbols (void);
|
||||
|
||||
static void coff_win32_init(FILE *fp, efunc errfunc,
|
||||
ldfunc ldef, evalfunc eval) {
|
||||
static void coff_win32_init(FILE *fp, efunc errfunc,
|
||||
ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
win32 = TRUE;
|
||||
(void) ldef; /* placate optimisers */
|
||||
coff_gen_init(fp, errfunc);
|
||||
}
|
||||
|
||||
static void coff_std_init(FILE *fp, efunc errfunc,
|
||||
ldfunc ldef, evalfunc eval) {
|
||||
static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
win32 = FALSE;
|
||||
(void) ldef; /* placate optimisers */
|
||||
coff_gen_init(fp, errfunc);
|
||||
}
|
||||
|
||||
static void coff_gen_init(FILE *fp, efunc errfunc) {
|
||||
static void coff_gen_init(FILE *fp, efunc errfunc)
|
||||
{
|
||||
|
||||
coffp = fp;
|
||||
error = errfunc;
|
||||
sects = NULL;
|
||||
@ -155,10 +158,13 @@ static void coff_gen_init(FILE *fp, efunc errfunc) {
|
||||
def_seg = seg_alloc();
|
||||
}
|
||||
|
||||
static void coff_cleanup(void) {
|
||||
static void coff_cleanup(int debuginfo)
|
||||
{
|
||||
struct Reloc *r;
|
||||
int i;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
coff_write();
|
||||
fclose (coffp);
|
||||
for (i=0; i<nsects; i++) {
|
||||
@ -169,6 +175,7 @@ static void coff_cleanup(void) {
|
||||
sects[i]->head = sects[i]->head->next;
|
||||
nasm_free (r);
|
||||
}
|
||||
nasm_free (sects[i]);
|
||||
}
|
||||
nasm_free (sects);
|
||||
saa_free (syms);
|
||||
@ -177,7 +184,8 @@ static void coff_cleanup(void) {
|
||||
saa_free (strs);
|
||||
}
|
||||
|
||||
static int coff_make_section (char *name, unsigned long flags) {
|
||||
static int coff_make_section (char *name, unsigned long flags)
|
||||
{
|
||||
struct Section *s;
|
||||
|
||||
s = nasm_malloc (sizeof(*s));
|
||||
@ -205,7 +213,8 @@ static int coff_make_section (char *name, unsigned long flags) {
|
||||
return nsects-1;
|
||||
}
|
||||
|
||||
static long coff_section_names (char *name, int pass, int *bits) {
|
||||
static long coff_section_names (char *name, int pass, int *bits)
|
||||
{
|
||||
char *p;
|
||||
unsigned long flags, align_and = ~0L, align_or = 0L;
|
||||
int i;
|
||||
@ -225,7 +234,7 @@ static long coff_section_names (char *name, int pass, int *bits) {
|
||||
if (strlen(name) > 8) {
|
||||
error (ERR_WARNING, "COFF section names limited to 8 characters:"
|
||||
" truncating");
|
||||
p[8] = '\0';
|
||||
name[8] = '\0';
|
||||
}
|
||||
flags = 0;
|
||||
|
||||
@ -306,7 +315,8 @@ static long coff_section_names (char *name, int pass, int *bits) {
|
||||
}
|
||||
|
||||
static void coff_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
int pos = strslen+4;
|
||||
struct Symbol *sym;
|
||||
|
||||
@ -363,7 +373,8 @@ static void coff_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
|
||||
static long coff_add_reloc (struct Section *sect, long segment,
|
||||
int relative) {
|
||||
int relative)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
|
||||
@ -399,7 +410,8 @@ static long coff_add_reloc (struct Section *sect, long segment,
|
||||
}
|
||||
|
||||
static void coff_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
struct Section *s;
|
||||
long realbytes = type & OUT_SIZMASK;
|
||||
unsigned char mydata[4], *p;
|
||||
@ -506,16 +518,19 @@ static void coff_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
|
||||
static void coff_sect_write (struct Section *sect,
|
||||
unsigned char *data, unsigned long len) {
|
||||
unsigned char *data, unsigned long len)
|
||||
{
|
||||
saa_wbytes (sect->data, data, len);
|
||||
sect->len += len;
|
||||
}
|
||||
|
||||
static int coff_directives (char *directive, char *value, int pass) {
|
||||
static int coff_directives (char *directive, char *value, int pass)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coff_write (void) {
|
||||
static void coff_write (void)
|
||||
{
|
||||
long pos, sympos, vsize;
|
||||
int i;
|
||||
|
||||
@ -579,7 +594,8 @@ static void coff_write (void) {
|
||||
|
||||
static void coff_section_header (char *name, long vsize,
|
||||
long datalen, long datapos,
|
||||
long relpos, int nrelocs, long flags) {
|
||||
long relpos, int nrelocs, long flags)
|
||||
{
|
||||
char padname[8];
|
||||
|
||||
memset (padname, 0, 8);
|
||||
@ -596,7 +612,8 @@ static void coff_section_header (char *name, long vsize,
|
||||
fwritelong (flags, coffp);
|
||||
}
|
||||
|
||||
static void coff_write_relocs (struct Section *s) {
|
||||
static void coff_write_relocs (struct Section *s)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
for (r = s->head; r; r = r->next) {
|
||||
@ -615,7 +632,8 @@ static void coff_write_relocs (struct Section *s) {
|
||||
}
|
||||
|
||||
static void coff_symbol (char *name, long strpos, long value,
|
||||
int section, int type, int aux) {
|
||||
int section, int type, int aux)
|
||||
{
|
||||
char padname[8];
|
||||
|
||||
if (name) {
|
||||
@ -633,7 +651,8 @@ static void coff_symbol (char *name, long strpos, long value,
|
||||
fputc (aux, coffp);
|
||||
}
|
||||
|
||||
static void coff_write_symbols (void) {
|
||||
static void coff_write_symbols (void)
|
||||
{
|
||||
char filename[18];
|
||||
int i;
|
||||
|
||||
@ -674,34 +693,47 @@ static void coff_write_symbols (void) {
|
||||
}
|
||||
}
|
||||
|
||||
static long coff_segbase (long segment) {
|
||||
static long coff_segbase (long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static void coff_std_filename (char *inname, char *outname, efunc error) {
|
||||
static void coff_std_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
strcpy(coff_infile, inname);
|
||||
standard_extension (inname, outname, ".o", error);
|
||||
}
|
||||
|
||||
static void coff_win32_filename (char *inname, char *outname, efunc error) {
|
||||
static void coff_win32_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
strcpy(coff_infile, inname);
|
||||
standard_extension (inname, outname, ".obj", error);
|
||||
}
|
||||
|
||||
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
|
||||
|
||||
static char *coff_stdmac[] = {
|
||||
"%define __SECT__ [section .text]",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int coff_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
|
||||
|
||||
#ifdef OF_COFF
|
||||
|
||||
struct ofmt of_coff = {
|
||||
"COFF (i386) object files (e.g. DJGPP for DOS)",
|
||||
"coff",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
coff_stdmac,
|
||||
coff_std_init,
|
||||
coff_set_info,
|
||||
coff_out,
|
||||
coff_deflabel,
|
||||
coff_section_names,
|
||||
@ -718,8 +750,12 @@ struct ofmt of_coff = {
|
||||
struct ofmt of_win32 = {
|
||||
"Microsoft Win32 (i386) object files",
|
||||
"win32",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
coff_stdmac,
|
||||
coff_win32_init,
|
||||
coff_set_info,
|
||||
coff_out,
|
||||
coff_deflabel,
|
||||
coff_section_names,
|
||||
|
95
outdbg.c
95
outdbg.c
@ -27,17 +27,24 @@ struct Section {
|
||||
FILE *dbgf;
|
||||
efunc dbgef;
|
||||
|
||||
struct ofmt of_dbg;
|
||||
static void dbg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
(void) eval;
|
||||
|
||||
dbgf = fp;
|
||||
dbgef = errfunc;
|
||||
dbgsect = NULL;
|
||||
(void) ldef;
|
||||
fprintf(fp,"NASM Output format debug dump\n");
|
||||
of_dbg.current_dfmt->init(&of_dbg,0,fp,errfunc);
|
||||
|
||||
}
|
||||
|
||||
static void dbg_cleanup(void)
|
||||
static void dbg_cleanup(int debuginfo)
|
||||
{
|
||||
(void) debuginfo;
|
||||
of_dbg.current_dfmt->cleanup();
|
||||
while (dbgsect) {
|
||||
struct Section *tmp = dbgsect;
|
||||
dbgsect = dbgsect->next;
|
||||
@ -84,7 +91,8 @@ static long dbg_section_names (char *name, int pass, int *bits)
|
||||
}
|
||||
|
||||
static void dbg_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
fprintf(dbgf,"deflabel %s := %08lx:%08lx %s (%d)%s%s\n",
|
||||
name, segment, offset,
|
||||
is_global == 2 ? "common" : is_global ? "global" : "local",
|
||||
@ -93,7 +101,8 @@ static void dbg_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
|
||||
static void dbg_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
long realbytes = type & OUT_SIZMASK;
|
||||
long ldata;
|
||||
int id;
|
||||
@ -135,25 +144,99 @@ static void dbg_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
}
|
||||
|
||||
static long dbg_segbase(long segment) {
|
||||
static long dbg_segbase(long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int dbg_directive (char *directive, char *value, int pass) {
|
||||
static int dbg_directive (char *directive, char *value, int pass)
|
||||
{
|
||||
fprintf(dbgf, "directive [%s] value [%s] (pass %d)\n",
|
||||
directive, value, pass);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dbg_filename (char *inname, char *outname, efunc error) {
|
||||
static void dbg_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
standard_extension (inname, outname, ".dbg", error);
|
||||
}
|
||||
|
||||
static int dbg_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
(void) type;
|
||||
(void) val;
|
||||
return 0;
|
||||
}
|
||||
char *types[] = {
|
||||
"unknown", "label", "byte","word","dword","float","qword","tbyte"
|
||||
};
|
||||
void dbgdbg_init(struct ofmt * of, void * id, FILE * fp, efunc error)
|
||||
{
|
||||
(void) of;
|
||||
(void) id;
|
||||
(void) fp;
|
||||
(void) error;
|
||||
fprintf(fp," With debug info\n");
|
||||
}
|
||||
static void dbgdbg_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void dbgdbg_linnum (const char *lnfname, long lineno, long segto)
|
||||
{
|
||||
fprintf(dbgf,"dbglinenum %s(%ld) := %08lx\n",
|
||||
lnfname,lineno,segto);
|
||||
}
|
||||
static void dbgdbg_deflabel (char *name, long segment,
|
||||
long offset, int is_global, char *special)
|
||||
{
|
||||
fprintf(dbgf,"dbglabel %s := %08lx:%08lx %s (%d)%s%s\n",
|
||||
name,
|
||||
segment, offset,
|
||||
is_global == 2 ? "common" : is_global ? "global" : "local",
|
||||
is_global,
|
||||
special ? ": " : "", special);
|
||||
}
|
||||
static void dbgdbg_define(const char *type, const char *params)
|
||||
{
|
||||
fprintf(dbgf,"dbgdirective [%s] value [%s]\n",type, params);
|
||||
}
|
||||
static void dbgdbg_output (int output_type, void *param)
|
||||
{
|
||||
(void) output_type;
|
||||
(void) param;
|
||||
}
|
||||
static void dbgdbg_typevalue(long type)
|
||||
{
|
||||
fprintf(dbgf,"new type: %s(%lX)\n",
|
||||
types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type) );
|
||||
}
|
||||
static struct dfmt debug_debug_form = {
|
||||
"Trace of all info passed to debug stage",
|
||||
"debug",
|
||||
dbgdbg_init,
|
||||
dbgdbg_linnum,
|
||||
dbgdbg_deflabel,
|
||||
dbgdbg_define,
|
||||
dbgdbg_typevalue,
|
||||
dbgdbg_output,
|
||||
dbgdbg_cleanup,
|
||||
};
|
||||
|
||||
static struct dfmt *debug_debug_arr[3] = {
|
||||
&debug_debug_form,
|
||||
&null_debug_form,
|
||||
NULL
|
||||
};
|
||||
struct ofmt of_dbg = {
|
||||
"Trace of all info passed to output stage",
|
||||
"dbg",
|
||||
NULL,
|
||||
debug_debug_arr,
|
||||
&null_debug_form,
|
||||
NULL,
|
||||
dbg_init,
|
||||
dbg_set_info,
|
||||
dbg_out,
|
||||
dbg_deflabel,
|
||||
dbg_section_names,
|
||||
|
95
outelf.c
95
outelf.c
@ -117,7 +117,7 @@ static struct ELF_SECTDATA {
|
||||
void *data;
|
||||
long len;
|
||||
int is_saa;
|
||||
} elf_sects[ELF_MAX_SECTIONS];
|
||||
} *elf_sects;
|
||||
static int elf_nsect;
|
||||
static long elf_foffs;
|
||||
|
||||
@ -139,7 +139,8 @@ static long elf_gotpc_sect, elf_gotoff_sect;
|
||||
static long elf_got_sect, elf_plt_sect;
|
||||
static long elf_sym_sect;
|
||||
|
||||
static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
elffp = fp;
|
||||
error = errfunc;
|
||||
evaluate = eval;
|
||||
@ -173,10 +174,13 @@ static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
|
||||
def_seg = seg_alloc();
|
||||
}
|
||||
|
||||
static void elf_cleanup(void) {
|
||||
static void elf_cleanup(int debuginfo)
|
||||
{
|
||||
struct Reloc *r;
|
||||
int i;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
elf_write();
|
||||
fclose (elffp);
|
||||
for (i=0; i<nsects; i++) {
|
||||
@ -196,7 +200,8 @@ static void elf_cleanup(void) {
|
||||
saa_free (strs);
|
||||
}
|
||||
|
||||
static void add_sectname (char *firsthalf, char *secondhalf) {
|
||||
static void add_sectname (char *firsthalf, char *secondhalf)
|
||||
{
|
||||
int len = strlen(firsthalf)+strlen(secondhalf);
|
||||
while (shstrtablen + len + 1 > shstrtabsize)
|
||||
shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
|
||||
@ -205,7 +210,8 @@ static void add_sectname (char *firsthalf, char *secondhalf) {
|
||||
shstrtablen += len+1;
|
||||
}
|
||||
|
||||
static int elf_make_section (char *name, int type, int flags, int align) {
|
||||
static int elf_make_section (char *name, int type, int flags, int align)
|
||||
{
|
||||
struct Section *s;
|
||||
|
||||
s = nasm_malloc (sizeof(*s));
|
||||
@ -235,18 +241,18 @@ static int elf_make_section (char *name, int type, int flags, int align) {
|
||||
return nsects-1;
|
||||
}
|
||||
|
||||
static long elf_section_names (char *name, int pass, int *bits) {
|
||||
static long elf_section_names (char *name, int pass, int *bits)
|
||||
{
|
||||
char *p;
|
||||
int flags_and, flags_or, type, align, i;
|
||||
|
||||
/*
|
||||
* Default is 32 bits.
|
||||
*/
|
||||
if (!name)
|
||||
if (!name) {
|
||||
*bits = 32;
|
||||
|
||||
if (!name)
|
||||
return def_seg;
|
||||
}
|
||||
|
||||
p = name;
|
||||
while (*p && !isspace(*p)) p++;
|
||||
@ -334,7 +340,8 @@ static long elf_section_names (char *name, int pass, int *bits) {
|
||||
}
|
||||
|
||||
static void elf_deflabel (char *name, long segment, long offset,
|
||||
int is_global, char *special) {
|
||||
int is_global, char *special)
|
||||
{
|
||||
int pos = strslen;
|
||||
struct Symbol *sym;
|
||||
int special_used = FALSE;
|
||||
@ -439,9 +446,29 @@ static void elf_deflabel (char *name, long segment, long offset,
|
||||
sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
|
||||
|
||||
if (sym->type == SYM_GLOBAL) {
|
||||
/*
|
||||
* There's a problem here that needs fixing.
|
||||
* If sym->section == SHN_ABS, then the first line of the
|
||||
* else section causes a core dump, because its a reference
|
||||
* beyond the end of the section array.
|
||||
* This behaviour is exhibited by this code:
|
||||
* GLOBAL crash_nasm
|
||||
* crash_nasm equ 0
|
||||
*
|
||||
* I'm not sure how to procede, because I haven't got the
|
||||
* first clue about how ELF works, so I don't know what to
|
||||
* do with it. Furthermore, I'm not sure what the rest of this
|
||||
* section of code does. Help?
|
||||
*
|
||||
* For now, I'll see if doing absolutely nothing with it will
|
||||
* work...
|
||||
*/
|
||||
if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
|
||||
{
|
||||
bsym = raa_write (bsym, segment, nglobs);
|
||||
else {
|
||||
}
|
||||
else if (sym->section != SHN_ABS)
|
||||
{
|
||||
/*
|
||||
* This is a global symbol; so we must add it to the linked
|
||||
* list of global symbols in its section. We'll push it on
|
||||
@ -505,7 +532,8 @@ static void elf_deflabel (char *name, long segment, long offset,
|
||||
}
|
||||
|
||||
static void elf_add_reloc (struct Section *sect, long segment,
|
||||
int type) {
|
||||
int type)
|
||||
{
|
||||
struct Reloc *r;
|
||||
|
||||
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
|
||||
@ -553,7 +581,8 @@ static void elf_add_reloc (struct Section *sect, long segment,
|
||||
*/
|
||||
static long elf_add_gsym_reloc (struct Section *sect,
|
||||
long segment, long offset,
|
||||
int type, int exact) {
|
||||
int type, int exact)
|
||||
{
|
||||
struct Reloc *r;
|
||||
struct Section *s;
|
||||
struct Symbol *sym, *sm;
|
||||
@ -617,7 +646,8 @@ static long elf_add_gsym_reloc (struct Section *sect,
|
||||
}
|
||||
|
||||
static void elf_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt) {
|
||||
long segment, long wrt)
|
||||
{
|
||||
struct Section *s;
|
||||
long realbytes = type & OUT_SIZMASK;
|
||||
long addr;
|
||||
@ -744,7 +774,8 @@ static void elf_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
}
|
||||
|
||||
static void elf_write(void) {
|
||||
static void elf_write(void)
|
||||
{
|
||||
int nsections, align;
|
||||
char *p;
|
||||
int commlen;
|
||||
@ -819,6 +850,7 @@ static void elf_write(void) {
|
||||
align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
|
||||
elf_foffs += align;
|
||||
elf_nsect = 0;
|
||||
elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10));
|
||||
|
||||
elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
|
||||
p = shstrtab+1;
|
||||
@ -853,10 +885,12 @@ static void elf_write(void) {
|
||||
*/
|
||||
elf_write_sections();
|
||||
|
||||
nasm_free (elf_sects);
|
||||
saa_free (symtab);
|
||||
}
|
||||
|
||||
static struct SAA *elf_build_symtab (long *len, long *local) {
|
||||
static struct SAA *elf_build_symtab (long *len, long *local)
|
||||
{
|
||||
struct SAA *s = saa_init(1L);
|
||||
struct Symbol *sym;
|
||||
unsigned char entry[16], *p;
|
||||
@ -968,7 +1002,8 @@ static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
|
||||
|
||||
static void elf_section_header (int name, int type, int flags,
|
||||
void *data, int is_saa, long datalen,
|
||||
int link, int info, int align, int eltsize) {
|
||||
int link, int info, int align, int eltsize)
|
||||
{
|
||||
elf_sects[elf_nsect].data = data;
|
||||
elf_sects[elf_nsect].len = datalen;
|
||||
elf_sects[elf_nsect].is_saa = is_saa;
|
||||
@ -988,7 +1023,8 @@ static void elf_section_header (int name, int type, int flags,
|
||||
fwritelong ((long)eltsize, elffp);
|
||||
}
|
||||
|
||||
static void elf_write_sections (void) {
|
||||
static void elf_write_sections (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < elf_nsect; i++)
|
||||
if (elf_sects[i].data) {
|
||||
@ -1004,34 +1040,49 @@ static void elf_write_sections (void) {
|
||||
}
|
||||
|
||||
static void elf_sect_write (struct Section *sect,
|
||||
unsigned char *data, unsigned long len) {
|
||||
unsigned char *data, unsigned long len)
|
||||
{
|
||||
saa_wbytes (sect->data, data, len);
|
||||
sect->len += len;
|
||||
}
|
||||
|
||||
static long elf_segbase (long segment) {
|
||||
static long elf_segbase (long segment)
|
||||
{
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int elf_directive (char *directive, char *value, int pass) {
|
||||
static int elf_directive (char *directive, char *value, int pass)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void elf_filename (char *inname, char *outname, efunc error) {
|
||||
static void elf_filename (char *inname, char *outname, efunc error)
|
||||
{
|
||||
strcpy(elf_module, inname);
|
||||
standard_extension (inname, outname, ".o", error);
|
||||
}
|
||||
|
||||
static char *elf_stdmac[] = {
|
||||
"%define __SECT__ [section .text]",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%define $_%1 $%1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
static int elf_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ofmt of_elf = {
|
||||
"ELF32 (i386) object files (e.g. Linux)",
|
||||
"elf",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
elf_stdmac,
|
||||
elf_init,
|
||||
elf_set_info,
|
||||
elf_out,
|
||||
elf_deflabel,
|
||||
elf_section_names,
|
||||
|
39
outform.c
39
outform.c
@ -11,9 +11,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUILD_DRIVERS_ARRAY
|
||||
#include "outform.h"
|
||||
|
||||
static struct ofmt *drivers[MAX_OUTPUT_FORMATS];
|
||||
static int ndrivers = 0;
|
||||
|
||||
struct ofmt *ofmt_find(char *name) /* find driver */
|
||||
@ -26,17 +27,45 @@ struct ofmt *ofmt_find(char *name) /* find driver */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
struct dfmt *dfmt_find(struct ofmt *ofmt, char *name) /* find driver */
|
||||
{
|
||||
struct dfmt **dfmt = ofmt->debug_formats;
|
||||
while (*dfmt) {
|
||||
if (!strcmp(name, (*dfmt)->shortname))
|
||||
return (*dfmt);
|
||||
dfmt++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ofmt_list(struct ofmt *deffmt, FILE *fp)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<ndrivers; i++)
|
||||
fprintf(fp, " %c %-7s%s\n",
|
||||
fprintf(fp, " %c %-10s%s\n",
|
||||
drivers[i] == deffmt ? '*' : ' ',
|
||||
drivers[i]->shortname,
|
||||
drivers[i]->fullname);
|
||||
}
|
||||
|
||||
void ofmt_register (struct ofmt *info) {
|
||||
drivers[ndrivers++] = info;
|
||||
void dfmt_list(struct ofmt *ofmt, FILE *fp)
|
||||
{
|
||||
struct dfmt ** drivers = ofmt->debug_formats;
|
||||
while (*drivers) {
|
||||
fprintf(fp, " %c %-10s%s\n",
|
||||
drivers[0] == ofmt->current_dfmt ? '*' : ' ',
|
||||
drivers[0]->shortname,
|
||||
drivers[0]->fullname);
|
||||
drivers++;
|
||||
}
|
||||
}
|
||||
struct ofmt *ofmt_register (efunc error) {
|
||||
for (ndrivers=0; drivers[ndrivers] != NULL; ndrivers++);
|
||||
|
||||
if (ndrivers==0)
|
||||
{
|
||||
error(ERR_PANIC | ERR_NOFILE,
|
||||
"No output drivers given at compile time");
|
||||
}
|
||||
|
||||
return (&OF_DEFAULT);
|
||||
}
|
||||
|
84
outform.h
84
outform.h
@ -20,6 +20,9 @@
|
||||
* OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf' are in.
|
||||
* OF_OTHERS -- ensure that 'bin', 'as86' & 'rdf' are in.
|
||||
* OF_ALL -- ensure that all formats are included.
|
||||
* note that this doesn't include 'dbg', which is
|
||||
* only really useful if you're doing development
|
||||
* work on NASM. Define OF_DBG if you want this.
|
||||
*
|
||||
* OF_DEFAULT=of_name -- ensure that 'name' is the default format.
|
||||
*
|
||||
@ -35,12 +38,6 @@
|
||||
|
||||
#include "nasm.h"
|
||||
|
||||
#define MAX_OUTPUT_FORMATS 16
|
||||
|
||||
struct ofmt *ofmt_find(char *);
|
||||
void ofmt_list(struct ofmt *, FILE *);
|
||||
void ofmt_register (struct ofmt *);
|
||||
|
||||
/* -------------- USER MODIFIABLE PART ---------------- */
|
||||
|
||||
/*
|
||||
@ -60,7 +57,7 @@ void ofmt_register (struct ofmt *);
|
||||
|
||||
/* ====configurable info begins here==== */
|
||||
/* formats configurable:
|
||||
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf */
|
||||
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf,rdf2 */
|
||||
|
||||
/* process options... */
|
||||
|
||||
@ -95,8 +92,8 @@ void ofmt_register (struct ofmt *);
|
||||
#ifndef OF_AS86
|
||||
#define OF_AS86
|
||||
#endif
|
||||
#ifndef OF_RDF
|
||||
#define OF_RDF
|
||||
#ifndef OF_RDF2
|
||||
#define OF_RDF2
|
||||
#endif
|
||||
#endif /* OF_ALL */
|
||||
|
||||
@ -138,6 +135,9 @@ void ofmt_register (struct ofmt *);
|
||||
#ifndef OF_RDF
|
||||
#define OF_RDF
|
||||
#endif
|
||||
#ifndef OF_RDF2
|
||||
#define OF_RDF2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* finally... override any format specifically specifed to be off */
|
||||
@ -168,9 +168,75 @@ void ofmt_register (struct ofmt *);
|
||||
#ifdef OF_NO_RDF
|
||||
#undef OF_RDF
|
||||
#endif
|
||||
#ifdef OF_NO_RDF2
|
||||
#undef OF_RDF
|
||||
#endif
|
||||
|
||||
#ifndef OF_DEFAULT
|
||||
#define OF_DEFAULT of_bin
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_DRIVERS_ARRAY /* only if included from outform.c */
|
||||
|
||||
/* pull in the externs for the different formats, then make the *drivers
|
||||
* array based on the above defines */
|
||||
|
||||
extern struct ofmt of_bin;
|
||||
extern struct ofmt of_aout;
|
||||
extern struct ofmt of_aoutb;
|
||||
extern struct ofmt of_coff;
|
||||
extern struct ofmt of_elf;
|
||||
extern struct ofmt of_as86;
|
||||
extern struct ofmt of_obj;
|
||||
extern struct ofmt of_win32;
|
||||
extern struct ofmt of_rdf;
|
||||
extern struct ofmt of_rdf2;
|
||||
extern struct ofmt of_dbg;
|
||||
|
||||
struct ofmt *drivers[]={
|
||||
#ifdef OF_BIN
|
||||
&of_bin,
|
||||
#endif
|
||||
#ifdef OF_AOUT
|
||||
&of_aout,
|
||||
#endif
|
||||
#ifdef OF_AOUTB
|
||||
&of_aoutb,
|
||||
#endif
|
||||
#ifdef OF_COFF
|
||||
&of_coff,
|
||||
#endif
|
||||
#ifdef OF_ELF
|
||||
&of_elf,
|
||||
#endif
|
||||
#ifdef OF_AS86
|
||||
&of_as86,
|
||||
#endif
|
||||
#ifdef OF_OBJ
|
||||
&of_obj,
|
||||
#endif
|
||||
#ifdef OF_WIN32
|
||||
&of_win32,
|
||||
#endif
|
||||
#ifdef OF_RDF
|
||||
&of_rdf,
|
||||
#endif
|
||||
#ifdef OF_RDF2
|
||||
&of_rdf2,
|
||||
#endif
|
||||
#ifdef OF_DBG
|
||||
&of_dbg,
|
||||
#endif
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* BUILD_DRIVERS_ARRAY */
|
||||
|
||||
struct ofmt *ofmt_find(char *);
|
||||
struct dfmt *dfmt_find(struct ofmt *, char *);
|
||||
void ofmt_list(struct ofmt *, FILE *);
|
||||
void dfmt_list(struct ofmt *ofmt, FILE *fp);
|
||||
struct ofmt *ofmt_register (efunc error);
|
||||
|
||||
#endif /* NASM_OUTFORM_H */
|
||||
|
223
outforms.h
Normal file
223
outforms.h
Normal file
@ -0,0 +1,223 @@
|
||||
/* outform.h header file for binding output format drivers to the
|
||||
* remainder of the code in the Netwide Assembler
|
||||
*
|
||||
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
* Julian Hall. All rights reserved. The software is
|
||||
* redistributable under the licence given in the file "Licence"
|
||||
* distributed in the NASM archive.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header file allows configuration of which output formats
|
||||
* get compiled into the NASM binary. You can configure by defining
|
||||
* various preprocessor symbols beginning with "OF_", either on the
|
||||
* compiler command line or at the top of this file.
|
||||
*
|
||||
* OF_ONLY -- only include specified object formats
|
||||
* OF_name -- ensure that output format 'name' is included
|
||||
* OF_NO_name -- remove output format 'name'
|
||||
* OF_DOS -- ensure that 'obj', 'bin' & 'win32' are included.
|
||||
* OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf' are in.
|
||||
* OF_OTHERS -- ensure that 'bin', 'as86' & 'rdf' are in.
|
||||
* OF_ALL -- ensure that all formats are included.
|
||||
*
|
||||
* OF_DEFAULT=of_name -- ensure that 'name' is the default format.
|
||||
*
|
||||
* eg: -DOF_UNIX -DOF_ELF -DOF_DEFAULT=of_elf would be a suitable config
|
||||
* for an average linux system.
|
||||
*
|
||||
* Default config = -DOF_ALL -DOF_DEFAULT=of_bin
|
||||
*
|
||||
* You probably only want to set these options while compiling 'nasm.c'. */
|
||||
|
||||
#ifndef NASM_OUTFORMS_H
|
||||
#define NASM_OUTFORMS_H
|
||||
|
||||
#include "nasm.h"
|
||||
|
||||
/* -------------- USER MODIFIABLE PART ---------------- */
|
||||
|
||||
/*
|
||||
* Insert #defines here in accordance with the configuration
|
||||
* instructions above.
|
||||
*
|
||||
* E.g.
|
||||
*
|
||||
* #define OF_ONLY
|
||||
* #define OF_OBJ
|
||||
* #define OF_BIN
|
||||
*
|
||||
* for a 16-bit DOS assembler with no extraneous formats.
|
||||
*/
|
||||
|
||||
/* ------------ END USER MODIFIABLE PART -------------- */
|
||||
|
||||
/* ====configurable info begins here==== */
|
||||
/* formats configurable:
|
||||
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf */
|
||||
|
||||
/* process options... */
|
||||
|
||||
#ifndef OF_ONLY
|
||||
#ifndef OF_ALL
|
||||
#define OF_ALL /* default is to have all formats */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef OF_ALL /* set all formats on... */
|
||||
#ifndef OF_BIN
|
||||
#define OF_BIN
|
||||
#endif
|
||||
#ifndef OF_OBJ
|
||||
#define OF_OBJ
|
||||
#endif
|
||||
#ifndef OF_ELF
|
||||
#define OF_ELF
|
||||
#endif
|
||||
#ifndef OF_COFF
|
||||
#define OF_COFF
|
||||
#endif
|
||||
#ifndef OF_AOUT
|
||||
#define OF_AOUT
|
||||
#endif
|
||||
#ifndef OF_AOUTB
|
||||
#define OF_AOUTB
|
||||
#endif
|
||||
#ifndef OF_WIN32
|
||||
#define OF_WIN32
|
||||
#endif
|
||||
#ifndef OF_AS86
|
||||
#define OF_AS86
|
||||
#endif
|
||||
#ifndef OF_RDF
|
||||
#define OF_RDF
|
||||
#endif
|
||||
#endif /* OF_ALL */
|
||||
|
||||
/* turn on groups of formats specified.... */
|
||||
#ifdef OF_DOS
|
||||
#ifndef OF_OBJ
|
||||
#define OF_OBJ
|
||||
#endif
|
||||
#ifndef OF_BIN
|
||||
#define OF_BIN
|
||||
#endif
|
||||
#ifndef OF_WIN32
|
||||
#define OF_WIN32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef OF_UNIX
|
||||
#ifndef OF_AOUT
|
||||
#define OF_AOUT
|
||||
#endif
|
||||
#ifndef OF_AOUTB
|
||||
#define OF_AOUTB
|
||||
#endif
|
||||
#ifndef OF_COFF
|
||||
#define OF_COFF
|
||||
#endif
|
||||
#ifndef OF_ELF
|
||||
#define OF_ELF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef OF_OTHERS
|
||||
#ifndef OF_BIN
|
||||
#define OF_BIN
|
||||
#endif
|
||||
#ifndef OF_AS86
|
||||
#define OF_AS86
|
||||
#endif
|
||||
#ifndef OF_RDF
|
||||
#define OF_RDF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* finally... override any format specifically specifed to be off */
|
||||
#ifdef OF_NO_BIN
|
||||
#undef OF_BIN
|
||||
#endif
|
||||
#ifdef OF_NO_OBJ
|
||||
#undef OF_OBJ
|
||||
#endif
|
||||
#ifdef OF_NO_ELF
|
||||
#undef OF_ELF
|
||||
#endif
|
||||
#ifdef OF_NO_AOUT
|
||||
#undef OF_AOUT
|
||||
#endif
|
||||
#ifdef OF_NO_AOUTB
|
||||
#undef OF_AOUTB
|
||||
#endif
|
||||
#ifdef OF_NO_COFF
|
||||
#undef OF_COFF
|
||||
#endif
|
||||
#ifdef OF_NO_WIN32
|
||||
#undef OF_WIN32
|
||||
#endif
|
||||
#ifdef OF_NO_AS86
|
||||
#undef OF_AS86
|
||||
#endif
|
||||
#ifdef OF_NO_RDF
|
||||
#undef OF_RDF
|
||||
#endif
|
||||
|
||||
#ifndef OF_DEFAULT
|
||||
#define OF_DEFAULT of_bin
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_DRIVERS_ARRAY /* only if included from outform.c */
|
||||
|
||||
/* pull in the externs for the different formats, then make the *drivers
|
||||
* array based on the above defines */
|
||||
|
||||
extern struct ofmt of_bin;
|
||||
extern struct ofmt of_aout;
|
||||
extern struct ofmt of_aoutb;
|
||||
extern struct ofmt of_coff;
|
||||
extern struct ofmt of_elf;
|
||||
extern struct ofmt of_as86;
|
||||
extern struct ofmt of_obj;
|
||||
extern struct ofmt of_win32;
|
||||
extern struct ofmt of_rdf;
|
||||
extern struct ofmt of_dbg;
|
||||
|
||||
struct ofmt *drivers[]={
|
||||
#ifdef OF_BIN
|
||||
&of_bin,
|
||||
#endif
|
||||
#ifdef OF_AOUT
|
||||
&of_aout,
|
||||
#endif
|
||||
#ifdef OF_AOUTB
|
||||
&of_aoutb,
|
||||
#endif
|
||||
#ifdef OF_COFF
|
||||
&of_coff,
|
||||
#endif
|
||||
#ifdef OF_ELF
|
||||
&of_elf,
|
||||
#endif
|
||||
#ifdef OF_AS86
|
||||
&of_as86,
|
||||
#endif
|
||||
#ifdef OF_OBJ
|
||||
&of_obj,
|
||||
#endif
|
||||
#ifdef OF_WIN32
|
||||
&of_win32,
|
||||
#endif
|
||||
#ifdef OF_RDF
|
||||
&of_rdf,
|
||||
#endif
|
||||
#ifdef OF_DBG
|
||||
&of_dbg,
|
||||
#endif
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* BUILD_DRIVERS_ARRAY */
|
||||
|
||||
#endif /* NASM_OUTFORMS_H */
|
25
outrdf.c
25
outrdf.c
@ -316,6 +316,12 @@ static void rdf_out (long segto, void *data, unsigned long type,
|
||||
struct RelocRec rr;
|
||||
unsigned char databuf[4],*pd;
|
||||
|
||||
if (segto == NO_SEG) {
|
||||
if ((type & OUT_TYPMASK) != OUT_RESERVE)
|
||||
error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
|
||||
return;
|
||||
}
|
||||
|
||||
segto >>= 1; /* convert NASM segment no to RDF number */
|
||||
|
||||
if (segto != 0 && segto != 1 && segto != 2) {
|
||||
@ -426,11 +432,13 @@ static void rdf_out (long segto, void *data, unsigned long type,
|
||||
}
|
||||
}
|
||||
|
||||
static void rdf_cleanup (void) {
|
||||
static void rdf_cleanup (int debuginfo) {
|
||||
long l;
|
||||
unsigned char b[4],*d;
|
||||
struct BSSRec bs;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
|
||||
/* should write imported & exported symbol declarations to header here */
|
||||
|
||||
@ -496,14 +504,29 @@ static char *rdf_stdmac[] = {
|
||||
"%imacro library 1+.nolist",
|
||||
"[library %1]",
|
||||
"%endmacro",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int rdf_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ofmt of_rdf = {
|
||||
"Relocatable Dynamic Object File Format v1.1",
|
||||
#ifdef OF_RDF2
|
||||
"oldrdf",
|
||||
#else
|
||||
"rdf",
|
||||
#endif
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
rdf_stdmac,
|
||||
rdf_init,
|
||||
rdf_set_info,
|
||||
rdf_out,
|
||||
rdf_deflabel,
|
||||
rdf_section_names,
|
||||
|
690
outrdf2.c
Normal file
690
outrdf2.c
Normal file
@ -0,0 +1,690 @@
|
||||
/* outrdf2.c output routines for the Netwide Assembler to produce
|
||||
* RDOFF version 2 format object files (which are intended
|
||||
* mainly for use in proprietary projects, as the code to
|
||||
* load and execute them is very simple). They will also be
|
||||
* used for device drivers and possibly some executable files
|
||||
* in the MOSCOW operating system. See Rdoff.txt for
|
||||
* details.
|
||||
*
|
||||
* The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
|
||||
* Julian Hall. All rights reserved. The software is
|
||||
* redistributable under the licence given in the file "Licence"
|
||||
* distributed in the NASM archive.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nasm.h"
|
||||
#include "nasmlib.h"
|
||||
#include "outform.h"
|
||||
|
||||
/* VERBOSE_WARNINGS: define this to add some extra warnings... */
|
||||
#define VERBOSE_WARNINGS
|
||||
|
||||
#ifdef OF_RDF2
|
||||
|
||||
#define RDF_MAXSEGS 64 /* maximum number of segments - user configurable */
|
||||
|
||||
typedef unsigned short int16;
|
||||
typedef unsigned char byte;
|
||||
|
||||
static const char *RDOFF2Id = "RDOFF2"; /* written to start of RDOFF files */
|
||||
|
||||
|
||||
/* the records that can be found in the RDOFF header */
|
||||
|
||||
/* Note that whenever a segment is referred to in the RDOFF file, its number
|
||||
* is always half of the segment number that NASM uses to refer to it; this
|
||||
* is because NASM only allocates even numbered segments, so as to not
|
||||
* waste any of the 16 bits of segment number written to the file - this
|
||||
* allows up to 65533 external labels to be defined; otherwise it would be
|
||||
* 32764. */
|
||||
|
||||
struct RelocRec {
|
||||
byte type; /* must be 1, or 6 for segment base ref */
|
||||
byte reclen; /* set to 8 */
|
||||
byte segment; /* only 0 for code, or 1 for data supported,
|
||||
* but add 64 for relative refs (ie do not require
|
||||
* reloc @ loadtime, only linkage) */
|
||||
long offset; /* from start of segment in which reference is loc'd */
|
||||
byte length; /* 1 2 or 4 bytes */
|
||||
int16 refseg; /* segment to which reference refers to */
|
||||
};
|
||||
|
||||
struct ImportRec {
|
||||
byte type; /* must be 2, or 7 for FAR import */
|
||||
byte reclen; /* equals 3+label length */
|
||||
int16 segment; /* segment number allocated to the label for reloc
|
||||
* records - label is assumed to be at offset zero
|
||||
* in this segment, so linker must fix up with offset
|
||||
* of segment and of offset within segment */
|
||||
char label[33]; /* zero terminated... should be written to file until
|
||||
* the zero, but not after it - max len = 32 chars */
|
||||
};
|
||||
|
||||
struct ExportRec {
|
||||
byte type; /* must be 3 */
|
||||
byte reclen; /* equals 6+label length */
|
||||
byte segment; /* segment referred to (0/1) */
|
||||
long offset; /* offset within segment */
|
||||
char label[33]; /* zero terminated as above. max len = 32 chars */
|
||||
};
|
||||
|
||||
struct DLLRec {
|
||||
byte type; /* must be 4 */
|
||||
byte reclen; /* equals 1+library name */
|
||||
char libname[128]; /* name of library to link with at load time */
|
||||
};
|
||||
|
||||
struct BSSRec {
|
||||
byte type; /* must be 5 */
|
||||
byte reclen; /* equeals 4 */
|
||||
long amount; /* number of bytes BSS to reserve */
|
||||
};
|
||||
|
||||
#define COUNT_SEGTYPES 9
|
||||
|
||||
static char * segmenttypes[COUNT_SEGTYPES] = {
|
||||
"null", "text", "code", "data", "comment", "lcomment", "pcomment",
|
||||
"symdebug", "linedebug"
|
||||
};
|
||||
|
||||
static int segmenttypenumbers[COUNT_SEGTYPES] = {
|
||||
0, 1, 1, 2, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
/* code for managing buffers needed to seperate code and data into individual
|
||||
* sections until they are ready to be written to the file.
|
||||
* We'd better hope that it all fits in memory else we're buggered... */
|
||||
|
||||
#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096)
|
||||
* on 80x86 machines for efficiency */
|
||||
|
||||
/***********************************************************************
|
||||
* Actual code to deal with RDOFF2 ouput format begins here...
|
||||
*/
|
||||
|
||||
/* global variables set during the initialisation phase */
|
||||
|
||||
static struct SAA *seg[RDF_MAXSEGS]; /* seg 0 = code, seg 1 = data */
|
||||
static struct SAA *header; /* relocation/import/export records */
|
||||
|
||||
static FILE *ofile;
|
||||
|
||||
static efunc error;
|
||||
|
||||
static struct seginfo {
|
||||
char *segname;
|
||||
int segnumber;
|
||||
int16 segtype;
|
||||
int16 segreserved;
|
||||
long seglength;
|
||||
} segments[RDF_MAXSEGS];
|
||||
|
||||
static int nsegments;
|
||||
|
||||
static long bsslength;
|
||||
static long headerlength;
|
||||
|
||||
static void rdf2_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
|
||||
{
|
||||
int segtext, segdata, segbss;
|
||||
|
||||
/* set up the initial segments */
|
||||
segments[0].segname = ".text";
|
||||
segments[0].segnumber = 0;
|
||||
segments[0].segtype = 1;
|
||||
segments[0].segreserved = 0;
|
||||
segments[0].seglength = 0;
|
||||
|
||||
segments[1].segname = ".data";
|
||||
segments[1].segnumber = 1;
|
||||
segments[1].segtype = 2;
|
||||
segments[1].segreserved = 0;
|
||||
segments[1].seglength = 0;
|
||||
|
||||
segments[2].segname = ".bss";
|
||||
segments[2].segnumber = 2;
|
||||
segments[2].segtype = 0xFFFF; /* reserved - should never be produced */
|
||||
segments[2].segreserved = 0;
|
||||
segments[2].seglength = 0;
|
||||
|
||||
nsegments = 3;
|
||||
|
||||
ofile = fp;
|
||||
error = errfunc;
|
||||
|
||||
seg[0] = saa_init(1L);
|
||||
seg[1] = saa_init(1L);
|
||||
seg[2] = NULL; /* special case! */
|
||||
|
||||
header = saa_init(1L);
|
||||
|
||||
segtext = seg_alloc();
|
||||
segdata = seg_alloc();
|
||||
segbss = seg_alloc();
|
||||
if (segtext != 0 || segdata != 2 || segbss != 4)
|
||||
error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
|
||||
segtext,segdata,segbss);
|
||||
bsslength=0;
|
||||
headerlength = 0;
|
||||
}
|
||||
|
||||
static long rdf2_section_names(char *name, int pass, int *bits)
|
||||
{
|
||||
int i;
|
||||
char * p, * q;
|
||||
int code = -1;
|
||||
int reserved = 0;
|
||||
|
||||
/*
|
||||
* Default is 32 bits, in the text segment.
|
||||
*/
|
||||
if (!name) {
|
||||
*bits = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for segment type code following segment name */
|
||||
p = name;
|
||||
while (*p && !isspace(*p)) p++;
|
||||
if (*p) { /* we're now in whitespace */
|
||||
*p++ = '\0';
|
||||
while (*p && isspace(80)) *p++ = '\0';
|
||||
}
|
||||
if (*p) { /* we're now in an attribute value */
|
||||
/*
|
||||
* see if we have an optional ',number' following the type code
|
||||
*/
|
||||
if ((q = strchr(p, ','))) {
|
||||
*q++ = '\0';
|
||||
|
||||
reserved = readnum(q, &i);
|
||||
if (i) {
|
||||
error(ERR_NONFATAL, "value following comma must be numeric");
|
||||
reserved = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check it against the text strings in segmenttypes
|
||||
*/
|
||||
|
||||
for (i = 0; i < COUNT_SEGTYPES; i++)
|
||||
if (!nasm_stricmp(p, segmenttypes[i])) {
|
||||
code = segmenttypenumbers[i];
|
||||
break;
|
||||
}
|
||||
if (code == -1) { /* didn't find anything */
|
||||
code = readnum(p, &i);
|
||||
if (i) {
|
||||
error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",p);
|
||||
code = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (!strcmp(name, segments[i].segname)) {
|
||||
if (code != -1 || reserved != 0)
|
||||
error(ERR_NONFATAL, "segment attributes specified on"
|
||||
" redeclaration of segment");
|
||||
return segments[i].segnumber * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* declaring a new segment! */
|
||||
|
||||
if (code == -1) {
|
||||
error(ERR_NONFATAL, "new segment declared without type code");
|
||||
code = 3;
|
||||
}
|
||||
if (nsegments == RDF_MAXSEGS) {
|
||||
error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",
|
||||
RDF_MAXSEGS);
|
||||
return NO_SEG;
|
||||
}
|
||||
|
||||
segments[nsegments].segname = nasm_strdup(name);
|
||||
i = seg_alloc();
|
||||
if (i % 2 != 0)
|
||||
error(ERR_PANIC, "seg_alloc() returned odd number");
|
||||
segments[nsegments].segnumber = i >> 1;
|
||||
segments[nsegments].segtype = code;
|
||||
segments[nsegments].segreserved = reserved;
|
||||
segments[nsegments].seglength = 0;
|
||||
|
||||
seg[nsegments] = saa_init(1L);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void write_reloc_rec(struct RelocRec *r)
|
||||
{
|
||||
char buf[4],*b;
|
||||
|
||||
if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */
|
||||
r->type = 6;
|
||||
|
||||
r->refseg >>= 1; /* adjust segment nos to RDF rather than NASM */
|
||||
|
||||
saa_wbytes(header,&r->type,1);
|
||||
saa_wbytes(header,&r->reclen,1);
|
||||
saa_wbytes(header,&r->segment,1);
|
||||
b = buf; WRITELONG(b,r->offset);
|
||||
saa_wbytes(header,buf,4);
|
||||
saa_wbytes(header,&r->length,1);
|
||||
b = buf; WRITESHORT(b,r->refseg);
|
||||
saa_wbytes(header,buf,2);
|
||||
headerlength += r->reclen + 2;
|
||||
}
|
||||
|
||||
static void write_export_rec(struct ExportRec *r)
|
||||
{
|
||||
char buf[4], *b;
|
||||
|
||||
r->segment >>= 1;
|
||||
|
||||
saa_wbytes(header,&r->type,1);
|
||||
saa_wbytes(header,&r->reclen,1);
|
||||
saa_wbytes(header,&r->segment,1);
|
||||
b = buf; WRITELONG(b,r->offset);
|
||||
saa_wbytes(header,buf,4);
|
||||
saa_wbytes(header,r->label,strlen(r->label) + 1);
|
||||
headerlength += r->reclen + 2;
|
||||
}
|
||||
|
||||
static void write_import_rec(struct ImportRec *r)
|
||||
{
|
||||
char buf[4], *b;
|
||||
|
||||
r->segment >>= 1;
|
||||
|
||||
saa_wbytes(header,&r->type,1);
|
||||
saa_wbytes(header,&r->reclen,1);
|
||||
b = buf; WRITESHORT(b,r->segment);
|
||||
saa_wbytes(header,buf,2);
|
||||
saa_wbytes(header,r->label,strlen(r->label) + 1);
|
||||
headerlength += r->reclen + 2;
|
||||
}
|
||||
|
||||
static void write_bss_rec(struct BSSRec *r)
|
||||
{
|
||||
char buf[4], *b;
|
||||
|
||||
saa_wbytes(header,&r->type,1);
|
||||
saa_wbytes(header,&r->reclen,1);
|
||||
b = buf; WRITELONG(b,r->amount);
|
||||
saa_wbytes(header,buf,4);
|
||||
headerlength += r->reclen + 2;
|
||||
}
|
||||
|
||||
static void write_dll_rec(struct DLLRec *r)
|
||||
{
|
||||
saa_wbytes(header,&r->type,1);
|
||||
saa_wbytes(header,&r->reclen,1);
|
||||
saa_wbytes(header,r->libname,strlen(r->libname) + 1);
|
||||
headerlength += r->reclen + 2;
|
||||
}
|
||||
|
||||
static void rdf2_deflabel(char *name, long segment, long offset,
|
||||
int is_global, char *special)
|
||||
{
|
||||
struct ExportRec r;
|
||||
struct ImportRec ri;
|
||||
#ifdef VERBOSE_WARNINGS
|
||||
static int warned_common = 0;
|
||||
#endif
|
||||
static int farsym = 0;
|
||||
static int i;
|
||||
|
||||
if (special) {
|
||||
while(*special == ' ' || *special == '\t') special++;
|
||||
|
||||
if (!nasm_stricmp(special, "far")) {
|
||||
farsym = 1;
|
||||
}
|
||||
else if (!nasm_stricmp(special, "near")) {
|
||||
farsym = 0;
|
||||
}
|
||||
else
|
||||
error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
|
||||
}
|
||||
|
||||
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
|
||||
error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_global == 2) {
|
||||
#ifdef VERBOSE_WARNINGS
|
||||
if (!warned_common) {
|
||||
error(ERR_WARNING,"common declarations not supported: using extern");
|
||||
warned_common = 1;
|
||||
}
|
||||
#endif
|
||||
is_global = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (segments[i].segnumber == segment>>1) break;
|
||||
}
|
||||
if (i >= nsegments) { /* EXTERN declaration */
|
||||
if (farsym)
|
||||
ri.type = 7;
|
||||
else
|
||||
ri.type = 2;
|
||||
ri.segment = segment;
|
||||
strncpy(ri.label,name,32);
|
||||
ri.label[32] = 0;
|
||||
ri.reclen = 3 + strlen(ri.label);
|
||||
write_import_rec(&ri);
|
||||
} else if (is_global) {
|
||||
r.type = 3;
|
||||
r.segment = segment;
|
||||
r.offset = offset;
|
||||
strncpy(r.label,name,32);
|
||||
r.label[32] = 0;
|
||||
r.reclen = 6 + strlen(r.label);
|
||||
write_export_rec(&r);
|
||||
}
|
||||
}
|
||||
|
||||
static void membufwrite(int segment, void * data, int bytes)
|
||||
{
|
||||
int i;
|
||||
char buf[4], * b;
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (segments[i].segnumber == segment) break;
|
||||
}
|
||||
if (i == nsegments)
|
||||
error(ERR_PANIC, "can't find segment %d", segment);
|
||||
|
||||
if (bytes < 0) {
|
||||
b = buf;
|
||||
if (bytes == -2)
|
||||
WRITESHORT(b,*(short *)data);
|
||||
else
|
||||
WRITELONG(b,*(long *)data);
|
||||
data = buf;
|
||||
bytes = -bytes;
|
||||
}
|
||||
segments[i].seglength += bytes;
|
||||
saa_wbytes(seg[i],data,bytes);
|
||||
}
|
||||
|
||||
static int getsegmentlength(int segment)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (segments[i].segnumber == segment) break;
|
||||
}
|
||||
if (i == nsegments)
|
||||
error(ERR_PANIC, "can't find segment %d", segment);
|
||||
|
||||
return segments[i].seglength;
|
||||
}
|
||||
|
||||
static void rdf2_out (long segto, void *data, unsigned long type,
|
||||
long segment, long wrt)
|
||||
{
|
||||
long bytes = type & OUT_SIZMASK;
|
||||
struct RelocRec rr;
|
||||
unsigned char databuf[4],*pd;
|
||||
int seg;
|
||||
|
||||
if (segto == NO_SEG) {
|
||||
if ((type & OUT_TYPMASK) != OUT_RESERVE)
|
||||
error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
|
||||
return;
|
||||
}
|
||||
|
||||
segto >>= 1; /* convert NASM segment no to RDF number */
|
||||
|
||||
for (seg = 0; seg < nsegments; seg++) {
|
||||
if (segments[seg].segnumber == segto) break;
|
||||
}
|
||||
if (seg >= nsegments) {
|
||||
error(ERR_NONFATAL,"specified segment not supported by rdf output format");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wrt != NO_SEG) {
|
||||
wrt = NO_SEG; /* continue to do _something_ */
|
||||
error (ERR_NONFATAL, "WRT not supported by rdf output format");
|
||||
}
|
||||
|
||||
type &= OUT_TYPMASK;
|
||||
|
||||
if (segto == 2 && type != OUT_RESERVE)
|
||||
{
|
||||
error(ERR_NONFATAL, "BSS segments may not be initialised");
|
||||
|
||||
/* just reserve the space for now... */
|
||||
|
||||
if (type == OUT_REL2ADR)
|
||||
bytes = 2;
|
||||
else
|
||||
bytes = 4;
|
||||
type = OUT_RESERVE;
|
||||
}
|
||||
|
||||
if (type == OUT_RESERVE) {
|
||||
if (segto == 2) /* BSS segment space reserverd */
|
||||
bsslength += bytes;
|
||||
else
|
||||
while (bytes --)
|
||||
membufwrite(segto,databuf,1);
|
||||
}
|
||||
else if (type == OUT_RAWDATA) {
|
||||
if (segment != NO_SEG)
|
||||
error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
|
||||
|
||||
membufwrite(segto,data,bytes);
|
||||
}
|
||||
else if (type == OUT_ADDRESS) {
|
||||
|
||||
/* if segment == NO_SEG then we are writing an address of an
|
||||
object within the same segment - do not produce reloc rec. */
|
||||
|
||||
/* FIXME - is this behaviour sane? at first glance it doesn't
|
||||
appear to be. Must test this thoroughly...! */
|
||||
|
||||
if (segment != NO_SEG)
|
||||
{
|
||||
/* it's an address, so we must write a relocation record */
|
||||
|
||||
rr.type = 1; /* type signature */
|
||||
rr.reclen = 8;
|
||||
rr.segment = segto; /* segment we're currently in */
|
||||
rr.offset = getsegmentlength(segto); /* current offset */
|
||||
rr.length = bytes; /* length of reference */
|
||||
rr.refseg = segment; /* segment referred to */
|
||||
write_reloc_rec(&rr);
|
||||
}
|
||||
|
||||
pd = databuf; /* convert address to little-endian */
|
||||
if (bytes == 2)
|
||||
WRITESHORT (pd, *(long *)data);
|
||||
else
|
||||
WRITELONG (pd, *(long *)data);
|
||||
|
||||
membufwrite(segto,databuf,bytes);
|
||||
|
||||
}
|
||||
else if (type == OUT_REL2ADR)
|
||||
{
|
||||
if (segment == segto)
|
||||
error(ERR_PANIC, "intra-segment OUT_REL2ADR");
|
||||
|
||||
rr.reclen = 8;
|
||||
rr.offset = getsegmentlength(segto); /* current offset */
|
||||
rr.length = 2; /* length of reference */
|
||||
rr.refseg = segment; /* segment referred to (will be >>1'd)*/
|
||||
|
||||
if (segment != NO_SEG && segment % 2) {
|
||||
rr.type = 6;
|
||||
rr.segment = segto; /* memory base refs *aren't ever* relative! */
|
||||
write_reloc_rec(&rr);
|
||||
|
||||
/* what do we put in the code? Simply the data. This should almost
|
||||
* always be zero, unless someone's doing segment arithmetic...
|
||||
*/
|
||||
rr.offset = *(long *) data;
|
||||
}
|
||||
else
|
||||
{
|
||||
rr.type = 1; /* type signature */
|
||||
rr.segment = segto+64; /* segment we're currently in + rel flag */
|
||||
write_reloc_rec(&rr);
|
||||
|
||||
/* work out what to put in the code: offset of the end of this operand,
|
||||
* subtracted from any data specified, so that loader can just add
|
||||
* address of imported symbol onto it to get address relative to end of
|
||||
* instruction: import_address + data(offset) - end_of_instrn */
|
||||
|
||||
rr.offset = *(long *)data -(rr.offset + bytes);
|
||||
}
|
||||
|
||||
membufwrite(segto,&rr.offset,-2);
|
||||
}
|
||||
else if (type == OUT_REL4ADR)
|
||||
{
|
||||
if (segment == segto)
|
||||
error(ERR_PANIC, "intra-segment OUT_REL4ADR");
|
||||
if (segment != NO_SEG && segment % 2) {
|
||||
error(ERR_PANIC, "erm... 4 byte segment base ref?");
|
||||
}
|
||||
|
||||
rr.type = 1; /* type signature */
|
||||
rr.segment = segto+64; /* segment we're currently in + rel tag */
|
||||
rr.offset = getsegmentlength(segto); /* current offset */
|
||||
rr.length = 4; /* length of reference */
|
||||
rr.refseg = segment; /* segment referred to */
|
||||
rr.reclen = 8;
|
||||
write_reloc_rec(&rr);
|
||||
|
||||
rr.offset = *(long *)data -(rr.offset + bytes);
|
||||
|
||||
membufwrite(segto,&rr.offset,-4);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdf2_cleanup (int debuginfo) {
|
||||
long l;
|
||||
struct BSSRec bs;
|
||||
int i;
|
||||
|
||||
(void) debuginfo;
|
||||
|
||||
/* should write imported & exported symbol declarations to header here */
|
||||
|
||||
/* generate the output file... */
|
||||
fwrite(RDOFF2Id,6,1,ofile); /* file type magic number */
|
||||
|
||||
if (bsslength != 0) /* reserve BSS */
|
||||
{
|
||||
bs.type = 5;
|
||||
bs.amount = bsslength;
|
||||
bs.reclen = 4;
|
||||
write_bss_rec(&bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate overall length of the output object
|
||||
*/
|
||||
l = headerlength + 4;
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (i == 2) continue; /* skip BSS segment */
|
||||
l += 10 + segments[i].seglength;
|
||||
}
|
||||
l += 10; /* null segment */
|
||||
|
||||
fwritelong(l, ofile);
|
||||
|
||||
fwritelong(headerlength, ofile);
|
||||
saa_fpwrite(header,ofile); /* dump header */
|
||||
saa_free(header);
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
if (i == 2) continue;
|
||||
|
||||
fwriteshort(segments[i].segtype, ofile);
|
||||
fwriteshort(segments[i].segnumber, ofile);
|
||||
fwriteshort(segments[i].segreserved, ofile);
|
||||
fwritelong(segments[i].seglength, ofile);
|
||||
|
||||
saa_fpwrite(seg[i], ofile);
|
||||
saa_free(seg[i]);
|
||||
}
|
||||
|
||||
/* null segment - write 10 bytes of zero */
|
||||
fwritelong(0,ofile);
|
||||
fwritelong(0,ofile);
|
||||
fwriteshort(0,ofile);
|
||||
|
||||
fclose(ofile);
|
||||
}
|
||||
|
||||
static long rdf2_segbase (long segment) {
|
||||
return segment;
|
||||
}
|
||||
|
||||
static int rdf2_directive (char *directive, char *value, int pass) {
|
||||
struct DLLRec r;
|
||||
|
||||
if (! strcmp(directive, "library")) {
|
||||
if (pass == 1) {
|
||||
r.type = 4;
|
||||
strcpy(r.libname, value);
|
||||
write_dll_rec(&r);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rdf2_filename (char *inname, char *outname, efunc error) {
|
||||
standard_extension(inname,outname,".rdf",error);
|
||||
}
|
||||
|
||||
static char *rdf2_stdmac[] = {
|
||||
"%define __SECT__ [section .text]",
|
||||
"%imacro library 1+.nolist",
|
||||
"[library %1]",
|
||||
"%endmacro",
|
||||
"%macro __NASM_CDecl__ 1",
|
||||
"%endmacro",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int rdf2_set_info(enum geninfo type, char **val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct ofmt of_rdf2 = {
|
||||
"Relocatable Dynamic Object File Format v2.0",
|
||||
"rdf",
|
||||
NULL,
|
||||
null_debug_arr,
|
||||
&null_debug_form,
|
||||
rdf2_stdmac,
|
||||
rdf2_init,
|
||||
rdf2_set_info,
|
||||
rdf2_out,
|
||||
rdf2_deflabel,
|
||||
rdf2_section_names,
|
||||
rdf2_segbase,
|
||||
rdf2_directive,
|
||||
rdf2_filename,
|
||||
rdf2_cleanup
|
||||
};
|
||||
|
||||
#endif /* OF_RDF2 */
|
202
parser.c
202
parser.c
@ -41,26 +41,34 @@ static int is_comma_next (void);
|
||||
static int i;
|
||||
static struct tokenval tokval;
|
||||
static efunc error;
|
||||
static struct ofmt *outfmt; /* Structure of addresses of output routines */
|
||||
static loc_t *location; /* Pointer to current line's segment,offset */
|
||||
|
||||
void parser_global_info (struct ofmt *output, loc_t *locp)
|
||||
{
|
||||
outfmt = output;
|
||||
location = locp;
|
||||
}
|
||||
|
||||
insn *parse_line (int pass, char *buffer, insn *result,
|
||||
efunc errfunc, evalfunc evaluate, evalinfofunc einfo) {
|
||||
efunc errfunc, evalfunc evaluate, ldfunc ldef)
|
||||
{
|
||||
int operand;
|
||||
int critical;
|
||||
struct eval_hints hints;
|
||||
|
||||
result->forw_ref = FALSE;
|
||||
error = errfunc;
|
||||
einfo ("", 0L, 0L);
|
||||
|
||||
stdscan_reset();
|
||||
stdscan_bufptr = buffer;
|
||||
i = stdscan(NULL, &tokval);
|
||||
|
||||
result->label = NULL; /* Assume no label */
|
||||
result->eops = NULL; /* must do this, whatever happens */
|
||||
result->operands = 0; /* must initialise this */
|
||||
|
||||
if (i==0) { /* blank line - ignore */
|
||||
result->label = NULL; /* so, no label on it */
|
||||
result->opcode = -1; /* and no instruction either */
|
||||
return result;
|
||||
}
|
||||
@ -68,23 +76,32 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
(i!=TOKEN_REG || (REG_SREG & ~reg_flags[tokval.t_integer]))) {
|
||||
error (ERR_NONFATAL, "label or instruction expected"
|
||||
" at start of line");
|
||||
result->label = NULL;
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (i == TOKEN_ID) { /* there's a label here */
|
||||
result->label = tokval.t_charptr;
|
||||
einfo (result->label, 0L, 0L);
|
||||
i = stdscan(NULL, &tokval);
|
||||
if (i == ':') { /* skip over the optional colon */
|
||||
i = stdscan(NULL, &tokval);
|
||||
} else if (i == 0 && pass == 1) {
|
||||
error (ERR_WARNING|ERR_WARN_OL,
|
||||
} else if (i == 0) {
|
||||
error (ERR_WARNING|ERR_WARN_OL|ERR_PASS1,
|
||||
"label alone on a line without a colon might be in error");
|
||||
}
|
||||
} else /* no label; so, moving swiftly on */
|
||||
result->label = NULL;
|
||||
if (i != TOKEN_INSN || tokval.t_integer != I_EQU)
|
||||
{
|
||||
/*
|
||||
* FIXME: location->segment could be NO_SEG, in which case
|
||||
* it is possible we should be passing 'abs_seg'. Look into this.
|
||||
* Work out whether that is *really* what we should be doing.
|
||||
* Generally fix things. I think this is right as it is, but
|
||||
* am still not certain.
|
||||
*/
|
||||
ldef (result->label, location->segment,
|
||||
location->offset, NULL, TRUE, FALSE, outfmt, errfunc);
|
||||
}
|
||||
}
|
||||
|
||||
if (i==0) {
|
||||
result->opcode = -1; /* this line contains just a label */
|
||||
@ -95,7 +112,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
result->times = 1L;
|
||||
|
||||
while (i == TOKEN_PREFIX ||
|
||||
(i==TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer]))) {
|
||||
(i==TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer])))
|
||||
{
|
||||
/*
|
||||
* Handle special case: the TIMES prefix.
|
||||
*/
|
||||
@ -115,9 +133,11 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
result->times = 1L;
|
||||
} else {
|
||||
result->times = value->value;
|
||||
if (value->value < 0)
|
||||
if (value->value < 0) {
|
||||
error(ERR_NONFATAL, "TIMES value %d is negative",
|
||||
value->value);
|
||||
result->times = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (result->nprefix == MAXPREFIX)
|
||||
@ -169,7 +189,9 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
result->opcode == I_RESQ ||
|
||||
result->opcode == I_REST ||
|
||||
result->opcode == I_EQU)
|
||||
{
|
||||
critical = pass;
|
||||
}
|
||||
else
|
||||
critical = (pass==2 ? 2 : 0);
|
||||
|
||||
@ -178,12 +200,15 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
result->opcode == I_DD ||
|
||||
result->opcode == I_DQ ||
|
||||
result->opcode == I_DT ||
|
||||
result->opcode == I_INCBIN) {
|
||||
result->opcode == I_INCBIN)
|
||||
{
|
||||
extop *eop, **tail = &result->eops, **fixptr;
|
||||
int oper_num = 0;
|
||||
|
||||
result->eops_float = FALSE;
|
||||
|
||||
/*
|
||||
* Begin to read the DB/DW/DD/DQ/DT operands.
|
||||
* Begin to read the DB/DW/DD/DQ/DT/INCBIN operands.
|
||||
*/
|
||||
while (1) {
|
||||
i = stdscan(NULL, &tokval);
|
||||
@ -204,14 +229,14 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == TOKEN_FLOAT || i == '-') {
|
||||
if ((i == TOKEN_FLOAT && is_comma_next()) || i == '-') {
|
||||
long sign = +1L;
|
||||
|
||||
if (i == '-') {
|
||||
char *save = stdscan_bufptr;
|
||||
i = stdscan(NULL, &tokval);
|
||||
sign = -1L;
|
||||
if (i != TOKEN_FLOAT) {
|
||||
if (i != TOKEN_FLOAT || !is_comma_next()) {
|
||||
stdscan_bufptr = save;
|
||||
i = tokval.t_type = '-';
|
||||
}
|
||||
@ -219,23 +244,30 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
|
||||
if (i == TOKEN_FLOAT) {
|
||||
eop->type = EOT_DB_STRING;
|
||||
result->eops_float = TRUE;
|
||||
if (result->opcode == I_DD)
|
||||
eop->stringlen = 4;
|
||||
else if (result->opcode == I_DQ)
|
||||
eop->stringlen = 8;
|
||||
else if (result->opcode == I_DT)
|
||||
eop->stringlen = 10;
|
||||
eop->stringlen = 10;
|
||||
else {
|
||||
error(ERR_NONFATAL, "floating-point constant"
|
||||
" encountered in `D%c' instruction",
|
||||
result->opcode == I_DW ? 'W' : 'B');
|
||||
eop->type = EOT_NOTHING;
|
||||
/*
|
||||
* fix suggested by Pedro Gimeno... original line
|
||||
* was:
|
||||
* eop->type = EOT_NOTHING;
|
||||
*/
|
||||
eop->stringlen = 0;
|
||||
}
|
||||
eop = nasm_realloc(eop, sizeof(extop)+eop->stringlen);
|
||||
tail = &eop->next;
|
||||
*fixptr = eop;
|
||||
eop->stringval = (char *)eop + sizeof(extop);
|
||||
if (!float_const (tokval.t_charptr, sign,
|
||||
if (eop->stringlen < 4 ||
|
||||
!float_const (tokval.t_charptr, sign,
|
||||
(unsigned char *)eop->stringval,
|
||||
eop->stringlen, error))
|
||||
eop->type = EOT_NOTHING;
|
||||
@ -244,7 +276,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
}
|
||||
}
|
||||
|
||||
/* anything else */ {
|
||||
/* anything else */
|
||||
{
|
||||
expr *value;
|
||||
value = evaluate (stdscan, NULL, &tokval, NULL,
|
||||
critical, error, NULL);
|
||||
@ -312,7 +345,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
*/
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
}
|
||||
} else /* DB ... */
|
||||
if (oper_num == 0)
|
||||
error (ERR_WARNING|ERR_PASS1,
|
||||
"no operand for data declaration");
|
||||
else
|
||||
result->operands = oper_num;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -324,29 +362,42 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
expr *value; /* used most of the time */
|
||||
int mref; /* is this going to be a memory ref? */
|
||||
int bracket; /* is it a [] mref, or a & mref? */
|
||||
int setsize = 0;
|
||||
|
||||
result->oprs[operand].addr_size = 0;/* have to zero this whatever */
|
||||
result->oprs[operand].eaflags = 0; /* and this */
|
||||
result->oprs[operand].opflags = 0;
|
||||
|
||||
i = stdscan(NULL, &tokval);
|
||||
if (i == 0) break; /* end of operands: get out of here */
|
||||
result->oprs[operand].type = 0; /* so far, no override */
|
||||
while (i == TOKEN_SPECIAL) {/* size specifiers */
|
||||
switch ((int)tokval.t_integer) {
|
||||
case S_BYTE:
|
||||
result->oprs[operand].type |= BITS8;
|
||||
if (!setsize) /* we want to use only the first */
|
||||
result->oprs[operand].type |= BITS8;
|
||||
setsize = 1;
|
||||
break;
|
||||
case S_WORD:
|
||||
result->oprs[operand].type |= BITS16;
|
||||
if (!setsize)
|
||||
result->oprs[operand].type |= BITS16;
|
||||
setsize = 1;
|
||||
break;
|
||||
case S_DWORD:
|
||||
case S_LONG:
|
||||
result->oprs[operand].type |= BITS32;
|
||||
if (!setsize)
|
||||
result->oprs[operand].type |= BITS32;
|
||||
setsize = 1;
|
||||
break;
|
||||
case S_QWORD:
|
||||
result->oprs[operand].type |= BITS64;
|
||||
if (!setsize)
|
||||
result->oprs[operand].type |= BITS64;
|
||||
setsize = 1;
|
||||
break;
|
||||
case S_TWORD:
|
||||
result->oprs[operand].type |= BITS80;
|
||||
if (!setsize)
|
||||
result->oprs[operand].type |= BITS80;
|
||||
setsize = 1;
|
||||
break;
|
||||
case S_TO:
|
||||
result->oprs[operand].type |= TO;
|
||||
@ -360,6 +411,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
case S_SHORT:
|
||||
result->oprs[operand].type |= SHORT;
|
||||
break;
|
||||
default:
|
||||
error (ERR_NONFATAL, "invalid operand size specification");
|
||||
}
|
||||
i = stdscan(NULL, &tokval);
|
||||
}
|
||||
@ -397,8 +450,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
}
|
||||
|
||||
value = evaluate (stdscan, NULL, &tokval,
|
||||
&result->forw_ref, critical, error, &hints);
|
||||
&result->oprs[operand].opflags,
|
||||
critical, error, &hints);
|
||||
i = tokval.t_type;
|
||||
if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
|
||||
result->forw_ref = TRUE;
|
||||
}
|
||||
if (!value) { /* error in evaluator */
|
||||
result->opcode = -1; /* unrecoverable parse error: */
|
||||
return result; /* ignore this instruction */
|
||||
@ -434,8 +491,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
i = stdscan(NULL, &tokval);
|
||||
}
|
||||
value = evaluate (stdscan, NULL, &tokval,
|
||||
&result->forw_ref, critical, error, &hints);
|
||||
&result->oprs[operand].opflags,
|
||||
critical, error, &hints);
|
||||
i = tokval.t_type;
|
||||
if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
|
||||
result->forw_ref = TRUE;
|
||||
}
|
||||
/* and get the offset */
|
||||
if (!value) { /* but, error in evaluator */
|
||||
result->opcode = -1; /* unrecoverable parse error: */
|
||||
@ -480,34 +541,38 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
i = e->type, s = e->value;
|
||||
e++;
|
||||
}
|
||||
if (e->type && e->type <= EXPR_REG_END) {/* it's a 2nd register */
|
||||
if (e->value != 1) { /* it has to be indexreg */
|
||||
if (i != -1) { /* but it can't be */
|
||||
error(ERR_NONFATAL, "invalid effective address");
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
} else
|
||||
i = e->type, s = e->value;
|
||||
} else { /* it can be basereg */
|
||||
if (b != -1) /* or can it? */
|
||||
i = e->type, s = 1;
|
||||
else
|
||||
b = e->type;
|
||||
}
|
||||
if (e->type && e->type <= EXPR_REG_END) /* it's a 2nd register */
|
||||
{
|
||||
if (b != -1) /* If the first was the base, ... */
|
||||
i = e->type, s = e->value; /* second has to be indexreg */
|
||||
|
||||
else if (e->value != 1) /* If both want to be index */
|
||||
{
|
||||
error(ERR_NONFATAL, "invalid effective address");
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
b = e->type;
|
||||
e++;
|
||||
}
|
||||
if (e->type != 0) { /* is there an offset? */
|
||||
if (e->type <= EXPR_REG_END) {/* in fact, is there an error? */
|
||||
if (e->type <= EXPR_REG_END) /* in fact, is there an error? */
|
||||
{
|
||||
error (ERR_NONFATAL, "invalid effective address");
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e->type == EXPR_UNKNOWN) {
|
||||
o = 0; /* doesn't matter what */
|
||||
result->oprs[operand].wrt = NO_SEG; /* nor this */
|
||||
o = 0; /* doesn't matter what */
|
||||
result->oprs[operand].wrt = NO_SEG; /* nor this */
|
||||
result->oprs[operand].segment = NO_SEG; /* or this */
|
||||
while (e->type) e++; /* go to the end of the line */
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e->type == EXPR_SIMPLE) {
|
||||
o = e->value;
|
||||
e++;
|
||||
@ -566,30 +631,63 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
result->oprs[operand].indexreg = i;
|
||||
result->oprs[operand].scale = s;
|
||||
result->oprs[operand].offset = o;
|
||||
} else { /* it's not a memory reference */
|
||||
}
|
||||
else /* it's not a memory reference */
|
||||
{
|
||||
if (is_just_unknown(value)) { /* it's immediate but unknown */
|
||||
result->oprs[operand].type |= IMMEDIATE;
|
||||
result->oprs[operand].offset = 0; /* don't care */
|
||||
result->oprs[operand].segment = NO_SEG; /* don't care again */
|
||||
result->oprs[operand].wrt = NO_SEG;/* still don't care */
|
||||
} else if (is_reloc(value)) { /* it's immediate */
|
||||
}
|
||||
else if (is_reloc(value)) /* it's immediate */
|
||||
{
|
||||
result->oprs[operand].type |= IMMEDIATE;
|
||||
result->oprs[operand].offset = reloc_value(value);
|
||||
result->oprs[operand].segment = reloc_seg(value);
|
||||
result->oprs[operand].wrt = reloc_wrt(value);
|
||||
if (is_simple(value) && reloc_value(value)==1)
|
||||
result->oprs[operand].type |= UNITY;
|
||||
} else { /* it's a register */
|
||||
}
|
||||
else /* it's a register */
|
||||
{
|
||||
int i;
|
||||
|
||||
if (value->type>=EXPR_SIMPLE || value->value!=1) {
|
||||
error (ERR_NONFATAL, "invalid operand type");
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* check that its only 1 register, not an expression...
|
||||
*/
|
||||
for (i = 1; value[i].type; i++)
|
||||
if (value[i].value) {
|
||||
error (ERR_NONFATAL, "invalid operand type");
|
||||
result->opcode = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* clear overrides, except TO which applies to FPU regs */
|
||||
if (result->oprs[operand].type & ~TO) {
|
||||
/*
|
||||
* we want to produce a warning iff the specified size
|
||||
* is different from the register size
|
||||
*/
|
||||
i = result->oprs[operand].type & SIZE_MASK;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
result->oprs[operand].type &= TO;
|
||||
result->oprs[operand].type |= REGISTER;
|
||||
result->oprs[operand].type |= reg_flags[value->type];
|
||||
result->oprs[operand].basereg = value->type;
|
||||
|
||||
if (i && (result->oprs[operand].type & SIZE_MASK) != i)
|
||||
error (ERR_WARNING|ERR_PASS1,
|
||||
"register size specification ignored");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -612,7 +710,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
|
||||
return result;
|
||||
}
|
||||
|
||||
static int is_comma_next (void) {
|
||||
static int is_comma_next (void)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
struct tokenval tv;
|
||||
@ -623,7 +722,8 @@ static int is_comma_next (void) {
|
||||
return (i == ',' || i == ';' || !i);
|
||||
}
|
||||
|
||||
void cleanup_insn (insn *i) {
|
||||
void cleanup_insn (insn *i)
|
||||
{
|
||||
extop *e;
|
||||
|
||||
while (i->eops) {
|
||||
|
3
parser.h
3
parser.h
@ -10,8 +10,9 @@
|
||||
#ifndef NASM_PARSER_H
|
||||
#define NASM_PARSER_H
|
||||
|
||||
void parser_global_info (struct ofmt *output, loc_t *locp);
|
||||
insn *parse_line (int pass, char *buffer, insn *result,
|
||||
efunc error, evalfunc evaluate, evalinfofunc einfo);
|
||||
efunc error, evalfunc evaluate, ldfunc ldef);
|
||||
void cleanup_insn (insn *instruction);
|
||||
|
||||
#endif
|
||||
|
9
sync.c
9
sync.c
@ -25,7 +25,8 @@ static struct Sync {
|
||||
} *synx;
|
||||
static int nsynx;
|
||||
|
||||
void init_sync(void) {
|
||||
void init_sync(void)
|
||||
{
|
||||
/*
|
||||
* I'd like to allocate an array of size SYNC_MAX, then write
|
||||
* `synx--' which would allow numbering the array from one
|
||||
@ -48,7 +49,8 @@ void init_sync(void) {
|
||||
nsynx = 0;
|
||||
}
|
||||
|
||||
void add_sync(unsigned long pos, unsigned long length) {
|
||||
void add_sync(unsigned long pos, unsigned long length)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nsynx == SYNC_MAX)
|
||||
@ -68,7 +70,8 @@ void add_sync(unsigned long pos, unsigned long length) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long next_sync(unsigned long position, unsigned long *length) {
|
||||
unsigned long next_sync(unsigned long position, unsigned long *length)
|
||||
{
|
||||
while (nsynx > 0 && synx[1].pos + synx[1].length <= position) {
|
||||
int i, j;
|
||||
struct Sync t;
|
||||
|
1457
zoutieee.c
Normal file
1457
zoutieee.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user