* assembler output format fixed

This commit is contained in:
mazen 2002-10-13 21:46:07 +00:00
parent fb36caedf1
commit 3a3b8a3dc4
5 changed files with 397 additions and 438 deletions

View File

@ -1,18 +1,7 @@
{*****************************************************************************}
{ File : aasmcpu.pas }
{ Author : Mazen NEIFER }
{ Project : Free Pascal Compiler (FPC) }
{ Creation date : 2002\05\01 }
{ Last modification date : 2002\08\20 }
{ Licence : GPL }
{ Bug report : mazen.neifer.01@supaero.org }
{*****************************************************************************}
{
{******************************************************************************
$Id$
Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
Contains the assembler object for the i386
* This code was inspired by the NASM sources
The Netwide Assembler is copyright (C) 1996 Simon Tatham and
Julian Hall. All rights reserved.
@ -30,71 +19,59 @@
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 aasmcpu;
****************************************************************************}
unit aasmcpu;
{$INCLUDE fpcdefs.inc}
INTERFACE
USES
interface
uses
cclasses,globals,verbose,
cpuinfo,cpubase,
symppu,
aasmbase,aasmtai;
CONST
const
MaxPrefixes=4;
type
TOperandOrder = (op_intel,op_att);
TOperandOrder=(op_intel,op_att);
{ alignment for operator }
tai_align = class(tai_align_abstract)
reg : tregister;
tai_align=class(tai_align_abstract)
reg:tregister;
constructor create(b:byte);
constructor create_op(b: byte; _op: byte);
constructor create_op(b:byte; _op:byte);
function getfillbuf:pchar;override;
end;
taicpu = class(taicpu_abstract)
opsize : topsize;
constructor op_none(op : tasmop;_size : topsize);
constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
constructor op_const(op : tasmop;_size : topsize;_op1 : aword);
constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
opsize:topsize;
constructor op_none(op:tasmop;_size:topsize);
constructor op_reg(op:tasmop;_size:topsize;_op1:tregister);
constructor op_const(op:tasmop;_size:topsize;_op1:aword);
constructor op_ref(op:tasmop;_size:topsize;const _op1:treference);
constructor op_reg_reg(op:tasmop;_size:topsize;_op1,_op2:tregister);
constructor op_reg_ref(op:tasmop;_size:topsize;_op1:tregister;const _op2:treference);
constructor op_reg_const(op:tasmop; _size:topsize; _op1:tregister; _op2:aword);
constructor op_const_reg(op:tasmop;_size:topsize;_op1:aword;_op2:tregister);
constructor op_const_const(op:tasmop;_size:topsize;_op1,_op2:aword);
constructor op_const_ref(op:tasmop;_size:topsize;_op1:aword;const _op2:treference);
constructor op_ref_reg(op:tasmop;_size:topsize;const _op1:treference;_op2:tregister);
{ this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
constructor op_ref_ref(op : tasmop;_size : topsize;const _op1,_op2 : treference);
constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
constructor op_reg_reg_reg(op:tasmop;_size:topsize;_op1,_op2,_op3:tregister);
constructor op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:aWord;_op3:tregister);
constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
constructor op_reg_reg_ref(op:tasmop;_size:topsize;_op1,_op2:tregister; const _op3:treference);
constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
procedure changeopsize(siz:topsize);
function GetString:string;
procedure CheckNonCommutativeOpcodes;
private
FOperandOrder : TOperandOrder;
procedure init(_size : topsize); { this need to be called by all constructor }
FOperandOrder:TOperandOrder;
procedure init(_size:topsize);{this need to be called by all constructor}
{$ifndef NOAG386BIN}
public
{ the next will reset all instructions that can change in pass 2 }
@ -105,10 +82,10 @@ type
procedure SetOperandOrder(order:TOperandOrder);
private
{ next fields are filled in pass1, so pass2 is faster }
insentry : PInsEntry;
insentry:PInsEntry;
insoffset,
inssize : longint;
LastInsOffset : longint; { need to be public to be reset }
inssize:longint;
LastInsOffset:longint; { need to be public to be reset }
function InsEnd:longint;
procedure create_ot;
function Matches(p:PInsEntry):longint;
@ -120,28 +97,22 @@ type
PROCEDURE DoneAsm;
PROCEDURE InitAsm;
implementation
uses
cutils,
CpuGas;
{****************************************************************************
TAI_ALIGN
****************************************************************************}
constructor tai_align.create(b: byte);
constructor tai_align.create(b:byte);
begin
inherited create(b);
reg := R_NONE;
reg:= R_NONE;
end;
constructor tai_align.create_op(b: byte; _op: byte);
constructor tai_align.create_op(b:byte; _op:byte);
begin
inherited create_op(b,_op);
reg := R_NONE;
reg:= R_NONE;
end;
function tai_align.getfillbuf:pchar;
const
alignarray:array[0..5] of string[8]=(
@ -153,8 +124,8 @@ uses
#$90
);
var
bufptr : pchar;
j : longint;
bufptr:pchar;
j:longint;
begin
if not use_op then
begin
@ -171,19 +142,16 @@ uses
end;
getfillbuf:=pchar(@buf);
end;
{*****************************************************************************
Taicpu Constructors
*****************************************************************************}
procedure taicpu.changeopsize(siz:topsize);
begin
opsize:=siz;
end;
procedure taicpu.init(_size : topsize);
procedure taicpu.init(_size:topsize);
begin
{ default order is att }
FOperandOrder:=op_att;
@ -198,14 +166,14 @@ uses
end;
constructor taicpu.op_none(op : tasmop;_size : topsize);
constructor taicpu.op_none(op:tasmop;_size:topsize);
begin
inherited create(op);
init(_size);
end;
constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
constructor taicpu.op_reg(op:tasmop;_size:topsize;_op1:tregister);
begin
inherited create(op);
init(_size);
@ -214,7 +182,7 @@ uses
end;
constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aword);
constructor taicpu.op_const(op:tasmop;_size:topsize;_op1:aword);
begin
inherited create(op);
init(_size);
@ -223,7 +191,7 @@ uses
end;
constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
constructor taicpu.op_ref(op:tasmop;_size:topsize;const _op1:treference);
begin
inherited create(op);
init(_size);
@ -232,7 +200,7 @@ uses
end;
constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
constructor taicpu.op_reg_reg(op:tasmop;_size:topsize;_op1,_op2:tregister);
begin
inherited create(op);
init(_size);
@ -242,7 +210,7 @@ uses
end;
constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
constructor taicpu.op_reg_const(op:tasmop; _size:topsize; _op1:tregister; _op2:aword);
begin
inherited create(op);
init(_size);
@ -252,7 +220,7 @@ uses
end;
constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
constructor taicpu.op_reg_ref(op:tasmop;_size:topsize;_op1:tregister;const _op2:treference);
begin
inherited create(op);
init(_size);
@ -262,7 +230,7 @@ uses
end;
constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
constructor taicpu.op_const_reg(op:tasmop;_size:topsize;_op1:aword;_op2:tregister);
begin
inherited create(op);
init(_size);
@ -272,7 +240,7 @@ uses
end;
constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
constructor taicpu.op_const_const(op:tasmop;_size:topsize;_op1,_op2:aword);
begin
inherited create(op);
init(_size);
@ -282,7 +250,7 @@ uses
end;
constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
constructor taicpu.op_const_ref(op:tasmop;_size:topsize;_op1:aword;const _op2:treference);
begin
inherited create(op);
init(_size);
@ -302,7 +270,7 @@ constructor taicpu.op_ref_reg(op:tasmop;_size:topsize;const _op1:treference;_op2
end;
constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;const _op1,_op2 : treference);
constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
begin
inherited create(op);
init(_size);
@ -312,7 +280,7 @@ constructor taicpu.op_ref_reg(op:tasmop;_size:topsize;const _op1:treference;_op2
end;
constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
constructor taicpu.op_reg_reg_reg(op:tasmop;_size:topsize;_op1,_op2,_op3:tregister);
begin
inherited create(op);
init(_size);
@ -331,7 +299,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
LoadReg(2,_op3);
END;
constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
constructor taicpu.op_reg_reg_ref(op:tasmop;_size:topsize;_op1,_op2:tregister;const _op3:treference);
begin
inherited create(op);
init(_size);
@ -342,7 +310,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
begin
inherited create(op);
init(_size);
@ -353,7 +321,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
begin
inherited create(op);
init(_size);
@ -364,7 +332,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
begin
inherited create(op);
init(_size);
@ -374,7 +342,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
begin
inherited create(op);
init(_size);
@ -383,7 +351,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
begin
inherited create(op);
init(_size);
@ -392,7 +360,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
begin
inherited create(op);
init(_size);
@ -402,7 +370,7 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
end;
constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
begin
inherited create(op);
init(_size);
@ -413,9 +381,9 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
function taicpu.GetString:string;
var
i : longint;
s : string;
addsize : boolean;
i:longint;
s:string;
addsize:boolean;
begin
s:='['+std_op2str[opcode];
for i:=1to ops do
@ -478,17 +446,17 @@ CONSTRUCTOR taicpu.op_reg_const_reg(op:tasmop;_size:topsize;_op1:TRegister;_op2:
procedure taicpu.Swatoperands;
var
p : TOper;
p:TOper;
begin
{ Fix the operands which are in AT&T style and we need them in Intel style }
case ops of
2 : begin
2:begin
{ 0,1 -> 1,0 }
p:=oper[0];
oper[0]:=oper[1];
oper[1]:=p;
end;
3 : begin
3:begin
{ 0,1,2 -> 2,1,0 }
p:=oper[0];
oper[0]:=oper[2];
@ -556,11 +524,11 @@ end;
type
ea=packed record
sib_present : boolean;
bytes : byte;
size : byte;
modrm : byte;
sib : byte;
sib_present:boolean;
bytes:byte;
size:byte;
modrm:byte;
sib:byte;
end;
procedure taicpu.create_ot;
@ -568,7 +536,7 @@ procedure taicpu.create_ot;
this function will also fix some other fields which only needs to be once
}
var
i,l,relsize : longint;
i,l,relsize:longint;
begin
if ops=0 then
exit;
@ -577,9 +545,9 @@ begin
with oper[i] do
begin
case typ of
top_reg :
top_reg:
{ot:=reg2type[reg]};
top_ref :
top_ref:
begin
{ create ot field }
if (ot and OT_SIZE_MASK)=0 then
@ -595,14 +563,14 @@ begin
if (ref^.scalefactor=0) then
ref^.scalefactor:=1;
end;
top_const :
top_const:
begin
if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
ot:=OT_IMM8 or OT_SIGNED
else
ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
end;
top_symbol :
top_symbol:
begin
if LastInsOffset=-1 then
l:=0
@ -632,18 +600,18 @@ end;
function taicpu.Matches(p:PInsEntry):longint;
{ * IF_SM stands for Size Match: any operand whose size is not
{ * IF_SM stands for Size Match:any operand whose size is not
* explicitly specified by the template is `really' intended to be
* the same size as the first size-specified operand.
* Non-specification is tolerated in the input instruction, but
* _wrong_ specification is not.
*
* IF_SM2 invokes Size Match on only the first _two_ operands, for
* three-operand instructions such as SHLD: it implies that the
* three-operand instructions such as SHLD:it implies that the
* first two operands must match in size, but that the third is
* required to be _unspecified_.
*
* IF_SB invokes Size Byte: operands with unspecified size in the
* IF_SB invokes Size Byte:operands with unspecified size in the
* template are really bytes, and so no non-byte specification in
* the input instruction will be tolerated. IF_SW similarly invokes
* Size Word, and IF_SD invokes Size Doubleword.
@ -653,8 +621,8 @@ function taicpu.Matches(p:PInsEntry):longint;
* required to have unspecified size in the instruction too...)
}
var
i,j,asize,oprs : longint;
siz : array[0..2] of longint;
i,j,asize,oprs:longint;
siz:array[0..2] of longint;
begin
Matches:=100;
@ -782,7 +750,7 @@ end;
function taicpu.CheckIfValid:boolean;
var
m,i : longint;
m,i:longint;
begin
CheckIfValid:=false;
{ Things which may only be done once, not when a second pass is done to
@ -899,7 +867,7 @@ begin
end;
function taicpu.NeedAddrPrefix(opidx:byte):boolean;
var
i,b : tregister;
i,b:tregister;
begin
{ if (OT_MEMORY and (not oper[opidx].ot))=0 then
begin
@ -919,21 +887,21 @@ end;
function regval(r:tregister):byte;
begin
{case r of
R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0 :
R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0:
regval:=0;
R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1 :
R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1:
regval:=1;
R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2 :
R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2:
regval:=2;
R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3 :
R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3:
regval:=3;
R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4 :
R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4:
regval:=4;
R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5 :
R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5:
regval:=5;
R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6 :
R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6:
regval:=6;
R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7 :
R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7:
regval:=7;
else}
begin
@ -946,7 +914,7 @@ end;
function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
{const
regs : array[0..63] of tregister=(
regs:array[0..63] of tregister=(
R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NONE, R_NONE, R_NONE,
R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NONE, R_NONE, R_NONE,
R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NONE, R_NONE, R_NONE,
@ -957,12 +925,12 @@ function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NONE, R_NONE, R_NONE
);}
var
j : longint;
i,b : tregister;
sym : tasmsymbol;
md,s : byte;
j:longint;
i,b:tregister;
sym:tasmsymbol;
md,s:byte;
base,index,scalefactor,
o : longint;
o:longint;
begin
process_ea:=false;
{ register ? }
@ -1033,37 +1001,37 @@ begin
exit;}
{ base }
{ case b of
R_EAX : base:=0;
R_ECX : base:=1;
R_EDX : base:=2;
R_EBX : base:=3;
R_ESP : base:=4;
R_EAX:base:=0;
R_ECX:base:=1;
R_EDX:base:=2;
R_EBX:base:=3;
R_ESP:base:=4;
R_NONE,
R_EBP : base:=5;
R_ESI : base:=6;
R_EDI : base:=7;
R_EBP:base:=5;
R_ESI:base:=6;
R_EDI:base:=7;
else
exit;
end;}
{ index }
{ case i of
R_EAX : index:=0;
R_ECX : index:=1;
R_EDX : index:=2;
R_EBX : index:=3;
R_NONE : index:=4;
R_EBP : index:=5;
R_ESI : index:=6;
R_EDI : index:=7;
R_EAX:index:=0;
R_ECX:index:=1;
R_EDX:index:=2;
R_EBX:index:=3;
R_NONE:index:=4;
R_EBP:index:=5;
R_ESI:index:=6;
R_EDI:index:=7;
else
exit;
end;
case s of
0,
1 : scalefactor:=0;
2 : scalefactor:=1;
4 : scalefactor:=2;
8 : scalefactor:=3;
1:scalefactor:=0;
2:scalefactor:=1;
4:scalefactor:=2;
8:scalefactor:=3;
else
exit;
end;
@ -1102,10 +1070,10 @@ end;
function taicpu.calcsize(p:PInsEntry):longint;
var
codes : pchar;
c : byte;
len : longint;
ea_data : ea;
codes:pchar;
c:byte;
len:longint;
ea_data:ea;
begin
len:=0;
codes:=@p^.code;
@ -1113,19 +1081,19 @@ begin
c:=ord(codes^);
inc(codes);
case c of
0 :
0:
break;
1,2,3 :
1,2,3:
begin
inc(codes,c);
inc(len,c);
end;
8,9,10 :
8,9,10:
begin
inc(codes);
inc(len);
end;
4,5,6,7 :
4,5,6,7:
begin
if opsize=S_W then
inc(len,2)
@ -1136,34 +1104,34 @@ begin
12,13,14,
16,17,18,
20,21,22,
40,41,42 :
40,41,42:
inc(len);
24,25,26,
31,
48,49,50 :
48,49,50:
inc(len,2);
28,29,30, { we don't have 16 bit immediates code }
32,33,34,
52,53,54,
56,57,58 :
56,57,58:
inc(len,4);
192,193,194 :
192,193,194:
if NeedAddrPrefix(c-192) then
inc(len);
208 :
208:
inc(len);
200,
201,
202,
209,
210,
217,218,219 : ;
216 :
217,218,219:;
216:
begin
inc(codes);
inc(len);
end;
224,225,226 :
224,225,226:
begin
InternalError(777002);
end;
@ -1183,8 +1151,6 @@ begin
until false;
calcsize:=len;
end;
{$endif NOAG386BIN}
PROCEDURE DoneAsm;
BEGIN
@ -1193,3 +1159,9 @@ PROCEDURE InitAsm;
BEGIN
END;
end.
{
$Log$
Revision 1.4 2002-10-13 21:46:07 mazen
* assembler output format fixed
}

View File

@ -843,11 +843,11 @@ procedure tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
delay slot, so an inversion is possible such as
JMPL %i6+8,%g0
JMPL %i7+8,%g0
RESTORE %g0,0,%g0
If no inversion we can use just
RESTORE %g0,0,%g0
JMPL %i6+8,%g0
JMPL %i7+8,%g0
NOP}
with list do
begin
@ -1264,7 +1264,10 @@ BEGIN
END.
{
$Log$
Revision 1.15 2002-10-11 13:35:14 mazen
Revision 1.16 2002-10-13 21:46:07 mazen
* assembler output format fixed
Revision 1.15 2002/10/11 13:35:14 mazen
*** empty log message ***
Revision 1.14 2002/10/10 19:57:51 mazen

View File

@ -1,17 +1,7 @@
{*****************************************************************************}
{ File : cpugas.pas }
{ Author : Mazen NEIFER }
{ Project : Free Pascal Compiler (FPC) }
{ Creation date : 2002\05\01 }
{ Last modification date : 2002\08\22 }
{ Licence : GPL }
{ Bug report : mazen.neifer.01@supaero.org }
{*****************************************************************************}
{ $Id$
{******************************************************************************
$Id$
Copyright (c) 1998-2000 by Florian Klaempfl
This unit implements an asmoutput class for SPARC AT&T syntax
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
@ -27,173 +17,173 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************}
UNIT CpuGas;
unit CpuGas;
{This unit implements an asmoutput class for SPARC AT&T syntax}
{$MACRO ON}{$INCLUDE fpcdefs.inc}
INTERFACE
USES
interface
uses
cclasses,cpubase,
globals,
aasmbase,aasmtai,aasmcpu,assemble,aggas;
TYPE
type
TGasSPARC=class(TGnuAssembler)
PROCEDURE WriteInstruction(hp:Tai);OVERRIDE;
END;
IMPLEMENTATION
USES
strings,
dos,
globtype,
fmodule,finput,
procedure WriteInstruction(hp:Tai);override;
end;
implementation
uses
finput,
cutils,systems,
verbose;
{$DEFINE gas_reg2str:=std_reg2str}
CONST
const
line_length = 70;
VAR
var
{$ifdef GDB}
n_line : byte; { different types of source lines }
n_line:byte; { different types of source lines }
linecount,
includecount : longint;
funcname : pchar;
stabslastfileinfo : tfileposinfo;
includecount:longint;
funcname:pchar;
stabslastfileinfo:tfileposinfo;
{$endif}
lastsec : tsection; { last section type written }
lastfileinfo : tfileposinfo;
lastsec:tsection; { last section type written }
lastfileinfo:tfileposinfo;
infile,
lastinfile : tinputfile;
symendcount : longint;
function fixline(s:string):string;
{
return s with all leading and ending spaces and tabs removed
}
var
i,j,k : longint;
begin
i:=length(s);
while (i>0) and (s[i] in [#9,' ']) do
dec(i);
j:=1;
while (j<i) and (s[j] in [#9,' ']) do
inc(j);
for k:=j to i do
if s[k] in [#0..#31,#127..#255] then
s[k]:='.';
fixline:=Copy(s,j,i-j+1);
lastinfile:tinputfile;
symendcount:longint;
function fixline(s:string):string;
{return s with all leading and ending spaces and tabs removed}
var
i,j,k:longint;
begin
i:=length(s);
while (i>0) and (s[i] in [#9,' ']) do
dec(i);
j:=1;
while (j<i) and (s[j] in [#9,' ']) do
inc(j);
for k:=j to i do
if s[k] in [#0..#31,#127..#255]
then
s[k]:='.';
fixline:=Copy(s,j,i-j+1);
end;
function single2str(d : single) : string;
var
hs : string;
function single2str(d:single):string;
var
hs:string;
begin
str(d,hs);
{replace space with +}
if hs[1]=' '
then
hs[1]:='+';
single2str:='0d'+hs
end;
function double2str(d:double):string;
var
hs:string;
begin
str(d,hs);
{ replace space with + }
if hs[1]=' '
then
hs[1]:='+';
double2str:='0d'+hs
end;
function extended2str(e:extended):string;
var
hs:string;
begin
str(e,hs);
{ replace space with + }
if hs[1]=' '
then
hs[1]:='+';
extended2str:='0d'+hs
end;
function GetReferenceString(var ref:TReference):string;
var
s:string;
begin
with ref do
begin
str(d,hs);
{ replace space with + }
if hs[1]=' ' then
hs[1]:='+';
single2str:='0d'+hs
end;
function double2str(d : double) : string;
var
hs : string;
begin
str(d,hs);
{ replace space with + }
if hs[1]=' ' then
hs[1]:='+';
double2str:='0d'+hs
end;
function extended2str(e : extended) : string;
var
hs : string;
begin
str(e,hs);
{ replace space with + }
if hs[1]=' ' then
hs[1]:='+';
extended2str:='0d'+hs
end;
function getreferencestring(var ref : treference) : string;
var
s : string;
begin
with ref do
begin
inc(offset,offsetfixup);
offsetfixup:=0;
inc(offset,offsetfixup);
offsetfixup:=0;
{ have we a segment prefix ? }
{ These are probably not correctly handled under GAS }
{ should be replaced by coding the segment override }
{ directly! - DJGPP FAQ }
if segment<>R_NONE then
if segment<>R_NONE
then
s:=gas_reg2str[segment]+':'
else
else
s:='';
if assigned(symbol) then
if assigned(symbol)
then
s:=s+symbol.name;
if offset<0 then
if offset<0
then
s:=s+tostr(offset)
else
if (offset>0) then
begin
if assigned(symbol) then
else if (offset>0)
then
begin
if assigned(symbol)
then
s:=s+'+'+tostr(offset)
else
s:=s+tostr(offset);
end
else if (index=R_NONE) and (base=R_NONE) and not assigned(symbol) then
s:=s+'0';
if (index<>R_NONE) and (base=R_NONE) then
begin
s:=s+'(,'+gas_reg2str[index];
if scalefactor<>0 then
s:=s+','+tostr(scalefactor)+')'
else
s:=s+')';
s:=s+tostr(offset);
end
else
if (index=R_NONE) and (base<>R_NONE) then
s:=s+'('+gas_reg2str[base]+')'
else
if (index<>R_NONE) and (base<>R_NONE) then
begin
s:=s+'('+gas_reg2str[base]+','+gas_reg2str[index];
if scalefactor<>0 then
s:=s+','+tostr(scalefactor)+')'
else
s := s+')';
end;
end;
getreferencestring:=s;
end;
function getopstr(const o:toper) : string;
var
hs : string;
begin
case o.typ of
top_reg :
getopstr:=gas_reg2str[o.reg];
top_ref :
getopstr:=getreferencestring(o.ref^);
top_const :
getopstr:='$'+tostr(longint(o.val));
top_symbol :
else if (index=R_NONE) and (base=R_NONE) and not assigned(symbol)
then
s:=s+'0';
if (index<>R_NONE) and (base=R_NONE)
then
begin
if assigned(o.sym) then
hs:='$'+o.sym.name
s:='['+gas_reg2str[index]+s;
if scalefactor<>0
then
s:=tostr(scalefactor)+'+'+s;
s:=s+']';
end
else if (index=R_NONE) and (base<>R_NONE)
then
s:='['+gas_reg2str[base]+'+'+s+']'
else if (index<>R_NONE) and (base<>R_NONE)
then
begin
s:='['+gas_reg2str[base]+'+'+gas_reg2str[index];
if scalefactor<>0
then
s:=tostr(scalefactor)+'+'+s;
s:= s+']';
end;
end;
getreferencestring:=s;
end;
function getopstr(const Oper:TOper):string;
var
hs:string;
begin
with Oper do
case typ of
top_reg:
getopstr:=gas_reg2str[reg];
top_ref:
getopstr:=getreferencestring(ref^);
top_const:
getopstr:={'$'+}tostr(longint(val));
top_symbol:
begin
if assigned(sym) then
hs:={'$'+}sym.name
else
hs:='$';
if o.symofs>0 then
hs:=hs+'+'+tostr(o.symofs)
if symofs>0 then
hs:=hs+'+'+tostr(symofs)
else
if o.symofs<0 then
hs:=hs+tostr(o.symofs)
if symofs<0 then
hs:=hs+tostr(symofs)
else
if not(assigned(o.sym)) then
if not(assigned(sym)) then
hs:=hs+'0';
getopstr:=hs;
end;
@ -202,44 +192,40 @@ VAR
end;
end;
function getopstr_jmp(const o:toper) : string;
var
hs : string;
begin
case o.typ of
top_reg :
getopstr_jmp:='*'+gas_reg2str[o.reg];
top_ref :
getopstr_jmp:='*'+getreferencestring(o.ref^);
top_const :
getopstr_jmp:=tostr(longint(o.val));
top_symbol :
function getopstr_jmp(const Oper:TOper):string;
var
hs:string;
begin
with Oper do
case typ of
top_reg:
getopstr_jmp:=gas_reg2str[reg]+'+';
top_ref:
getopstr_jmp:=GetReferenceString(ref^);
top_const:
getopstr_jmp:=tostr(longint(val));
top_symbol:
begin
hs:=o.sym.name;
if o.symofs>0 then
hs:=hs+'+'+tostr(o.symofs)
hs:=sym.name;
if symofs>0 then
hs:=hs+'+'+tostr(symofs)
else
if o.symofs<0 then
hs:=hs+tostr(o.symofs);
if symofs<0 then
hs:=hs+tostr(symofs);
getopstr_jmp:=hs;
end;
else
internalerror(10001);
end;
end;
{****************************************************************************
TISPARCATTASMOUTPUT
****************************************************************************}
const
ait_const2str:array[ait_const_32bit..ait_const_8bit]of string[8]=(#9'.long'#9,#9'.short'#9,#9'.byte'#9);
procedure TGasSPARC.WriteInstruction(hp:Tai);
var
Op:TAsmOp;
s:STRING;
s:String;
i:Integer;
sep:STRING[3];
begin
if hp.typ<>ait_instruction
then
@ -248,64 +234,46 @@ procedure TGasSPARC.WriteInstruction(hp:Tai);
op:=taicpu(hp).opcode;
{call maybe not translated to call}
s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition];
if is_CallJmp(op)
{process operands}
s:=#9+std_op2str[op];
if taicpu(hp).ops>0
then
{ call and jmp need an extra handling }
{ this code is only called if jmp isn't a labeled instruction }
{ quick hack to overcome a problem with manglednames=255 chars }
begin
s:=#9+std_op2str[op]+#9+getopstr_jmp(taicpu(hp).oper[0]);
end
ELSE
BEGIN {process operands}
s:=#9+std_op2str[op];
IF taicpu(hp).ops<>0
THEN
BEGIN
{
if not is_calljmp(op) then
sep:=','
else
}
sep:=#9;
FOR i:=0 TO taicpu(hp).ops-1 DO
BEGIN
s:=s+sep+getopstr(taicpu(hp).oper[i]);
sep:=',';
END;
END;
END;
begin
s+=#9+getopstr(taicpu(hp).oper[0]);
for i:=1 to taicpu(hp).ops-1 do
s+=','+getopstr(taicpu(hp).oper[i]);
end;
AsmWriteLn(s);
END;
end;
{*****************************************************************************
Initialize
*****************************************************************************}
CONST
const
as_SPARC_as_info:TAsmInfo=(
id : as_gas;
idtxt : 'AS';
asmbin : 'as';
asmcmd : '-o $OBJ $ASM';
supported_target : system_any;
outputbinary: false;
allowdirect : true;
needar : true;
labelprefix_only_inside_procedure : false;
labelprefix : '.L';
comment : '# ';
secnames : ({sec_none}'', {no section}
{sec_code}'.text', {executable code}
{sec_data}'.data', {initialized R/W data}
{sec_bss}'.bss', {uninitialized R/W data}
{sec_idata2}'.comment', {comments}
{sec_idata4}'.debug', {debugging information}
{sec_idata5}'.rodata', {RO data}
{sec_idata6}'.line', {line numbers info for symbolic debug}
{sec_idata7}'.init', {runtime intialization code}
{sec_edata}'.fini', {runtime finalization code}
{sec_stab}'.stab',
{sec_stabstr} '.stabstr',
{sec_common}'.note') {note info}
id:as_gas;
idtxt:'AS';
asmbin:'as';
asmcmd:'-o $OBJ $ASM';
supported_target:system_any;
outputbinary:false;
allowdirect:true;
needar:true;
labelprefix_only_inside_procedure:false;
labelprefix:'.L';
comment:'; ';
secnames:({sec_none}'', {no section}
{sec_code}'.text', {executable code}
{sec_data}'.data', {initialized R/W data}
{sec_bss}'.bss', {uninitialized R/W data}
{sec_idata2}'.comment', {comments}
{sec_idata4}'.debug', {debugging information}
{sec_idata5}'.rodata', {RO data}
{sec_idata6}'.line', {line numbers info for symbolic debug}
{sec_idata7}'.init', {runtime intialization code}
{sec_edata}'.fini', {runtime finalization code}
{sec_stab}'.stab',
{sec_stabstr} '.stabstr',
{sec_common}'.note') {note info}
);
INITIALIZATION
RegisterAssembler(as_SPARC_as_info,TGasSPARC);

View File

@ -27,8 +27,13 @@ uses
symconst,symbase,symtype,symdef,paramgr;
type
TSparcParaManager=class(TParaManager)
{Returns a structure giving the information on the storage of the parameter
(which must be an integer parameter)
@param(nr Parameter number of routine, starting from 1)}
function GetIntParaLoc(nr:longint):TParaLocation;override;
procedure create_param_loc_info(p:TAbstractProcDef);override;
{Returns the location where the invisible parameter for structured function
results will be passed.}
function GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;override;
end;
implementation
@ -232,50 +237,55 @@ WriteLn('***********************************************');
end;
function tSparcParaManager.GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;
begin
case p.rettype.def.deftype of
orddef,enumdef:
begin
WriteLn('Allocating i0 as return register');
GetFuncRetParaLoc.loc:=LOC_REGISTER;
GetFuncRetParaLoc.register:=R_I0;
GetFuncRetParaLoc.size:=def_cgsize(p.rettype.def);
if GetFuncRetParaLoc.size in [OS_S64,OS_64]
then
GetFuncRetParaLoc.RegisterHigh:=R_I1;
end;
floatdef:
begin
GetFuncRetParaLoc.loc:=LOC_FPUREGISTER;
GetFuncRetParaLoc.register:=R_F1;
GetFuncRetParaLoc.size:=def_cgsize(p.rettype.def);
end;
setdef,
variantdef,
pointerdef,
formaldef,
classrefdef,
recorddef,
objectdef,
stringdef,
procvardef,
filedef,
arraydef,
errordef:
begin
GetFuncRetParaLoc.loc:=LOC_REGISTER;
GetFuncRetParaLoc.register:=R_I0;
GetFuncRetParaLoc.size:=OS_ADDR;
end;
else
internalerror(2002090903);
end;
with GetFuncRetParaLoc do
case p.rettype.def.deftype of
orddef,enumdef:
begin
WriteLn('Allocating i0 as return register');
loc:=LOC_REGISTER;
register:=R_I0;
size:=def_cgsize(p.rettype.def);
if size in [OS_S64,OS_64]
then
RegisterHigh:=R_I1;
end;
floatdef:
begin
loc:=LOC_FPUREGISTER;
register:=R_F1;
size:=def_cgsize(p.rettype.def);
end;
setdef,
variantdef,
pointerdef,
formaldef,
classrefdef,
recorddef,
objectdef,
stringdef,
procvardef,
filedef,
arraydef,
errordef:
begin
loc:=LOC_REFERENCE;
reference.index:=frame_pointer_reg;
reference.offset:=64;
size:=OS_ADDR;
end;
else
internalerror(2002090903);
end;
end;
begin
ParaManager:=TSparcParaManager.create;
end.
{
$Log$
Revision 1.7 2002-10-10 19:57:51 mazen
Revision 1.8 2002-10-13 21:46:07 mazen
* assembler output format fixed
Revision 1.7 2002/10/10 19:57:51 mazen
* Just to update repsitory
Revision 1.6 2002/10/10 15:10:39 mazen

View File

@ -28,10 +28,13 @@ uses
aasmtai,
cclasses,globtype,cgbase,aasmbase,rgobj;
type
{This class implements the cpu spaecific register allocator. It is used by the
code generator to allocate and free registers which might be valid across
nodes. It also contains utility routines related to registers. Some of the
methods in this class overrides generic implementations in rgobj.pas.}
trgcpu=class(trgobj)
{ to keep the same allocation order as with the old routines }
procedure UngetregisterInt(list:taasmoutput;Reg:tregister);override;
function GetExplicitRegisterInt(list:taasmoutput;Reg:tregister):tregister;override;
procedure UngetregisterInt(list:taasmoutput;Reg:tregister);override;
end;
implementation
uses
@ -59,7 +62,10 @@ initialization
end.
{
$Log$
Revision 1.3 2002-10-12 19:03:23 mazen
Revision 1.4 2002-10-13 21:46:07 mazen
* assembler output format fixed
Revision 1.3 2002/10/12 19:03:23 mazen
* Get/Unget expilit registers to be re-examined
}