fpc/compiler/ag386int.pas
pierre 9b14f1f183 * several bugfixes
ADD ADC and AND are also sign extended
    nasm output OK (program still crashes at end
    and creates wrong assembler files !!)
    procsym types sym in tdef removed !!
1998-04-08 16:58:01 +00:00

809 lines
30 KiB
ObjectPascal

{
$Id$
Copyright (c) 1996,97 by Florian Klaempfl
This unit implements an asmoutput class for Intel syntax with Intel i386+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit ag386int;
interface
uses aasm,assemble;
type
pi386intasmlist=^ti386intasmlist;
ti386intasmlist = object(tasmlist)
procedure WriteTree(p:paasmoutput);virtual;
procedure WriteAsmList;virtual;
end;
implementation
uses
dos,globals,systems,cobjects,i386,
strings,files,verbose
{$ifdef GDB}
,gdb
{$endif GDB}
;
const
line_length = 70;
extstr : array[EXT_NEAR..EXT_ABS] of String[8] =
('NEAR','FAR','PROC','BYTE','WORD','DWORD',
'CODEPTR','DATAPTR','FWORD','PWORD','QWORD','TBYTE','ABS');
function getreferencestring(const ref : treference) : string;
var
s : string;
first : boolean;
begin
if ref.isintvalue then
s:= tostr(ref.offset)
else
{$ifdef ver0_6}
begin
first:=true;
{ have we a segment prefix ? }
if ref.segment<>R_DEFAULT_SEG then
begin
if current_module^.output_format in [of_nasm,of_obj] then
s:='['+_reg2str[ref.segment]+':'
else
s:=_reg2str[ref.segment]+':[';
end
else s:='[';
if assigned(ref.symbol) then
begin
s:=s+ref.symbol^;
first:=false;
end;
if (ref.base<>R_NO) then
begin
if not(first) then
s:=s+'+'
else
first:=false;
s:=s+_reg2str[ref.base];
end;
if (ref.index<>R_NO) then
begin
if not(first) then
s:=s+'+'
else
first:=false;
s:=s+_reg2str[ref.index];
if ref.scalefactor<>0 then
s:=s+'*'+tostr(ref.scalefactor);
end;
if ref.offset<0 then
s:=s+tostr(ref.offset)
else if (ref.offset>0) then
s:=s+'+'+tostr(ref.offset);
s:=s+']';
end;
{$else}
with ref do
begin
first:=true;
if ref.segment<>R_DEFAULT_SEG then
begin
if current_module^.output_format in [of_nasm,of_obj] then
s:='['+int_reg2str[segment]+':'
else
s:=int_reg2str[segment]+':[';
end
else
s:='[';
if assigned(symbol) then
begin
s:=s+symbol^;
first:=false;
end;
if (base<>R_NO) then
begin
if not(first) then
s:=s+'+'
else
first:=false;
s:=s+int_reg2str[base];
end;
if (index<>R_NO) then
begin
if not(first) then
s:=s+'+'
else
first:=false;
s:=s+int_reg2str[index];
if scalefactor<>0 then
s:=s+'*'+tostr(scalefactor);
end;
if offset<0 then
s:=s+tostr(offset)
else if (offset>0) then
s:=s+'+'+tostr(offset);
s:=s+']';
end;
{$endif}
getreferencestring:=s;
end;
function getopstr(t : byte;o : pointer;s : topsize; _operator: tasmop;dest : boolean) : string;
var
hs : string;
begin
case t of
top_reg : { a floating point register can be only a register operand }
if current_module^.output_format in [of_nasm,of_obj] then
getopstr:=int_nasmreg2str[tregister(o)]
else
getopstr:=int_reg2str[tregister(o)];
top_const,
top_ref : begin
if t=top_const then
hs := tostr(longint(o))
else
hs:=getreferencestring(preference(o)^);
if current_module^.output_format in [of_nasm,of_obj] then
if (_operator = A_LEA) or (_operator = A_LGS)
or (_operator = A_LSS) or (_operator = A_LFS)
or (_operator = A_LES) or (_operator = A_LDS)
or (_operator = A_SHR) or (_operator = A_SHL)
or (_operator = A_SAR) or (_operator = A_SAL)
or (_operator = A_OUT) or (_operator = A_IN) then
begin
end
else
case s of
S_B : hs:='byte '+hs;
S_W : hs:='word '+hs;
S_L : hs:='dword '+hs;
S_S : hs:='dword '+hs;
S_Q : hs:='qword '+hs;
S_X : if current_module^.output_format in [of_nasm,of_obj] then
hs:='tword '+hs
else
hs:='tbyte '+hs;
S_BW : if dest then
hs:='word '+hs
else
hs:='byte '+hs;
S_BL : if dest then
hs:='dword '+hs
else
hs:='byte '+hs;
S_WL : if dest then
hs:='dword '+hs
else
hs:='word '+hs;
end
else
Begin
{ can possibly give a range check error under tp }
{ if using in... }
if ((_operator <> A_LGS) and (_operator <> A_LSS) and
(_operator <> A_LFS) and (_operator <> A_LDS) and
(_operator <> A_LES)) then
Begin
case s of
S_B : hs:='byte ptr '+hs;
S_W : hs:='word ptr '+hs;
S_L : hs:='dword ptr '+hs;
S_BW : if dest then
hs:='word ptr '+hs
else
hs:='byte ptr '+hs;
S_BL : if dest then
hs:='dword ptr '+hs
else
hs:='byte ptr '+hs;
S_WL : if dest then
hs:='dword ptr '+hs
else
hs:='word ptr '+hs;
end;
end;
end;
getopstr:=hs;
end;
top_symbol : begin
hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
if current_module^.output_format=of_masm then
hs:='offset '+hs
else
hs:='dword '+hs;
if pcsymbol(o)^.offset>0 then
hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
else if pcsymbol(o)^.offset<0 then
hs:=hs+tostr(pcsymbol(o)^.offset);
getopstr:=hs;
end;
else internalerror(10001);
end;
end;
function getopstr_jmp(t : byte;o : pointer) : string;
var
hs : string;
begin
case t of
top_reg : getopstr_jmp:=int_reg2str[tregister(o)];
top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
top_const : getopstr_jmp:=tostr(longint(o));
top_symbol : begin
hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
if pcsymbol(o)^.offset>0 then
hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
else if pcsymbol(o)^.offset<0 then
hs:=hs+tostr(pcsymbol(o)^.offset);
getopstr_jmp:=hs;
end;
else internalerror(10001);
end;
end;
{****************************************************************************
TI386INTASMLIST
****************************************************************************}
const
ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
(#9'DD'#9,'',#9'DW'#9,#9'DB'#9);
Function PadTabs(p:pchar;addch:char):string;
var
s : string;
i : longint;
begin
i:=strlen(p);
if addch<>#0 then
begin
inc(i);
s:=StrPas(p)+addch;
end
else
s:=StrPas(p);
if i<8 then
PadTabs:=s+#9#9
else
PadTabs:=s+#9;
end;
procedure ti386intasmlist.WriteTree(p:paasmoutput);
type
twowords=record
word1,word2:word;
end;
var
s,
prefix,
suffix : string;
hp : pai;
counter,
lines,
i,j,l : longint;
consttyp : tait;
found,
quoted : boolean;
begin
hp:=pai(p^.first);
while assigned(hp) do
begin
case hp^.typ of
ait_comment : ;
ait_align : begin
{ align not supported at all with nasm v095 }
{ align with specific value not supported by }
{ turbo assembler. }
{ CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
{ SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
{ HERE UNDER TASM! }
{ if current_module^.output_format<>of_nasm then
AsmWriteLn(#9'ALIGN '+tostr(pai_align(hp)^.aligntype));}
end;
ait_external : begin
if current_module^.output_format in [of_nasm,of_obj] then
AsmWriteLn('EXTERN '+StrPas(pai_external(hp)^.name))
else
AsmWriteLn(#9#9'EXTRN'#9+StrPas(pai_external(hp)^.name)+
' :'+extstr[pai_external(hp)^.exttyp]);
end;
ait_datablock : begin
if current_module^.output_format in [of_nasm,of_obj] then
begin
if pai_datablock(hp)^.is_global then
AsmWriteLn('GLOBAL '+StrPas(pai_datablock(hp)^.name));
AsmWriteLn(PadTabs(pai_datablock(hp)^.name,':')+'RESB'#9+tostr(pai_datablock(hp)^.size));
end
else
begin
if pai_datablock(hp)^.is_global then
AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_datablock(hp)^.name));
AsmWriteLn(PadTabs(pai_datablock(hp)^.name,#0)+'DB'#9+tostr(pai_datablock(hp)^.size)+' DUP(?)');
end;
end;
ait_const_32bit,
ait_const_8bit,
ait_const_16bit : begin
AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
consttyp:=hp^.typ;
l:=0;
repeat
found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
if found then
begin
hp:=Pai(hp^.next);
s:=','+tostr(pai_const(hp)^.value);
AsmWrite(s);
inc(l,length(s));
end;
until (not found) or (l>line_length);
AsmLn;
end;
ait_const_symbol : begin
if current_module^.output_format<>of_nasm then
AsmWrite(#9#9+'DD '#9'offset ')
else
AsmWrite(#9#9+'DD '#9);
AsmWriteLn(StrPas(pchar(pai_const(hp)^.value)));
end;
ait_real_32bit : AsmWriteLn(#9#9'DD'#9+double2str(pai_single(hp)^.value));
ait_real_64bit : AsmWriteLn(#9#9'DQ'#9+double2str(pai_double(hp)^.value));
ait_real_extended : begin
{ nasm v095 does not like DT with real constants }
{ therefore write as double. }
{ other possible solution: decode directly to hex}
{ value. }
if current_module^.output_format<>of_nasm then
AsmWriteLn(#9#9'DT'#9+double2str(pai_extended(hp)^.value))
else
begin
{$ifdef EXTDEBUG}
AsmLn;
AsmWriteLn('; NASM bug work around for extended real');
{$endif}
AsmWriteLn(#9#9'DD'#9+double2str(pai_extended(hp)^.value))
end;
end;
ait_comp : AsmWriteLn(#9#9'DQ'#9+comp2str(pai_extended(hp)^.value));
ait_string : begin
counter := 0;
lines := pai_string(hp)^.len div line_length;
{ separate lines in different parts }
if pai_string(hp)^.len > 0 then
Begin
for j := 0 to lines-1 do
begin
AsmWrite(#9#9'DB'#9);
quoted:=false;
for i:=counter to counter+line_length do
begin
{ it is an ascii character. }
if (ord(pai_string(hp)^.str[i])>31) and
(ord(pai_string(hp)^.str[i])<128) and
(pai_string(hp)^.str[i]<>'"') then
begin
if not(quoted) then
begin
if i>counter then
AsmWrite(',');
AsmWrite('"');
end;
AsmWrite(pai_string(hp)^.str[i]);
quoted:=true;
end { if > 31 and < 128 and ord('"') }
else
begin
if quoted then
AsmWrite('"');
if i>counter then
AsmWrite(',');
quoted:=false;
AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
end;
end; { end for i:=0 to... }
if quoted then AsmWrite('"');
AsmWrite(target_info.newline);
counter := counter+line_length;
end; { end for j:=0 ... }
{ do last line of lines }
AsmWrite(#9#9'DB'#9);
quoted:=false;
for i:=counter to pai_string(hp)^.len-1 do
begin
{ it is an ascii character. }
if (ord(pai_string(hp)^.str[i])>31) and
(ord(pai_string(hp)^.str[i])<128) and
(pai_string(hp)^.str[i]<>'"') then
begin
if not(quoted) then
begin
if i>counter then
AsmWrite(',');
AsmWrite('"');
end;
AsmWrite(pai_string(hp)^.str[i]);
quoted:=true;
end { if > 31 and < 128 and " }
else
begin
if quoted then
AsmWrite('"');
if i>counter then
AsmWrite(',');
quoted:=false;
AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
end;
end; { end for i:=0 to... }
if quoted then
AsmWrite('"');
end;
AsmLn;
end;
ait_label : begin
AsmWrite(lab2str(pai_label(hp)^.l));
if (current_module^.output_format in [of_obj,of_nasm]) or
(assigned(hp^.next) and not(pai(hp^.next)^.typ in
[ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
ait_real_32bit,ait_real_64bit,ait_real_extended,ait_string])) then
AsmWriteLn(':');
end;
ait_direct : begin
AsmWritePChar(pai_direct(hp)^.str);
AsmLn;
end;
ait_labeled_instruction :
begin
if (current_module^.output_format in [of_nasm,of_obj]) and
not (pai_labeled(hp)^._operator in [A_JMP,A_LOOP,A_LOOPZ,A_LOOPE,
A_LOOPNZ,A_LOOPNE,A_JCXZ,A_JECXZ]) then
AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+'near '+lab2str(pai_labeled(hp)^.lab))
else
AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab));
end;
ait_symbol : begin
if pai_symbol(hp)^.is_global then
begin
if current_module^.output_format in [of_nasm,of_obj] then
AsmWriteLn('GLOBAL '+StrPas(pai_symbol(hp)^.name))
else
AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_symbol(hp)^.name));
end;
AsmWritePChar(pai_symbol(hp)^.name);
if assigned(hp^.next) and not(pai(hp^.next)^.typ in
[ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
ait_real_64bit,ait_string]) then
AsmWriteLn(':')
end;
ait_instruction : begin
suffix:='';
prefix:= '';
{ added prefix instructions, must be on same line as opcode }
if (pai386(hp)^.op1t = top_none) and
((pai386(hp)^._operator = A_REP) or
(pai386(hp)^._operator = A_LOCK) or
(pai386(hp)^._operator = A_REPE) or
(pai386(hp)^._operator = A_REPNE)) then
Begin
prefix:=int_op2str[pai386(hp)^._operator]+#9;
hp:=Pai(hp^.next);
{ this is theorically impossible... }
if hp=nil then
begin
s:=#9#9+prefix;
AsmWriteLn(s);
break;
end;
{ nasm prefers prefix on a line alone }
if (current_module^.output_format in [of_nasm,of_obj]) then
begin
AsmWriteln(#9#9+prefix);
prefix:='';
end;
end
else
prefix:= '';
{ A_FNSTS need the w as suffix at least for nasm}
if (current_module^.output_format in [of_nasm,of_obj]) then
if (pai386(hp)^._operator = A_FNSTS) then
pai386(hp)^._operator:=A_FNSTSW
else if (pai386(hp)^._operator = A_FSTS) then
pai386(hp)^._operator:=A_FSTSW;
if pai386(hp)^.op1t<>top_none then
begin
if pai386(hp)^._operator in [A_CALL] then
begin
if output_format=of_nasm then
s:=getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
else
s:='near ptr '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1);
end
else
begin
s:=getopstr(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.size,pai386(hp)^._operator,false);
if pai386(hp)^.op3t<>top_none then
begin
if pai386(hp)^.op2t<>top_none then
s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),
pai386(hp)^.size,pai386(hp)^._operator,true)+','+s;
s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),
pai386(hp)^.size,pai386(hp)^._operator,false)+','+s;
end
else
if pai386(hp)^.op2t<>top_none then
s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,pai386(hp)^.size,
pai386(hp)^._operator,true)+','+s;
end;
s:=#9+s;
end
else
begin
{ check if string instruction }
{ long form, otherwise may give range check errors }
{ in turbo pascal... }
if ((pai386(hp)^._operator = A_CMPS) or
(pai386(hp)^._operator = A_INS) or
(pai386(hp)^._operator = A_OUTS) or
(pai386(hp)^._operator = A_SCAS) or
(pai386(hp)^._operator = A_STOS) or
(pai386(hp)^._operator = A_MOVS) or
(pai386(hp)^._operator = A_LODS) or
(pai386(hp)^._operator = A_XLAT)) then
Begin
case pai386(hp)^.size of
S_B: suffix:='b';
S_W: suffix:='w';
S_L: suffix:='d';
else
Message(assem_f_invalid_suffix_intel);
end;
end;
s:='';
end;
AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^._operator]+suffix+s);
end;
{$ifdef GDB}
ait_stabn,
ait_stabs,
ait_stab_function_name : ;
{$endif GDB}
else
internalerror(10000);
end;
hp:=pai(hp^.next);
end;
end;
procedure ti386intasmlist.WriteAsmList;
begin
{$ifdef EXTDEBUG}
if assigned(current_module^.mainsource) then
comment(v_info,'Start writing intel-styled assembler output for '+current_module^.mainsource^);
{$endif}
if current_module^.output_format in [of_nasm,of_obj] then
begin
WriteTree(externals);
{ INTEL ASM doesn't support stabs
WriteTree(debuglist);}
AsmWriteLn('BITS 32');
AsmWriteLn('SECTION .text');
{
AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
}
WriteTree(codesegment);
AsmLn;
AsmWriteLn('SECTION .data');
{$ifdef EXTDEBUG}
AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
{$endif EXTDEBUG}
WriteTree(datasegment);
WriteTree(consts);
AsmLn;
AsmWriteLn('SECTION .bss');
WriteTree(bsssegment);
end
else
begin
AsmWriteLn('.386p');
WriteTree(externals);
{ INTEL ASM doesn't support stabs
WriteTree(debuglist);}
AsmWriteLn('DGROUP'#9#9'GROUP'#9'_BSS,_DATA');
AsmWriteLn('_TEXT'#9#9'SEGMENT'#9'BYTE PUBLIC USE32 ''CODE''');
AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
AsmLn;
WriteTree(codesegment);
AsmWriteLn('_TEXT'#9#9'ENDS');
AsmLn;
AsmWriteLn('_DATA'#9#9'SEGMENT'#9'DWORD PUBLIC USE32 ''DATA''');
{$ifdef EXTDEBUG}
AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
{$endif EXTDEBUG}
WriteTree(datasegment);
WriteTree(consts);
AsmWriteLn('_DATA'#9#9'ENDS');
AsmLn;
AsmWriteLn('_BSS'#9#9'SEGMENT'#9'DWORD PUBLIC USE32 ''BSS''');
WriteTree(bsssegment);
AsmWriteLn('_BSS'#9#9'ENDS');
AsmLn;
AsmWriteLn(#9#9'END');
end;
{$ifdef EXTDEBUG}
if assigned(current_module^.mainsource) then
comment(v_info,'Done writing intel-styled assembler output for '+current_module^.mainsource^);
{$endif EXTDEBUG}
end;
end.
{
$Log$
Revision 1.3 1998-04-08 16:58:01 pierre
* several bugfixes
ADD ADC and AND are also sign extended
nasm output OK (program still crashes at end
and creates wrong assembler files !!)
procsym types sym in tdef removed !!
Revision 1.2 1998/04/08 11:34:17 peter
* nasm works (linux only tested)
Revision 1.1.1.1 1998/03/25 11:18:16 root
* Restored version
Revision 1.1 1998/03/10 01:26:09 peter
+ new uniform names
Revision 1.18 1998/03/09 12:58:11 peter
* FWait warning is only showed for Go32V2 and $E+
* opcode tables moved to i386.pas/m68k.pas to reduce circular uses (and
for m68k the same tables are removed)
+ $E for i386
Revision 1.17 1998/03/06 00:52:23 peter
* replaced all old messages from errore.msg, only ExtDebug and some
Comment() calls are left
* fixed options.pas
Revision 1.16 1998/03/02 01:48:41 peter
* renamed target_DOS to target_GO32V1
+ new verbose system, merged old errors and verbose units into one new
verbose.pas, so errors.pas is obsolete
Revision 1.15 1998/02/23 02:57:41 carl
* small bugfix when compiling $extdebug
Revision 1.14 1998/02/15 21:16:20 peter
* all assembler outputs supported by assemblerobject
* cleanup with assembleroutputs, better .ascii generation
* help_constructor/destructor are now added to the externals
- generation of asmresponse is not outputformat depended
Revision 1.13 1998/02/13 10:35:07 daniel
* Made Motorola version compilable.
* Fixed optimizer
Revision 1.12 1998/02/12 17:19:07 florian
* fixed to get remake3 work, but needs additional fixes (output, I don't like
also that aktswitches isn't a pointer)
Revision 1.11 1998/02/12 11:50:11 daniel
Yes! Finally! After three retries, my patch!
Changes:
Complete rewrite of psub.pas.
Added support for DLL's.
Compiler requires less memory.
Platform units for each platform.
Revision 1.10 1997/12/13 18:59:48 florian
+ I/O streams are now also declared as external, if neccessary
* -Aobj generates now a correct obj file via nasm
Revision 1.9 1997/12/12 13:28:26 florian
+ version 0.99.0
* all WASM options changed into MASM
+ -O2 for Pentium II optimizations
Revision 1.8 1997/12/09 13:45:10 carl
* bugfix of DT under nasm (not allowed if non integral - nasm v095)
+ added pai_align --> useless here see file for more info
* bugfix of problems with in,out instructions under nasm
* bugfix of call under nasm (not fully tested though -- not sure)
* some range check errors removed (probably a few left though)
* bugfix of checking for extended type when emitting ':'
Revision 1.7 1997/12/04 15:20:47 carl
* esthetic bugfix with extdebug on.
Revision 1.6 1997/12/03 13:46:40 carl
* bugfix of my bug with near, now near in nasm mode for all non-rel8
instructions. (jcxz,jecxz still does not work thoug - assumed short now).
Revision 1.5 1997/12/02 15:52:26 carl
* bugfix of string (again...) - would be sometimes invalid.
* bugfix of segment overrides under nasm.
- removed near in labeled instructions (would cause errors).
Revision 1.4 1997/12/01 17:42:51 pierre
+ added some more functionnality to the assembler parser
Revision 1.3 1997/11/28 18:14:36 pierre
working version with several bug fixes
Revision 1.2 1997/11/28 14:54:50 carl
+ added popfd instruction.
Revision 1.1.1.1 1997/11/27 08:32:57 michael
FPC Compiler CVS start
Pre-CVS log:
CEC Carl-Eric Codere
FK Florian Klaempfl
PM Pierre Muller
+ feature added
- removed
* bug fixed or changed
History:
9th october 1997:
* bugfix of string write, closing quotes would never be written. (CEC)
23 october 1997:
* fixed problem with writing strings of length = 0 (CEC).
+ added line separation of long string chains. (CEC).
31st october 1997:
+ completed the table of opcodes. (CEC)
3rd november 1997:
+ MMX instructions added (FK)
9th november 1997:
* movsb represented the AT&T movsx - fixed, absolute values
in getreferencestring would be preceded by $ - fixed (CEC).
What's to do:
o Fix problems regarding the segment names under NASM
o generate extern entries for typed constants and variables
o write lines numbers and file names to output file
o comments
}