* another bunch of x86-64 fixes mainly calling convention and

assembler reader related
This commit is contained in:
florian 2004-01-14 23:39:05 +00:00
parent c3b9e56e90
commit 85bed883ce
16 changed files with 1391 additions and 1640 deletions

View File

@ -209,6 +209,9 @@ uses
{$ifdef powerpc}
,rappcgas
{$endif powerpc}
{$ifdef x86_64}
,rax64att
{$endif x86_64}
{$ifdef arm}
,raarmgas
{$endif arm}
@ -423,7 +426,11 @@ end;
end.
{
$Log$
Revision 1.43 2003-12-04 10:46:19 mazen
Revision 1.44 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.43 2003/12/04 10:46:19 mazen
+ added support for spac assembler reader
Revision 1.42 2003/11/17 23:23:47 florian

View File

@ -1779,7 +1779,7 @@ implementation
{$IFDEF testvarsets}
initsetalloc:=0;
{$ENDIF}
initasmmode:=asmmode_x8664_gas;
initasmmode:=asmmode_x86_64_gas;
{$endif x86_64}
initinterfacetype:=it_interfacecom;
initdefproccall:=pocall_default;
@ -1796,7 +1796,11 @@ implementation
end.
{
$Log$
Revision 1.120 2004-01-12 16:36:53 peter
Revision 1.121 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.120 2004/01/12 16:36:53 peter
* removed asmmode_direct
Revision 1.119 2004/01/02 16:50:24 jonas

View File

@ -40,7 +40,8 @@ unit cgcpu;
type
tcg386 = class(tcgx86)
class function reg_cgsize(const reg: tregister): tcgsize; override;
procedure init_register_allocators;override;
class function reg_cgsize(const reg: tregister): tcgsize; override;
end;
tcg64f386 = class(tcg64f32)
@ -57,7 +58,20 @@ unit cgcpu;
uses
globtype,globals,verbose,systems,cutils,
symdef,symsym,defutil,paramgr,
tgobj;
rgcpu,rgx86,tgobj;
procedure Tcg386.init_register_allocators;
begin
inherited init_register_allocators;
if cs_create_pic in aktmoduleswitches then
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
else
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
rgfpu:=Trgx86fpu.create;
end;
class function tcg386.reg_cgsize(const reg: tregister): tcgsize;
@ -232,7 +246,11 @@ begin
end.
{
$Log$
Revision 1.43 2004-01-12 16:39:40 peter
Revision 1.44 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.43 2004/01/12 16:39:40 peter
* sparc updates, mostly float related
Revision 1.42 2003/12/24 00:10:02 florian

View File

@ -153,7 +153,7 @@
This value can be deduced from the CALLED_USED_REGISTERS array in the
GCC source.
}
std_saved_registers = [RS_ESI,RS_EDI,RS_EBX];
saved_standard_registers : array[0..2] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI);
{# Required parameter alignment when calling a routine declared as
stdcall and cdecl. The alignment value should be the one defined
by GCC or the target ABI.
@ -165,7 +165,11 @@
{
$Log$
Revision 1.10 2003-10-17 14:38:32 peter
Revision 1.11 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.10 2003/10/17 14:38:32 peter
* 64k registers supported
* fixed some memory leaks

View File

@ -24,774 +24,20 @@ Unit ra386att;
{$i fpcdefs.inc}
Interface
uses
cpubase,
raatt,rax86;
type
ti386attreader = class(tattreader)
ActOpsize : topsize;
function is_asmopcode(const s: string):boolean;override;
procedure handleopcode;override;
procedure BuildReference(oper : t386operand);
procedure BuildOperand(oper : t386operand);
procedure BuildOpCode(instr : t386instruction);
procedure handlepercent;override;
end;
Implementation
interface
uses
{ helpers }
cutils,
{ global }
globtype,globals,verbose,
systems,
{ aasm }
cpuinfo,aasmbase,aasmtai,aasmcpu,
{ symtable }
symconst,symbase,symtype,symsym,symtable,
{ parser }
scanner,
procinfo,
itcpugas,
rabase,rautils,
cgbase,cgobj
;
rax86att;
procedure ti386attreader.handlepercent;
var
len : longint;
begin
len:=1;
actasmpattern[len]:='%';
c:=current_scanner.asmgetchar;
{ to be a register there must be a letter and not a number }
if c in ['0'..'9'] then
begin
actasmtoken:=AS_MOD;
end
else
begin
while c in ['a'..'z','A'..'Z','0'..'9'] do
Begin
inc(len);
actasmpattern[len]:=c;
c:=current_scanner.asmgetchar;
end;
actasmpattern[0]:=chr(len);
uppervar(actasmpattern);
if (actasmpattern = '%ST') and (c='(') then
Begin
actasmpattern:=actasmpattern+c;
c:=current_scanner.asmgetchar;
if c in ['0'..'9'] then
actasmpattern:=actasmpattern + c
else
Message(asmr_e_invalid_fpu_register);
c:=current_scanner.asmgetchar;
if c <> ')' then
Message(asmr_e_invalid_fpu_register)
else
Begin
actasmpattern:=actasmpattern + c;
c:=current_scanner.asmgetchar; { let us point to next character. }
end;
end;
if is_register(actasmpattern) then
exit;
Message(asmr_e_invalid_register);
actasmtoken:=raatt.AS_NONE;
end;
type
ti386attreader = class(tx86attreader)
end;
Procedure ti386attreader.BuildReference(oper : t386operand);
implementation
procedure Consume_RParen;
begin
if actasmtoken <> AS_RPAREN then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
end
else
begin
Consume(AS_RPAREN);
if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
end;
end;
end;
procedure Consume_Scale;
var
l : longint;
begin
{ we have to process the scaling }
l:=BuildConstExpression(false,true);
if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
oper.opr.ref.scalefactor:=l
else
Begin
Message(asmr_e_wrong_scale_factor);
oper.opr.ref.scalefactor:=0;
end;
end;
begin
oper.InitRef;
Consume(AS_LPAREN);
Case actasmtoken of
AS_INTNUM,
AS_MINUS,
AS_PLUS: { absolute offset, such as fs:(0x046c) }
Begin
{ offset(offset) is invalid }
If oper.opr.Ref.Offset <> 0 Then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
End
Else
Begin
oper.opr.Ref.Offset:=BuildConstExpression(false,true);
Consume_RParen;
end;
exit;
End;
AS_REGISTER: { (reg ... }
Begin
{ Check if there is already a base (mostly ebp,esp) than this is
not allowed, because it will give crashing code }
if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
message(asmr_e_cannot_index_relative_var);
oper.opr.ref.base:=actasmregister;
Consume(AS_REGISTER);
{ can either be a register or a right parenthesis }
{ (reg) }
if actasmtoken=AS_RPAREN then
Begin
Consume_RParen;
exit;
end;
{ (reg,reg .. }
Consume(AS_COMMA);
if actasmtoken=AS_REGISTER then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
{ check for scaling ... }
case actasmtoken of
AS_RPAREN:
Begin
Consume_RParen;
exit;
end;
AS_COMMA:
Begin
Consume(AS_COMMA);
Consume_Scale;
Consume_RParen;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; { end case }
end
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; {end case }
AS_COMMA: { (, ... can either be scaling, or index }
Begin
Consume(AS_COMMA);
{ Index }
if (actasmtoken=AS_REGISTER) then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
{ check for scaling ... }
case actasmtoken of
AS_RPAREN:
Begin
Consume_RParen;
exit;
end;
AS_COMMA:
Begin
Consume(AS_COMMA);
Consume_Scale;
Consume_RParen;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; {end case }
end
{ Scaling }
else
Begin
Consume_Scale;
Consume_RParen;
exit;
end;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end;
end;
Procedure ti386attreader.BuildOperand(oper : t386operand);
var
tempstr,
expr : string;
typesize,
l,k : longint;
procedure AddLabelOperand(hl:tasmlabel);
begin
if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
is_calljmp(actopcode) then
begin
oper.opr.typ:=OPR_SYMBOL;
oper.opr.symbol:=hl;
end
else
begin
oper.InitRef;
oper.opr.ref.symbol:=hl;
end;
end;
procedure MaybeRecordOffset;
var
hasdot : boolean;
l,
toffset,
tsize : longint;
begin
if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
exit;
l:=0;
hasdot:=(actasmtoken=AS_DOT);
if hasdot then
begin
if expr<>'' then
begin
BuildRecordOffsetSize(expr,toffset,tsize);
inc(l,toffset);
oper.SetSize(tsize,true);
end;
end;
if actasmtoken in [AS_PLUS,AS_MINUS] then
inc(l,BuildConstExpression(true,false));
case oper.opr.typ of
OPR_LOCAL :
begin
{ don't allow direct access to fields of parameters, because that
will generate buggy code. Allow it only for explicit typecasting }
if hasdot and
(not oper.hastype) and
(tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
(current_procinfo.procdef.proccalloption<>pocall_register) then
Message(asmr_e_cannot_access_field_directly_for_parameters);
inc(oper.opr.localsymofs,l)
end;
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309221);
end;
end;
function MaybeBuildReference:boolean;
{ Try to create a reference, if not a reference is found then false
is returned }
begin
MaybeBuildReference:=true;
case actasmtoken of
AS_INTNUM,
AS_MINUS,
AS_PLUS:
Begin
oper.opr.ref.offset:=BuildConstExpression(True,False);
if actasmtoken<>AS_LPAREN then
Message(asmr_e_invalid_reference_syntax)
else
BuildReference(oper);
end;
AS_LPAREN:
BuildReference(oper);
AS_ID: { only a variable is allowed ... }
Begin
tempstr:=actasmpattern;
Consume(AS_ID);
{ typecasting? }
if (actasmtoken=AS_LPAREN) and
SearchType(tempstr,typesize) then
begin
oper.hastype:=true;
Consume(AS_LPAREN);
BuildOperand(oper);
Consume(AS_RPAREN);
if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
oper.SetSize(typesize,true);
end
else
if not oper.SetupVar(tempstr,false) then
Message1(sym_e_unknown_id,tempstr);
{ record.field ? }
if actasmtoken=AS_DOT then
begin
BuildRecordOffsetSize(tempstr,l,k);
inc(oper.opr.ref.offset,l);
end;
case actasmtoken of
AS_END,
AS_SEPARATOR,
AS_COMMA: ;
AS_LPAREN:
BuildReference(oper);
else
Begin
Message(asmr_e_invalid_reference_syntax);
Consume(actasmtoken);
end;
end; {end case }
end;
else
MaybeBuildReference:=false;
end; { end case }
end;
const
regsize_2_size: array[S_B..S_L] of longint = (1,2,4);
var
tempreg : tregister;
hl : tasmlabel;
Begin
expr:='';
case actasmtoken of
AS_LPAREN: { Memory reference or constant expression }
Begin
oper.InitRef;
BuildReference(oper);
end;
AS_DOLLAR: { Constant expression }
Begin
Consume(AS_DOLLAR);
BuildConstantOperand(oper);
end;
AS_INTNUM,
AS_MINUS,
AS_PLUS:
Begin
{ Constant memory offset }
{ This must absolutely be followed by ( }
oper.InitRef;
oper.opr.ref.offset:=BuildConstExpression(True,False);
if actasmtoken<>AS_LPAREN then
Message(asmr_e_invalid_reference_syntax)
else
BuildReference(oper);
end;
AS_STAR: { Call from memory address }
Begin
Consume(AS_STAR);
if actasmtoken=AS_REGISTER then
begin
oper.opr.typ:=OPR_REGISTER;
oper.opr.reg:=actasmregister;
oper.SetSize(regsize_2_size[reg2opsize(actasmregister)],true);
Consume(AS_REGISTER);
end
else
begin
oper.InitRef;
if not MaybeBuildReference then
Message(asmr_e_syn_operand);
end;
{ this is only allowed for call's and jmp's }
if not is_calljmp(actopcode) then
Message(asmr_e_syn_operand);
end;
AS_ID: { A constant expression, or a Variable ref. }
Begin
{ Local Label ? }
if is_locallabel(actasmpattern) then
begin
CreateLocalLabel(actasmpattern,hl,false);
Consume(AS_ID);
AddLabelOperand(hl);
end
else
{ Check for label }
if SearchLabel(actasmpattern,hl,false) then
begin
Consume(AS_ID);
AddLabelOperand(hl);
end
else
{ probably a variable or normal expression }
{ or a procedure (such as in CALL ID) }
Begin
{ is it a constant ? }
if SearchIConstant(actasmpattern,l) then
Begin
if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
Message(asmr_e_invalid_operand_type);
BuildConstantOperand(oper);
end
else
begin
expr:=actasmpattern;
Consume(AS_ID);
{ typecasting? }
if (actasmtoken=AS_LPAREN) and
SearchType(expr,typesize) then
begin
oper.hastype:=true;
Consume(AS_LPAREN);
BuildOperand(oper);
Consume(AS_RPAREN);
if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
oper.SetSize(typesize,true);
end
else
begin
if oper.SetupVar(expr,false) then
begin
end
else
Begin
{ look for special symbols ... }
if expr= '__HIGH' then
begin
consume(AS_LPAREN);
if not oper.setupvar('high'+actasmpattern,false) then
Message1(sym_e_unknown_id,'high'+actasmpattern);
consume(AS_ID);
consume(AS_RPAREN);
end
else
if expr = '__RESULT' then
oper.SetUpResult
else
if expr = '__SELF' then
oper.SetupSelf
else
if expr = '__OLDEBP' then
oper.SetupOldEBP
else
{ check for direct symbolic names }
{ only if compiling the system unit }
if (cs_compilesystem in aktmoduleswitches) then
begin
if not oper.SetupDirectVar(expr) then
Begin
{ not found, finally ... add it anyways ... }
Message1(asmr_w_id_supposed_external,expr);
oper.InitRef;
oper.opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
end;
end
else
Message1(sym_e_unknown_id,expr);
end;
end;
end;
if actasmtoken=AS_DOT then
MaybeRecordOffset;
{ add a constant expression? }
if (actasmtoken=AS_PLUS) then
begin
l:=BuildConstExpression(true,false);
case oper.opr.typ of
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_LOCAL :
inc(oper.opr.localsymofs,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309202);
end;
end
end;
{ Do we have a indexing reference, then parse it also }
if actasmtoken=AS_LPAREN then
BuildReference(oper);
end;
AS_REGISTER: { Register, a variable reference or a constant reference }
Begin
{ save the type of register used. }
tempreg:=actasmregister;
Consume(AS_REGISTER);
if actasmtoken = AS_COLON then
Begin
Consume(AS_COLON);
oper.InitRef;
oper.opr.ref.segment:=tempreg;
{ This must absolutely be followed by a reference }
if not MaybeBuildReference then
Begin
Message(asmr_e_invalid_seg_override);
Consume(actasmtoken);
end;
end
{ Simple register }
else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
Begin
if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
Message(asmr_e_invalid_operand_type);
oper.opr.typ:=OPR_REGISTER;
oper.opr.reg:=tempreg;
oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
end
else
Message(asmr_e_syn_operand);
end;
AS_END,
AS_SEPARATOR,
AS_COMMA: ;
else
Begin
Message(asmr_e_syn_operand);
Consume(actasmtoken);
end;
end; { end case }
end;
procedure ti386attreader.BuildOpCode(instr : t386instruction);
var
operandnum : longint;
PrefixOp,OverrideOp: tasmop;
Begin
PrefixOp:=A_None;
OverrideOp:=A_None;
{ prefix seg opcode / prefix opcode }
repeat
if is_prefix(actopcode) then
begin
PrefixOp:=ActOpcode;
with instr do
begin
opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
ConcatInstruction(curlist);
end;
Consume(AS_OPCODE);
end
else
if is_override(actopcode) then
begin
OverrideOp:=ActOpcode;
with instr do
begin
opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
ConcatInstruction(curlist);
end;
Consume(AS_OPCODE);
end
else
break;
{ allow for newline as in gas styled syntax }
while actasmtoken=AS_SEPARATOR do
Consume(AS_SEPARATOR);
until (actasmtoken<>AS_OPCODE);
{ opcode }
if (actasmtoken<>AS_OPCODE) then
Begin
Message(asmr_e_invalid_or_missing_opcode);
RecoverConsume(true);
exit;
end;
{ Fill the instr object with the current state }
with instr do
begin
Opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
end;
{ Valid combination of prefix/override and instruction ? }
if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
{ We are reading operands, so opcode will be an AS_ID }
operandnum:=1;
Consume(AS_OPCODE);
{ Zero operand opcode ? }
if actasmtoken in [AS_SEPARATOR,AS_END] then
begin
operandnum:=0;
exit;
end;
{ Read the operands }
repeat
case actasmtoken of
AS_COMMA: { Operand delimiter }
Begin
if operandnum > Max_Operands then
Message(asmr_e_too_many_operands)
else
Inc(operandnum);
Consume(AS_COMMA);
end;
AS_SEPARATOR,
AS_END : { End of asm operands for this opcode }
begin
break;
end;
else
BuildOperand(instr.Operands[operandnum] as t386operand);
end; { end case }
until false;
instr.Ops:=operandnum;
end;
function ti386attreader.is_asmopcode(const s: string):boolean;
const
{ We need first to check the long prefixes, else we get probs
with things like movsbl }
att_sizesuffixstr : array[0..9] of string[2] = (
'','BW','BL','WL','B','W','L','S','Q','T'
);
att_sizesuffix : array[0..9] of topsize = (
S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
);
att_sizefpusuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
);
att_sizefpuintsuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
);
var
str2opentry: tstr2opentry;
cond : string[4];
cnd : tasmcond;
len,
j,
sufidx : longint;
Begin
is_asmopcode:=FALSE;
actopcode:=A_None;
actcondition:=C_None;
actopsize:=S_NO;
{ search for all possible suffixes }
for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
begin
len:=length(s)-length(att_sizesuffixstr[sufidx]);
if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
begin
{ here we search the entire table... }
str2opentry:=nil;
if {(length(s)>0) and} (len>0) then
str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
if assigned(str2opentry) then
begin
actopcode:=str2opentry.op;
if gas_needsuffix[actopcode]=attsufFPU then
actopsize:=att_sizefpusuffix[sufidx]
else if gas_needsuffix[actopcode]=attsufFPUint then
actopsize:=att_sizefpuintsuffix[sufidx]
else
actopsize:=att_sizesuffix[sufidx];
actasmtoken:=AS_OPCODE;
is_asmopcode:=TRUE;
exit;
end;
{ not found, check condition opcodes }
j:=0;
while (j<CondAsmOps) do
begin
if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
begin
cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
if cond<>'' then
begin
for cnd:=low(TasmCond) to high(TasmCond) do
if Cond=Upper(cond2str[cnd]) then
begin
actopcode:=CondASmOp[j];
if gas_needsuffix[actopcode]=attsufFPU then
actopsize:=att_sizefpusuffix[sufidx]
else if gas_needsuffix[actopcode]=attsufFPUint then
actopsize:=att_sizefpuintsuffix[sufidx]
else
actopsize:=att_sizesuffix[sufidx];
actcondition:=cnd;
actasmtoken:=AS_OPCODE;
is_asmopcode:=TRUE;
exit;
end;
end;
end;
inc(j);
end;
end;
end;
end;
procedure ti386attreader.handleopcode;
var
instr : T386Instruction;
begin
instr:=T386Instruction.Create(T386Operand);
instr.OpOrder:=op_att;
BuildOpcode(instr);
instr.AddReferenceSizes;
instr.SetInstructionOpsize;
instr.CheckOperandSizes;
instr.ConcatInstruction(curlist);
instr.Free;
end;
{*****************************************************************************
Initialize
*****************************************************************************}
uses
rabase,systems;
const
asmmode_i386_att_info : tasmmodeinfo =
@ -806,191 +52,7 @@ initialization
end.
{
$Log$
Revision 1.58 2003-11-12 16:05:39 florian
* assembler readers OOPed
+ typed currency constants
+ typed 128 bit float constants if the CPU supports it
Revision 1.57 2003/11/10 19:08:32 peter
* line numbering is now only done when #10, #10#13 is really parsed
instead of when it is the next character
Revision 1.56 2003/10/29 16:47:18 peter
* fix field offset in reference
Revision 1.55 2003/10/26 13:37:22 florian
* fixed web bug 2128
Revision 1.54 2003/10/24 17:39:03 peter
* more intel parser updates
Revision 1.53 2003/10/23 17:19:44 peter
* typecasting fixes
* reference building more delphi compatible
Revision 1.52 2003/10/20 19:29:35 peter
* fix check for register subscription of reference parameter
Revision 1.51 2003/10/16 21:29:24 peter
+ __HIGH() to retrieve high value
Revision 1.50 2003/10/07 18:21:18 peter
* fix crash
* allow parameter subscription for register parameters
Revision 1.49 2003/10/01 20:34:49 peter
* procinfo unit contains tprocinfo
* cginfo renamed to cgbase
* moved cgmessage to verbose
* fixed ppc and sparc compiles
Revision 1.48 2003/09/23 20:37:53 peter
* fix global var+offset
Revision 1.47 2003/09/23 17:56:06 peter
* locals and paras are allocated in the code generation
* tvarsym.localloc contains the location of para/local when
generating code for the current procedure
Revision 1.46 2003/09/03 15:55:01 peter
* NEWRA branch merged
Revision 1.45.2.2 2003/08/31 15:46:26 peter
* more updates for tregister
Revision 1.45.2.1 2003/08/28 18:35:08 peter
* tregister changed to cardinal
Revision 1.45 2003/05/30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.44 2003/05/22 21:32:29 peter
* removed some unit dependencies
Revision 1.43 2003/04/30 15:45:35 florian
* merged more x86-64/i386 code
Revision 1.42 2003/04/25 12:04:31 florian
* merged agx64att and ag386att to x86/agx86att
Revision 1.41 2003/04/21 20:05:10 peter
* removed some ie checks
Revision 1.40 2003/03/18 18:15:53 peter
* changed reg2opsize to function
Revision 1.39 2003/02/20 15:52:58 pierre
* fix a range check error
Revision 1.38 2003/02/19 22:00:16 daniel
* Code generator converted to new register notation
- Horribily outdated todo.txt removed
Revision 1.37 2003/02/03 22:47:14 daniel
- Removed reg_2_opsize array
Revision 1.36 2003/01/08 18:43:57 daniel
* Tregister changed into a record
Revision 1.35 2002/12/14 15:02:03 carl
* maxoperands -> max_operands (for portability in rautils.pas)
* fix some range-check errors with loadconst
+ add ncgadd unit to m68k
* some bugfix of a_param_reg with LOC_CREFERENCE
Revision 1.34 2002/12/01 22:08:34 carl
* some small cleanup (remove some specific operators which are not supported)
Revision 1.33 2002/11/30 23:16:39 carl
- removed unused message
Revision 1.32 2002/11/15 01:58:58 peter
* merged changes from 1.0.7 up to 04-11
- -V option for generating bug report tracing
- more tracing for option parsing
- errors for cdecl and high()
- win32 import stabs
- win32 records<=8 are returned in eax:edx (turned off by default)
- heaptrc update
- more info for temp management in .s file with EXTDEBUG
Revision 1.31 2002/09/03 16:26:28 daniel
* Make Tprocdef.defs protected
Revision 1.30 2002/08/13 18:01:52 carl
* rename swatoperands to swapoperands
+ m68k first compilable version (still needs a lot of testing):
assembler generator, system information , inline
assembler reader.
Revision 1.29 2002/08/12 15:08:42 carl
+ stab register indexes for powerpc (moved from gdb to cpubase)
+ tprocessor enumeration moved to cpuinfo
+ linker in target_info is now a class
* many many updates for m68k (will soon start to compile)
- removed some ifdef or correct them for correct cpu
Revision 1.28 2002/08/11 14:32:31 peter
* renamed current_library to objectlibrary
Revision 1.27 2002/08/11 13:24:17 peter
* saving of asmsymbols in ppu supported
* asmsymbollist global is removed and moved into a new class
tasmlibrarydata that will hold the info of a .a file which
corresponds with a single module. Added librarydata to tmodule
to keep the library info stored for the module. In the future the
objectfiles will also be stored to the tasmlibrarydata class
* all getlabel/newasmsymbol and friends are moved to the new class
Revision 1.26 2002/07/26 21:15:44 florian
* rewrote the system handling
Revision 1.25 2002/07/01 18:46:34 peter
* internal linker
* reorganized aasm layer
Revision 1.24 2002/05/18 13:34:25 peter
* readded missing revisions
Revision 1.23 2002/05/16 19:46:52 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.21 2002/04/15 19:12:09 carl
+ target_info.size_of_pointer -> pointer_size
+ some cleanup of unused types/variables
* move several constants from cpubase to their specific units
(where they are used)
+ att_Reg2str -> gas_reg2str
+ int_reg2str -> std_reg2str
Revision 1.20 2002/04/14 17:01:52 carl
+ att_reg2str -> gas_reg2str
Revision 1.19 2002/04/04 19:06:13 peter
* removed unused units
* use tlocation.size in cg.a_*loc*() routines
Revision 1.18 2002/04/02 17:11:39 peter
* tlocation,treference update
* LOC_CONSTANT added for better constant handling
* secondadd splitted in multiple routines
* location_force_reg added for loading a location to a register
of a specified size
* secondassignment parses now first the right and then the left node
(this is compatible with Kylix). This saves a lot of push/pop especially
with string operations
* adapted some routines to use the new cg methods
Revision 1.17 2002/03/28 20:48:25 carl
- remove go32v1 support
Revision 1.16 2002/01/24 18:25:53 peter
* implicit result variable generation for assembler routines
* removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
Revision 1.59 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
}

View File

@ -65,10 +65,10 @@ Unit Ra386int;
procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:longint;var asmsym:string);
function BuildConstExpression:longint;
function BuildRefConstExpression:longint;
procedure BuildReference(oper : t386operand);
procedure BuildOperand(oper: t386operand);
procedure BuildConstantOperand(oper: t386operand);
procedure BuildOpCode(instr : t386instruction);
procedure BuildReference(oper : tx86operand);
procedure BuildOperand(oper: tx86operand);
procedure BuildConstantOperand(oper: tx86operand);
procedure BuildOpCode(instr : tx86instruction);
procedure BuildConstant(maxvalue: longint);
end;
@ -1028,7 +1028,7 @@ Unit Ra386int;
end;
procedure ti386intreader.BuildReference(oper : t386operand);
procedure ti386intreader.BuildReference(oper : tx86operand);
var
k,l,scale : longint;
tempstr,hs : string;
@ -1366,7 +1366,7 @@ Unit Ra386int;
end;
Procedure ti386intreader.BuildConstantOperand(oper: t386operand);
Procedure ti386intreader.BuildConstantOperand(oper: tx86operand);
var
l : longint;
tempstr : string;
@ -1393,7 +1393,7 @@ Unit Ra386int;
end;
Procedure ti386intreader.BuildOperand(oper: t386operand);
Procedure ti386intreader.BuildOperand(oper: tx86operand);
procedure AddLabelOperand(hl:tasmlabel);
begin
@ -1634,7 +1634,7 @@ Unit Ra386int;
end;
Procedure ti386intreader.BuildOpCode(instr : t386instruction);
Procedure ti386intreader.BuildOpCode(instr : tx86instruction);
var
PrefixOp,OverrideOp: tasmop;
size,
@ -1751,7 +1751,7 @@ Unit Ra386int;
Consume(AS_PTR);
instr.Operands[operandnum].InitRef;
end;
BuildOperand(instr.Operands[operandnum] as t386operand);
BuildOperand(instr.Operands[operandnum] as tx86operand);
{ now set the size which was specified by the override }
instr.Operands[operandnum].setsize(size,true);
end;
@ -1776,10 +1776,10 @@ Unit Ra386int;
Consume(AS_PTR);
instr.Operands[operandnum].InitRef;
end;
BuildOperand(instr.Operands[operandnum] as t386operand);
BuildOperand(instr.Operands[operandnum] as tx86operand);
end;
else
BuildOperand(instr.Operands[operandnum] as t386operand);
BuildOperand(instr.Operands[operandnum] as tx86operand);
end; { end case }
until false;
instr.Ops:=operandnum;
@ -1856,7 +1856,7 @@ Unit Ra386int;
function ti386intreader.Assemble: tlinkedlist;
Var
hl : tasmlabel;
instr : T386Instruction;
instr : Tx86Instruction;
Begin
Message1(asmr_d_start_reading,'intel');
inexpression:=FALSE;
@ -1920,7 +1920,7 @@ Unit Ra386int;
AS_OPCODE :
Begin
instr:=T386Instruction.Create(T386Operand);
instr:=Tx86Instruction.Create(Tx86Operand);
BuildOpcode(instr);
with instr do
begin
@ -1977,7 +1977,11 @@ begin
end.
{
$Log$
Revision 1.68 2003-11-29 20:13:25 florian
Revision 1.69 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.68 2003/11/29 20:13:25 florian
* fixed several pi_do_call problems
Revision 1.67 2003/11/29 15:53:06 florian

View File

@ -70,7 +70,7 @@ interface
,asmmode_ppc_motorola
,asmmode_arm_gas
,asmmode_sparc_gas
,asmmode_x8664_gas
,asmmode_x86_64_gas
);
(* IMPORTANT NOTE:
@ -649,7 +649,11 @@ finalization
end.
{
$Log$
Revision 1.78 2004-01-12 16:39:40 peter
Revision 1.79 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.78 2004/01/12 16:39:40 peter
* sparc updates, mostly float related
Revision 1.77 2004/01/04 21:17:51 jonas

View File

@ -37,7 +37,6 @@ unit cgx86;
type
tcgx86 = class(tcg)
rgfpu : Trgx86fpu;
procedure init_register_allocators;override;
procedure done_register_allocators;override;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
@ -188,19 +187,6 @@ unit cgx86;
end;
procedure Tcgx86.init_register_allocators;
begin
inherited init_register_allocators;
if cs_create_pic in aktmoduleswitches then
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
else
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
rgfpu:=Trgx86fpu.create;
end;
procedure Tcgx86.done_register_allocators;
begin
rg[R_INTREGISTER].free;
@ -1806,63 +1792,45 @@ unit cgx86;
var
href : treference;
size : longint;
r : integer;
begin
{ Get temp }
size:=0;
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
for r:=low(saved_standard_registers) to high(saved_standard_registers) do
if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if size>0 then
begin
tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
{ Copy registers to temp }
href:=current_procinfo.save_regs_ref;
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
for r:=low(saved_standard_registers) to high(saved_standard_registers) do
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EBX,href);
inc(href.offset,POINTER_SIZE);
end;
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_ESI,href);
inc(href.offset,POINTER_SIZE);
end;
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EDI,href);
inc(href.offset,POINTER_SIZE);
if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),href);
inc(href.offset,POINTER_SIZE);
end;
include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
end;
end;
include(rg[R_INTREGISTER].preserved_by_proc,RS_EBX);
include(rg[R_INTREGISTER].preserved_by_proc,RS_ESI);
include(rg[R_INTREGISTER].preserved_by_proc,RS_EDI);
end;
procedure tcgx86.g_restore_standard_registers(list:Taasmoutput);
var
href : treference;
r : integer;
begin
{ Copy registers from temp }
href:=current_procinfo.save_regs_ref;
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EBX);
inc(href.offset,POINTER_SIZE);
end;
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_ESI);
inc(href.offset,POINTER_SIZE);
end;
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EDI);
inc(href.offset,POINTER_SIZE);
end;
for r:=low(saved_standard_registers) to high(saved_standard_registers) do
if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE));
inc(href.offset,POINTER_SIZE);
end;
tg.UnGetTemp(list,current_procinfo.save_regs_ref);
end;
@ -1927,7 +1895,11 @@ unit cgx86;
end.
{
$Log$
Revision 1.101 2004-01-14 21:43:54 peter
Revision 1.102 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.101 2004/01/14 21:43:54 peter
* add release_openarrayvalue
Revision 1.100 2003/12/26 14:02:30 peter

View File

@ -118,22 +118,22 @@ uses
first_fpu_imreg = $08;
{ MM Super registers }
RS_MM0 = $00;
RS_MM1 = $01;
RS_MM2 = $02;
RS_MM3 = $03;
RS_MM4 = $04;
RS_MM5 = $05;
RS_MM6 = $06;
RS_MM7 = $07;
RS_MM8 = $08;
RS_MM9 = $09;
RS_MM10 = $0a;
RS_MM11 = $0b;
RS_MM12 = $0c;
RS_MM13 = $0d;
RS_MM14 = $0e;
RS_MM15 = $0f;
RS_XMM0 = $00;
RS_XMM1 = $01;
RS_XMM2 = $02;
RS_XMM3 = $03;
RS_XMM4 = $04;
RS_XMM5 = $05;
RS_XMM6 = $06;
RS_XMM7 = $07;
RS_XMM8 = $08;
RS_XMM9 = $09;
RS_XMM10 = $0a;
RS_XMM11 = $0b;
RS_XMM12 = $0c;
RS_XMM13 = $0d;
RS_XMM14 = $0e;
RS_XMM15 = $0f;
{ Number of first imaginary register }
{$ifdef x86_64}
@ -535,7 +535,11 @@ implementation
end.
{
$Log$
Revision 1.35 2004-01-12 16:37:59 peter
Revision 1.36 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.35 2004/01/12 16:37:59 peter
* moved spilling code from taicpu to rg
Revision 1.34 2003/12/26 13:19:16 florian

View File

@ -1,500 +0,0 @@
{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl
Reads inline assembler and writes the lines direct to the output
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 radirect;
{$i fpcdefs.inc}
interface
uses
node;
function assemble : tnode;
implementation
uses
{ common }
cutils,
{ global }
globals,verbose,
systems,
{ aasm }
aasmbase,aasmtai,aasmcpu,
{ symtable }
symconst,symbase,symtype,symsym,symtable,defutil,paramgr,
{ pass 1 }
nbas,
{ parser }
scanner,
rax86,
{ codegen }
cgbase,procinfo,
{ constants }
itx86att,
cpubase
;
function assemble : tnode;
var
uhs,
retstr,s,hs : string;
c : char;
ende : boolean;
srsym,sym : tsym;
srsymtable : tsymtable;
code : TAAsmoutput;
i,l : longint;
procedure writeasmline;
var
i : longint;
begin
i:=length(s);
while (i>0) and (s[i] in [' ',#9]) do
dec(i);
s[0]:=chr(i);
if s<>'' then
code.concat(Tai_direct.Create(strpnew(s)));
s:='';
end;
begin
ende:=false;
s:='';
if assigned(current_procinfo.procdef.funcretsym) and
is_fpu(current_procinfo.procdef.rettype.def) then
tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
c:=current_scanner.asmgetcharstart;
code:=TAAsmoutput.Create;
while not(ende) do
begin
{ wrong placement
current_scanner.gettokenpos; }
case c of
'A'..'Z','a'..'z','_' : begin
current_scanner.gettokenpos;
i:=0;
hs:='';
while ((ord(c)>=ord('A')) and (ord(c)<=ord('Z')))
or ((ord(c)>=ord('a')) and (ord(c)<=ord('z')))
or ((ord(c)>=ord('0')) and (ord(c)<=ord('9')))
or (c='_') do
begin
inc(i);
hs[i]:=c;
c:=current_scanner.asmgetchar;
end;
hs[0]:=chr(i);
if upper(hs)='END' then
ende:=true
else
begin
if c=':' then
begin
searchsym(upper(hs),srsym,srsymtable);
if srsym<>nil then
if (srsym.typ = labelsym) then
Begin
hs:=tlabelsym(srsym).lab.name;
tlabelsym(srsym).lab.is_set:=true;
end
else
Message(asmr_w_using_defined_as_local);
end
else if upper(hs)='FWAIT' then
FwaitWarning
else
{ access to local variables }
if assigned(current_procinfo.procdef) then
begin
{ is the last written character an special }
{ char ? }
if (s[length(s)]='%') and
(not paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) and
((pos('AX',upper(hs))>0) or
(pos('AL',upper(hs))>0)) then
tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
if (s[length(s)]<>'%') and
(s[length(s)]<>'$') and
(s[length(s)]<>'.') and
((s[length(s)]<>'0') or (hs[1]<>'x')) then
begin
if assigned(current_procinfo.procdef.localst) and
(current_procinfo.procdef.localst.symtablelevel>=normal_function_level) then
sym:=tsym(current_procinfo.procdef.localst.search(upper(hs)))
else
sym:=nil;
if assigned(sym) then
begin
if (sym.typ = labelsym) then
Begin
hs:=tlabelsym(sym).lab.name;
end
else if sym.typ=varsym then
begin
{variables set are after a comma }
{like in movl %eax,I }
if pos(',',s) > 0 then
tvarsym(sym).varstate:=vs_used
else
if (pos('MOV',upper(s)) > 0) and (tvarsym(sym).varstate=vs_declared) then
Message1(sym_n_uninitialized_local_variable,hs);
if (vo_is_external in tvarsym(sym).varoptions) then
hs:=tvarsym(sym).mangledname
else
hs:='%%'+tvarsym(sym).name;
end
else
{ call to local function }
if (sym.typ=procsym) and ((pos('CALL',upper(s))>0) or
(pos('LEA',upper(s))>0)) then
begin
hs:=tprocsym(sym).first_procdef.mangledname;
end;
end
else
begin
if assigned(current_procinfo.procdef.parast) then
sym:=tsym(current_procinfo.procdef.parast.search(upper(hs)))
else
sym:=nil;
if assigned(sym) then
begin
if sym.typ=varsym then
begin
hs:='%%'+tvarsym(sym).name;
if pos(',',s) > 0 then
tvarsym(sym).varstate:=vs_used;
end;
end
{ I added that but it creates a problem in line.ppi
because there is a local label wbuffer and
a static variable WBUFFER ...
what would you decide, florian ?}
else
begin
uhs:=upper(hs);
if (uhs='__SELF') then
begin
if assigned(current_procinfo.procdef._class) then
uhs:='self'
else
begin
Message(asmr_e_cannot_use_SELF_outside_a_method);
uhs:='';
end;
end
else
if (uhs='__OLDEBP') then
begin
if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
uhs:='parentframe'
else
begin
Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
uhs:='';
end;
end
else
if uhs='__RESULT' then
begin
if (not is_void(current_procinfo.procdef.rettype.def)) then
uhs:='result'
else
begin
Message(asmr_e_void_function);
uhs:='';
end;
end;
if uhs<>'' then
searchsym(uhs,sym,srsymtable)
else
sym:=nil;
if assigned(sym) then
begin
case sym.owner.symtabletype of
globalsymtable,
staticsymtable :
begin
case sym.typ of
varsym :
begin
Message2(asmr_h_direct_global_to_mangled,hs,tvarsym(sym).mangledname);
hs:=tvarsym(sym).mangledname;
inc(tvarsym(sym).refs);
end;
typedconstsym :
begin
Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname);
hs:=ttypedconstsym(sym).mangledname;
end;
procsym :
begin
{ procs can be called or the address can be loaded }
if ((pos('CALL',upper(s))>0) or (pos('LEA',upper(s))>0)) then
begin
if tprocsym(sym).procdef_count>1 then
Message1(asmr_w_direct_global_is_overloaded_func,hs);
Message2(asmr_h_direct_global_to_mangled,hs,tprocsym(sym).first_procdef.mangledname);
hs:=tprocsym(sym).first_procdef.mangledname;
end;
end;
else
Message(asmr_e_wrong_sym_type);
end;
end;
parasymtable,
localsymtable :
begin
case sym.typ of
varsym :
begin
hs:='%%'+tvarsym(sym).name;
inc(tvarsym(sym).refs);
end;
typedconstsym :
begin
Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname);
hs:=ttypedconstsym(sym).mangledname;
end;
else
Message(asmr_e_wrong_sym_type);
end;
end;
end;
end
end;
end;
end;
end;
s:=s+hs;
end;
end;
'{',';',#10,#13 :
begin
writeasmline;
c:=current_scanner.asmgetchar;
end;
#26 :
Message(scan_f_end_of_file);
else
begin
current_scanner.gettokenpos;
inc(byte(s[0]));
s[length(s)]:=c;
c:=current_scanner.asmgetchar;
end;
end;
end;
writeasmline;
assemble:=casmnode.create(code);
end;
{*****************************************************************************
Initialize
*****************************************************************************}
const
{$ifdef x86_64}
asmmode_x86_64_direct_info : tasmmodeinfo =
(
id : asmmode_direct;
idtxt : 'DIRECT'
);
{$else x86_64}
asmmode_i386_direct_info : tasmmodeinfo =
(
id : asmmode_direct;
idtxt : 'DIRECT'
);
{$endif x86_64}
initialization
{$ifdef x86_64}
RegisterAsmMode(asmmode_x86_64_direct_info);
{$else x86_64}
RegisterAsmMode(asmmode_i386_direct_info);
{$endif x86_64}
end.
{
$Log$
Revision 1.11 2003-11-10 19:08:32 peter
* line numbering is now only done when #10, #10#13 is really parsed
instead of when it is the next character
Revision 1.10 2003/10/01 20:34:51 peter
* procinfo unit contains tprocinfo
* cginfo renamed to cgbase
* moved cgmessage to verbose
* fixed ppc and sparc compiles
Revision 1.9 2003/09/23 17:56:06 peter
* locals and paras are allocated in the code generation
* tvarsym.localloc contains the location of para/local when
generating code for the current procedure
Revision 1.8 2003/09/03 15:55:02 peter
* NEWRA branch merged
Revision 1.7.2.1 2003/08/27 21:06:34 peter
* more updates
Revision 1.7 2003/06/13 21:19:33 peter
* current_procdef removed, use current_procinfo.procdef instead
Revision 1.6 2003/06/02 21:42:05 jonas
* function results can now also be regvars
- removed tprocinfo.return_offset, never use it again since it's invalid
if the result is a regvar
Revision 1.5 2003/05/22 21:33:31 peter
* removed some unit dependencies
Revision 1.4 2003/05/15 18:58:54 peter
* removed selfpointer_offset, vmtpointer_offset
* tvarsym.adjusted_address
* address in localsymtable is now in the real direction
* removed some obsolete globals
Revision 1.3 2003/05/13 19:15:28 peter
* removed radirect
Revision 1.2 2003/05/01 07:59:43 florian
* introduced defaultordconsttype to decribe the default size of ordinal constants
on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
+ added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
* int64s/qwords are allowed as for loop counter on 64 bit CPUs
Revision 1.1 2003/04/30 15:45:35 florian
* merged more x86-64/i386 code
Revision 1.11 2003/04/27 11:21:36 peter
* aktprocdef renamed to current_procinfo.procdef
* procinfo renamed to current_procinfo
* procinfo will now be stored in current_module so it can be
cleaned up properly
* gen_main_procsym changed to create_main_proc and release_main_proc
to also generate a tprocinfo structure
* fixed unit implicit initfinal
Revision 1.10 2003/04/27 07:29:52 peter
* current_procinfo.procdef cleanup, current_procinfo.procdef is now always nil when parsing
a new procdef declaration
* aktprocsym removed
* lexlevel removed, use symtable.symtablelevel instead
* implicit init/final code uses the normal genentry/genexit
* funcret state checking updated for new funcret handling
Revision 1.9 2003/04/25 20:59:35 peter
* removed funcretn,funcretsym, function result is now in varsym
and aliases for result and function name are added using absolutesym
* vs_hidden parameter for funcret passed in parameter
* vs_hidden fixes
* writenode changed to printnode and released from extdebug
* -vp option added to generate a tree.log with the nodetree
* nicer printnode for statements, callnode
Revision 1.8 2003/04/25 12:04:31 florian
* merged agx64att and ag386att to x86/agx86att
Revision 1.7 2003/04/21 20:05:10 peter
* removed some ie checks
Revision 1.6 2003/01/08 18:43:57 daniel
* Tregister changed into a record
Revision 1.5 2002/11/25 17:43:27 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once
Revision 1.4 2002/11/18 17:32:00 peter
* pass proccalloption to ret_in_xxx and push_xxx functions
Revision 1.3 2002/09/03 16:26:28 daniel
* Make Tprocdef.defs protected
Revision 1.2 2002/08/17 09:23:47 florian
* first part of procinfo rewrite
Revision 1.1 2002/08/10 14:47:50 carl
+ moved target_cpu_string to cpuinfo
* renamed asmmode enum.
* assembler reader has now less ifdef's
* move from nppcmem.pas -> ncgmem.pas vec. node.
Revision 1.21 2002/07/20 11:58:05 florian
* types.pas renamed to defbase.pas because D6 contains a types
unit so this would conflicts if D6 programms are compiled
+ Willamette/SSE2 instructions to assembler added
Revision 1.20 2002/07/11 14:41:34 florian
* start of the new generic parameter handling
Revision 1.19 2002/07/01 18:46:34 peter
* internal linker
* reorganized aasm layer
Revision 1.18 2002/05/18 13:34:26 peter
* readded missing revisions
Revision 1.17 2002/05/16 19:46:52 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.15 2002/05/12 16:53:18 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function
* -CR checks also class typecasts at runtime by changing them
into as
* fixed compiler to cycle with the -CR option
* fixed stabs with elf writer, finally the global variables can
be watched
* removed a lot of routines from cga unit and replaced them by
calls to cgobj
* u32bit-s32bit updates for and,or,xor nodes. When one element is
u32bit then the other is typecasted also to u32bit without giving
a rangecheck warning/error.
* fixed pascal calling method with reversing also the high tree in
the parast, detected by tcalcst3 test
Revision 1.14 2002/04/15 19:12:09 carl
+ target_info.size_of_pointer -> pointer_size
+ some cleanup of unused types/variables
* move several constants from cpubase to their specific units
(where they are used)
+ att_Reg2str -> gas_reg2str
+ int_reg2str -> std_reg2str
Revision 1.13 2002/04/14 17:01:52 carl
+ att_reg2str -> gas_reg2str
}

View File

@ -41,13 +41,13 @@ Function CheckOverride(overrideop,op:tasmop): Boolean;
Procedure FWaitWarning;
type
T386Operand=class(TOperand)
Tx86Operand=class(TOperand)
opsize : topsize;
Procedure SetSize(_size:longint;force:boolean);override;
Procedure SetCorrectSize(opcode:tasmop);override;
end;
T386Instruction=class(TInstruction)
Tx86Instruction=class(TInstruction)
OpOrder : TOperandOrder;
opsize : topsize;
constructor Create(optype : tcoperand);override;
@ -193,10 +193,10 @@ begin
end;
{*****************************************************************************
T386Operand
TX86Operand
*****************************************************************************}
Procedure T386Operand.SetSize(_size:longint;force:boolean);
Procedure Tx86Operand.SetSize(_size:longint;force:boolean);
begin
inherited SetSize(_size,force);
{ OS_64 will be set to S_L and be fixed later
@ -205,7 +205,7 @@ begin
end;
Procedure T386Operand.SetCorrectSize(opcode:tasmop);
Procedure Tx86Operand.SetCorrectSize(opcode:tasmop);
begin
if gas_needsuffix[opcode]=attsufFPU then
begin
@ -229,14 +229,14 @@ end;
T386Instruction
*****************************************************************************}
constructor T386Instruction.Create(optype : tcoperand);
constructor Tx86Instruction.Create(optype : tcoperand);
begin
inherited Create(optype);
Opsize:=S_NO;
end;
procedure T386Instruction.SwapOperands;
procedure Tx86Instruction.SwapOperands;
begin
Inherited SwapOperands;
{ mark the correct order }
@ -247,7 +247,7 @@ begin
end;
procedure T386Instruction.AddReferenceSizes;
procedure Tx86Instruction.AddReferenceSizes;
{ this will add the sizes for references like [esi] which do not
have the size set yet, it will take only the size if the other
operand is a register }
@ -256,69 +256,73 @@ var
s : tasmsymbol;
so : longint;
begin
for i:=1to ops do
begin
operands[i].SetCorrectSize(opcode);
if t386operand(operands[i]).opsize=S_NO then
for i:=1 to ops do
begin
case operands[i].Opr.Typ of
OPR_LOCAL,
OPR_REFERENCE :
begin
if i=2 then
operand2:=1
else
operand2:=2;
if operand2<ops then
begin
{ Only allow register as operand to take the size from }
if operands[operand2].opr.typ=OPR_REGISTER then
operands[i].SetCorrectSize(opcode);
if tx86operand(operands[i]).opsize=S_NO then
begin
case operands[i].Opr.Typ of
OPR_LOCAL,
OPR_REFERENCE :
begin
if i=2 then
operand2:=1
else
operand2:=2;
if operand2<ops then
begin
if ((opcode<>A_MOVD) and
(opcode<>A_CVTSI2SS)) then
t386operand(operands[i]).opsize:=t386operand(operands[operand2]).opsize;
{ Only allow register as operand to take the size from }
if operands[operand2].opr.typ=OPR_REGISTER then
begin
if ((opcode<>A_MOVD) and
(opcode<>A_CVTSI2SS)) then
tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
end
else
begin
{ if no register then take the opsize (which is available with ATT),
if not availble then give an error }
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
else
begin
Message(asmr_e_unable_to_determine_reference_size);
{ recovery }
tx86operand(operands[i]).opsize:=S_L;
end;
end;
end
else
begin
{ if no register then take the opsize (which is available with ATT),
if not availble then give an error }
if opsize<>S_NO then
t386operand(operands[i]).opsize:=opsize
else
begin
Message(asmr_e_unable_to_determine_reference_size);
{ recovery }
t386operand(operands[i]).opsize:=S_L;
end;
end;
end
else
begin
if opsize<>S_NO then
t386operand(operands[i]).opsize:=opsize
end;
else
begin
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
end;
end;
OPR_SYMBOL :
begin
{ Fix lea which need a reference }
if opcode=A_LEA then
begin
s:=operands[i].opr.symbol;
so:=operands[i].opr.symofs;
operands[i].opr.typ:=OPR_REFERENCE;
Fillchar(operands[i].opr.ref,sizeof(treference),0);
operands[i].opr.ref.symbol:=s;
operands[i].opr.ref.offset:=so;
end;
{$ifdef x86_64}
tx86operand(operands[i]).opsize:=S_Q;
{$else x86_64}
tx86operand(operands[i]).opsize:=S_L;
{$endif x86_64}
end;
end;
OPR_SYMBOL :
begin
{ Fix lea which need a reference }
if opcode=A_LEA then
begin
s:=operands[i].opr.symbol;
so:=operands[i].opr.symofs;
operands[i].opr.typ:=OPR_REFERENCE;
Fillchar(operands[i].opr.ref,sizeof(treference),0);
operands[i].opr.ref.symbol:=s;
operands[i].opr.ref.offset:=so;
end;
t386operand(operands[i]).opsize:=S_L;
end;
end;
end;
end;
end;
end;
procedure T386Instruction.SetInstructionOpsize;
procedure Tx86Instruction.SetInstructionOpsize;
begin
if opsize<>S_NO then
exit;
@ -335,21 +339,21 @@ begin
is_segment_reg(operands[1].opr.reg) then
opsize:=S_L
else
opsize:=t386operand(operands[1]).opsize;
opsize:=tx86operand(operands[1]).opsize;
end;
2 :
begin
case opcode of
A_MOVZX,A_MOVSX :
begin
case t386operand(operands[1]).opsize of
case tx86operand(operands[1]).opsize of
S_W :
case t386operand(operands[2]).opsize of
case tx86operand(operands[2]).opsize of
S_L :
opsize:=S_WL;
end;
S_B :
case t386operand(operands[2]).opsize of
case tx86operand(operands[2]).opsize of
S_W :
opsize:=S_BW;
S_L :
@ -361,18 +365,18 @@ begin
32 bit register or memory, so no opsize is correct here PM }
exit;
A_OUT :
opsize:=t386operand(operands[1]).opsize;
opsize:=tx86operand(operands[1]).opsize;
else
opsize:=t386operand(operands[2]).opsize;
opsize:=tx86operand(operands[2]).opsize;
end;
end;
3 :
opsize:=t386operand(operands[3]).opsize;
opsize:=tx86operand(operands[3]).opsize;
end;
end;
procedure T386Instruction.CheckOperandSizes;
procedure Tx86Instruction.CheckOperandSizes;
var
sizeerr : boolean;
i : longint;
@ -403,11 +407,11 @@ begin
begin
case opsize of
S_BW :
sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_W);
sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_W);
S_BL :
sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_L);
sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_L);
S_WL :
sizeerr:=(t386operand(operands[1]).opsize<>S_W) or (t386operand(operands[2]).opsize<>S_L);
sizeerr:=(tx86operand(operands[1]).opsize<>S_W) or (tx86operand(operands[2]).opsize<>S_L);
end;
end;
end
@ -416,8 +420,8 @@ begin
for i:=1 to ops do
begin
if (operands[i].opr.typ<>OPR_CONSTANT) and
(t386operand(operands[i]).opsize in [S_B,S_W,S_L]) and
(t386operand(operands[i]).opsize<>opsize) then
(tx86operand(operands[i]).opsize in [S_B,S_W,S_L]) and
(tx86operand(operands[i]).opsize<>opsize) then
sizeerr:=true;
end;
end;
@ -436,7 +440,7 @@ end;
{ This check must be done with the operand in ATT order
i.e.after swapping in the intel reader
but before swapping in the NASM and TASM writers PM }
procedure T386Instruction.CheckNonCommutativeOpcodes;
procedure Tx86Instruction.CheckNonCommutativeOpcodes;
begin
if (OpOrder=op_intel) then
SwapOperands;
@ -487,7 +491,7 @@ end;
opcode Adding
*****************************************************************************}
function T386Instruction.ConcatInstruction(p : taasmoutput) : tai;
function Tx86Instruction.ConcatInstruction(p : taasmoutput) : tai;
var
siz : topsize;
i,asize : longint;
@ -502,21 +506,21 @@ begin
else
begin
if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
siz:=t386operand(operands[1]).opsize
siz:=tx86operand(operands[1]).opsize
else
siz:=t386operand(operands[Ops]).opsize;
siz:=tx86operand(operands[Ops]).opsize;
{ MOVD should be of size S_LQ or S_QL, but these do not exist PM }
if (ops=2) and
(t386operand(operands[1]).opsize<>S_NO) and
(t386operand(operands[2]).opsize<>S_NO) and
(t386operand(operands[1]).opsize<>t386operand(operands[2]).opsize) then
(tx86operand(operands[1]).opsize<>S_NO) and
(tx86operand(operands[2]).opsize<>S_NO) and
(tx86operand(operands[1]).opsize<>tx86operand(operands[2]).opsize) then
siz:=S_NO;
end;
if ((opcode=A_MOVD)or
(opcode=A_CVTSI2SS)) and
((t386operand(operands[1]).opsize=S_NO) or
(t386operand(operands[2]).opsize=S_NO)) then
((tx86operand(operands[1]).opsize=S_NO) or
(tx86operand(operands[2]).opsize=S_NO)) then
siz:=S_NO;
{ NASM does not support FADD without args
as alias of FADDP
@ -721,7 +725,9 @@ begin
begin
{ Check the instruction if it's valid }
{$ifndef NOAG386BIN}
{$ifndef x86_64}
ai.CheckIfValid;
{$endif x86_64}
{$endif NOAG386BIN}
p.concat(ai);
end
@ -733,7 +739,11 @@ end;
end.
{
$Log$
Revision 1.15 2003-11-17 23:23:47 florian
Revision 1.16 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.15 2003/11/17 23:23:47 florian
+ first part of arm assembler reader
Revision 1.14 2003/11/12 16:05:40 florian

986
compiler/x86/rax86att.pas Normal file
View File

@ -0,0 +1,986 @@
{
$Id$
Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
Does the parsing for the x86 GNU AS styled inline assembler.
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 rax86att;
{$i fpcdefs.inc}
Interface
uses
cpubase,
raatt,rax86;
type
tx86attreader = class(tattreader)
ActOpsize : topsize;
function is_asmopcode(const s: string):boolean;override;
procedure handleopcode;override;
procedure BuildReference(oper : tx86operand);
procedure BuildOperand(oper : tx86operand);
procedure BuildOpCode(instr : tx86instruction);
procedure handlepercent;override;
end;
Implementation
uses
{ helpers }
cutils,
{ global }
globtype,globals,verbose,
systems,
{ aasm }
cpuinfo,aasmbase,aasmtai,aasmcpu,
{ symtable }
symconst,symbase,symtype,symsym,symtable,
{ parser }
scanner,
procinfo,
itcpugas,
rabase,rautils,
cgbase,cgobj
;
procedure tx86attreader.handlepercent;
var
len : longint;
begin
len:=1;
actasmpattern[len]:='%';
c:=current_scanner.asmgetchar;
{ to be a register there must be a letter and not a number }
if c in ['0'..'9'] then
begin
actasmtoken:=AS_MOD;
end
else
begin
while c in ['a'..'z','A'..'Z','0'..'9'] do
Begin
inc(len);
actasmpattern[len]:=c;
c:=current_scanner.asmgetchar;
end;
actasmpattern[0]:=chr(len);
uppervar(actasmpattern);
if (actasmpattern = '%ST') and (c='(') then
Begin
actasmpattern:=actasmpattern+c;
c:=current_scanner.asmgetchar;
if c in ['0'..'9'] then
actasmpattern:=actasmpattern + c
else
Message(asmr_e_invalid_fpu_register);
c:=current_scanner.asmgetchar;
if c <> ')' then
Message(asmr_e_invalid_fpu_register)
else
Begin
actasmpattern:=actasmpattern + c;
c:=current_scanner.asmgetchar; { let us point to next character. }
end;
end;
if is_register(actasmpattern) then
exit;
Message(asmr_e_invalid_register);
actasmtoken:=raatt.AS_NONE;
end;
end;
Procedure tx86attreader.BuildReference(oper : tx86operand);
procedure Consume_RParen;
begin
if actasmtoken <> AS_RPAREN then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
end
else
begin
Consume(AS_RPAREN);
if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
end;
end;
end;
procedure Consume_Scale;
var
l : longint;
begin
{ we have to process the scaling }
l:=BuildConstExpression(false,true);
if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
oper.opr.ref.scalefactor:=l
else
Begin
Message(asmr_e_wrong_scale_factor);
oper.opr.ref.scalefactor:=0;
end;
end;
begin
oper.InitRef;
Consume(AS_LPAREN);
Case actasmtoken of
AS_INTNUM,
AS_MINUS,
AS_PLUS: { absolute offset, such as fs:(0x046c) }
Begin
{ offset(offset) is invalid }
If oper.opr.Ref.Offset <> 0 Then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
End
Else
Begin
oper.opr.Ref.Offset:=BuildConstExpression(false,true);
Consume_RParen;
end;
exit;
End;
AS_REGISTER: { (reg ... }
Begin
{ Check if there is already a base (mostly ebp,esp) than this is
not allowed, because it will give crashing code }
if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
message(asmr_e_cannot_index_relative_var);
oper.opr.ref.base:=actasmregister;
Consume(AS_REGISTER);
{ can either be a register or a right parenthesis }
{ (reg) }
if actasmtoken=AS_RPAREN then
Begin
Consume_RParen;
exit;
end;
{ (reg,reg .. }
Consume(AS_COMMA);
if actasmtoken=AS_REGISTER then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
{ check for scaling ... }
case actasmtoken of
AS_RPAREN:
Begin
Consume_RParen;
exit;
end;
AS_COMMA:
Begin
Consume(AS_COMMA);
Consume_Scale;
Consume_RParen;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; { end case }
end
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; {end case }
AS_COMMA: { (, ... can either be scaling, or index }
Begin
Consume(AS_COMMA);
{ Index }
if (actasmtoken=AS_REGISTER) then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
{ check for scaling ... }
case actasmtoken of
AS_RPAREN:
Begin
Consume_RParen;
exit;
end;
AS_COMMA:
Begin
Consume(AS_COMMA);
Consume_Scale;
Consume_RParen;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; {end case }
end
{ Scaling }
else
Begin
Consume_Scale;
Consume_RParen;
exit;
end;
end;
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end;
end;
Procedure tx86attreader.BuildOperand(oper : tx86operand);
var
tempstr,
expr : string;
typesize,
l,k : longint;
procedure AddLabelOperand(hl:tasmlabel);
begin
if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
is_calljmp(actopcode) then
begin
oper.opr.typ:=OPR_SYMBOL;
oper.opr.symbol:=hl;
end
else
begin
oper.InitRef;
oper.opr.ref.symbol:=hl;
end;
end;
procedure MaybeRecordOffset;
var
hasdot : boolean;
l,
toffset,
tsize : longint;
begin
if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
exit;
l:=0;
hasdot:=(actasmtoken=AS_DOT);
if hasdot then
begin
if expr<>'' then
begin
BuildRecordOffsetSize(expr,toffset,tsize);
inc(l,toffset);
oper.SetSize(tsize,true);
end;
end;
if actasmtoken in [AS_PLUS,AS_MINUS] then
inc(l,BuildConstExpression(true,false));
case oper.opr.typ of
OPR_LOCAL :
begin
{ don't allow direct access to fields of parameters, because that
will generate buggy code. Allow it only for explicit typecasting }
if hasdot and
(not oper.hastype) and
(tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
(current_procinfo.procdef.proccalloption<>pocall_register) then
Message(asmr_e_cannot_access_field_directly_for_parameters);
inc(oper.opr.localsymofs,l)
end;
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309221);
end;
end;
function MaybeBuildReference:boolean;
{ Try to create a reference, if not a reference is found then false
is returned }
begin
MaybeBuildReference:=true;
case actasmtoken of
AS_INTNUM,
AS_MINUS,
AS_PLUS:
Begin
oper.opr.ref.offset:=BuildConstExpression(True,False);
if actasmtoken<>AS_LPAREN then
Message(asmr_e_invalid_reference_syntax)
else
BuildReference(oper);
end;
AS_LPAREN:
BuildReference(oper);
AS_ID: { only a variable is allowed ... }
Begin
tempstr:=actasmpattern;
Consume(AS_ID);
{ typecasting? }
if (actasmtoken=AS_LPAREN) and
SearchType(tempstr,typesize) then
begin
oper.hastype:=true;
Consume(AS_LPAREN);
BuildOperand(oper);
Consume(AS_RPAREN);
if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
oper.SetSize(typesize,true);
end
else
if not oper.SetupVar(tempstr,false) then
Message1(sym_e_unknown_id,tempstr);
{ record.field ? }
if actasmtoken=AS_DOT then
begin
BuildRecordOffsetSize(tempstr,l,k);
inc(oper.opr.ref.offset,l);
end;
case actasmtoken of
AS_END,
AS_SEPARATOR,
AS_COMMA: ;
AS_LPAREN:
BuildReference(oper);
else
Begin
Message(asmr_e_invalid_reference_syntax);
Consume(actasmtoken);
end;
end; {end case }
end;
else
MaybeBuildReference:=false;
end; { end case }
end;
const
regsize_2_size: array[S_B..S_L] of longint = (1,2,4);
var
tempreg : tregister;
hl : tasmlabel;
Begin
expr:='';
case actasmtoken of
AS_LPAREN: { Memory reference or constant expression }
Begin
oper.InitRef;
BuildReference(oper);
end;
AS_DOLLAR: { Constant expression }
Begin
Consume(AS_DOLLAR);
BuildConstantOperand(oper);
end;
AS_INTNUM,
AS_MINUS,
AS_PLUS:
Begin
{ Constant memory offset }
{ This must absolutely be followed by ( }
oper.InitRef;
oper.opr.ref.offset:=BuildConstExpression(True,False);
if actasmtoken<>AS_LPAREN then
Message(asmr_e_invalid_reference_syntax)
else
BuildReference(oper);
end;
AS_STAR: { Call from memory address }
Begin
Consume(AS_STAR);
if actasmtoken=AS_REGISTER then
begin
oper.opr.typ:=OPR_REGISTER;
oper.opr.reg:=actasmregister;
oper.SetSize(regsize_2_size[reg2opsize(actasmregister)],true);
Consume(AS_REGISTER);
end
else
begin
oper.InitRef;
if not MaybeBuildReference then
Message(asmr_e_syn_operand);
end;
{ this is only allowed for call's and jmp's }
if not is_calljmp(actopcode) then
Message(asmr_e_syn_operand);
end;
AS_ID: { A constant expression, or a Variable ref. }
Begin
{ Local Label ? }
if is_locallabel(actasmpattern) then
begin
CreateLocalLabel(actasmpattern,hl,false);
Consume(AS_ID);
AddLabelOperand(hl);
end
else
{ Check for label }
if SearchLabel(actasmpattern,hl,false) then
begin
Consume(AS_ID);
AddLabelOperand(hl);
end
else
{ probably a variable or normal expression }
{ or a procedure (such as in CALL ID) }
Begin
{ is it a constant ? }
if SearchIConstant(actasmpattern,l) then
Begin
if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
Message(asmr_e_invalid_operand_type);
BuildConstantOperand(oper);
end
else
begin
expr:=actasmpattern;
Consume(AS_ID);
{ typecasting? }
if (actasmtoken=AS_LPAREN) and
SearchType(expr,typesize) then
begin
oper.hastype:=true;
Consume(AS_LPAREN);
BuildOperand(oper);
Consume(AS_RPAREN);
if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
oper.SetSize(typesize,true);
end
else
begin
if oper.SetupVar(expr,false) then
begin
end
else
Begin
{ look for special symbols ... }
if expr= '__HIGH' then
begin
consume(AS_LPAREN);
if not oper.setupvar('high'+actasmpattern,false) then
Message1(sym_e_unknown_id,'high'+actasmpattern);
consume(AS_ID);
consume(AS_RPAREN);
end
else
if expr = '__RESULT' then
oper.SetUpResult
else
if expr = '__SELF' then
oper.SetupSelf
else
if expr = '__OLDEBP' then
oper.SetupOldEBP
else
{ check for direct symbolic names }
{ only if compiling the system unit }
if (cs_compilesystem in aktmoduleswitches) then
begin
if not oper.SetupDirectVar(expr) then
Begin
{ not found, finally ... add it anyways ... }
Message1(asmr_w_id_supposed_external,expr);
oper.InitRef;
oper.opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
end;
end
else
Message1(sym_e_unknown_id,expr);
end;
end;
end;
if actasmtoken=AS_DOT then
MaybeRecordOffset;
{ add a constant expression? }
if (actasmtoken=AS_PLUS) then
begin
l:=BuildConstExpression(true,false);
case oper.opr.typ of
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_LOCAL :
inc(oper.opr.localsymofs,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309202);
end;
end
end;
{ Do we have a indexing reference, then parse it also }
if actasmtoken=AS_LPAREN then
BuildReference(oper);
end;
AS_REGISTER: { Register, a variable reference or a constant reference }
Begin
{ save the type of register used. }
tempreg:=actasmregister;
Consume(AS_REGISTER);
if actasmtoken = AS_COLON then
Begin
Consume(AS_COLON);
oper.InitRef;
oper.opr.ref.segment:=tempreg;
{ This must absolutely be followed by a reference }
if not MaybeBuildReference then
Begin
Message(asmr_e_invalid_seg_override);
Consume(actasmtoken);
end;
end
{ Simple register }
else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
Begin
if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
Message(asmr_e_invalid_operand_type);
oper.opr.typ:=OPR_REGISTER;
oper.opr.reg:=tempreg;
oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
end
else
Message(asmr_e_syn_operand);
end;
AS_END,
AS_SEPARATOR,
AS_COMMA: ;
else
Begin
Message(asmr_e_syn_operand);
Consume(actasmtoken);
end;
end; { end case }
end;
procedure tx86attreader.BuildOpCode(instr : tx86instruction);
var
operandnum : longint;
PrefixOp,OverrideOp: tasmop;
Begin
PrefixOp:=A_None;
OverrideOp:=A_None;
{ prefix seg opcode / prefix opcode }
repeat
if is_prefix(actopcode) then
begin
PrefixOp:=ActOpcode;
with instr do
begin
opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
ConcatInstruction(curlist);
end;
Consume(AS_OPCODE);
end
else
if is_override(actopcode) then
begin
OverrideOp:=ActOpcode;
with instr do
begin
opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
ConcatInstruction(curlist);
end;
Consume(AS_OPCODE);
end
else
break;
{ allow for newline as in gas styled syntax }
while actasmtoken=AS_SEPARATOR do
Consume(AS_SEPARATOR);
until (actasmtoken<>AS_OPCODE);
{ opcode }
if (actasmtoken<>AS_OPCODE) then
Begin
Message(asmr_e_invalid_or_missing_opcode);
RecoverConsume(true);
exit;
end;
{ Fill the instr object with the current state }
with instr do
begin
Opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
end;
{ Valid combination of prefix/override and instruction ? }
if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
{ We are reading operands, so opcode will be an AS_ID }
operandnum:=1;
Consume(AS_OPCODE);
{ Zero operand opcode ? }
if actasmtoken in [AS_SEPARATOR,AS_END] then
begin
operandnum:=0;
exit;
end;
{ Read the operands }
repeat
case actasmtoken of
AS_COMMA: { Operand delimiter }
Begin
if operandnum > Max_Operands then
Message(asmr_e_too_many_operands)
else
Inc(operandnum);
Consume(AS_COMMA);
end;
AS_SEPARATOR,
AS_END : { End of asm operands for this opcode }
begin
break;
end;
else
BuildOperand(instr.Operands[operandnum] as tx86operand);
end; { end case }
until false;
instr.Ops:=operandnum;
end;
function tx86attreader.is_asmopcode(const s: string):boolean;
const
{ We need first to check the long prefixes, else we get probs
with things like movsbl }
att_sizesuffixstr : array[0..9] of string[2] = (
'','BW','BL','WL','B','W','L','S','Q','T'
);
att_sizesuffix : array[0..9] of topsize = (
S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
);
att_sizefpusuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
);
att_sizefpuintsuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
);
var
str2opentry: tstr2opentry;
cond : string[4];
cnd : tasmcond;
len,
j,
sufidx : longint;
Begin
is_asmopcode:=FALSE;
actopcode:=A_None;
actcondition:=C_None;
actopsize:=S_NO;
{ search for all possible suffixes }
for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
begin
len:=length(s)-length(att_sizesuffixstr[sufidx]);
if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
begin
{ here we search the entire table... }
str2opentry:=nil;
if {(length(s)>0) and} (len>0) then
str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
if assigned(str2opentry) then
begin
actopcode:=str2opentry.op;
if gas_needsuffix[actopcode]=attsufFPU then
actopsize:=att_sizefpusuffix[sufidx]
else if gas_needsuffix[actopcode]=attsufFPUint then
actopsize:=att_sizefpuintsuffix[sufidx]
else
actopsize:=att_sizesuffix[sufidx];
actasmtoken:=AS_OPCODE;
is_asmopcode:=TRUE;
exit;
end;
{ not found, check condition opcodes }
j:=0;
while (j<CondAsmOps) do
begin
if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
begin
cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
if cond<>'' then
begin
for cnd:=low(TasmCond) to high(TasmCond) do
if Cond=Upper(cond2str[cnd]) then
begin
actopcode:=CondASmOp[j];
if gas_needsuffix[actopcode]=attsufFPU then
actopsize:=att_sizefpusuffix[sufidx]
else if gas_needsuffix[actopcode]=attsufFPUint then
actopsize:=att_sizefpuintsuffix[sufidx]
else
actopsize:=att_sizesuffix[sufidx];
actcondition:=cnd;
actasmtoken:=AS_OPCODE;
is_asmopcode:=TRUE;
exit;
end;
end;
end;
inc(j);
end;
end;
end;
end;
procedure tx86attreader.handleopcode;
var
instr : Tx86Instruction;
begin
instr:=Tx86Instruction.Create(Tx86Operand);
instr.OpOrder:=op_att;
BuildOpcode(instr);
instr.AddReferenceSizes;
instr.SetInstructionOpsize;
instr.CheckOperandSizes;
instr.ConcatInstruction(curlist);
instr.Free;
end;
end.
{
$Log$
Revision 1.1 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.58 2003/11/12 16:05:39 florian
* assembler readers OOPed
+ typed currency constants
+ typed 128 bit float constants if the CPU supports it
Revision 1.57 2003/11/10 19:08:32 peter
* line numbering is now only done when #10, #10#13 is really parsed
instead of when it is the next character
Revision 1.56 2003/10/29 16:47:18 peter
* fix field offset in reference
Revision 1.55 2003/10/26 13:37:22 florian
* fixed web bug 2128
Revision 1.54 2003/10/24 17:39:03 peter
* more intel parser updates
Revision 1.53 2003/10/23 17:19:44 peter
* typecasting fixes
* reference building more delphi compatible
Revision 1.52 2003/10/20 19:29:35 peter
* fix check for register subscription of reference parameter
Revision 1.51 2003/10/16 21:29:24 peter
+ __HIGH() to retrieve high value
Revision 1.50 2003/10/07 18:21:18 peter
* fix crash
* allow parameter subscription for register parameters
Revision 1.49 2003/10/01 20:34:49 peter
* procinfo unit contains tprocinfo
* cginfo renamed to cgbase
* moved cgmessage to verbose
* fixed ppc and sparc compiles
Revision 1.48 2003/09/23 20:37:53 peter
* fix global var+offset
Revision 1.47 2003/09/23 17:56:06 peter
* locals and paras are allocated in the code generation
* tvarsym.localloc contains the location of para/local when
generating code for the current procedure
Revision 1.46 2003/09/03 15:55:01 peter
* NEWRA branch merged
Revision 1.45.2.2 2003/08/31 15:46:26 peter
* more updates for tregister
Revision 1.45.2.1 2003/08/28 18:35:08 peter
* tregister changed to cardinal
Revision 1.45 2003/05/30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.44 2003/05/22 21:32:29 peter
* removed some unit dependencies
Revision 1.43 2003/04/30 15:45:35 florian
* merged more x86-64/i386 code
Revision 1.42 2003/04/25 12:04:31 florian
* merged agx64att and ag386att to x86/agx86att
Revision 1.41 2003/04/21 20:05:10 peter
* removed some ie checks
Revision 1.40 2003/03/18 18:15:53 peter
* changed reg2opsize to function
Revision 1.39 2003/02/20 15:52:58 pierre
* fix a range check error
Revision 1.38 2003/02/19 22:00:16 daniel
* Code generator converted to new register notation
- Horribily outdated todo.txt removed
Revision 1.37 2003/02/03 22:47:14 daniel
- Removed reg_2_opsize array
Revision 1.36 2003/01/08 18:43:57 daniel
* Tregister changed into a record
Revision 1.35 2002/12/14 15:02:03 carl
* maxoperands -> max_operands (for portability in rautils.pas)
* fix some range-check errors with loadconst
+ add ncgadd unit to m68k
* some bugfix of a_param_reg with LOC_CREFERENCE
Revision 1.34 2002/12/01 22:08:34 carl
* some small cleanup (remove some specific operators which are not supported)
Revision 1.33 2002/11/30 23:16:39 carl
- removed unused message
Revision 1.32 2002/11/15 01:58:58 peter
* merged changes from 1.0.7 up to 04-11
- -V option for generating bug report tracing
- more tracing for option parsing
- errors for cdecl and high()
- win32 import stabs
- win32 records<=8 are returned in eax:edx (turned off by default)
- heaptrc update
- more info for temp management in .s file with EXTDEBUG
Revision 1.31 2002/09/03 16:26:28 daniel
* Make Tprocdef.defs protected
Revision 1.30 2002/08/13 18:01:52 carl
* rename swatoperands to swapoperands
+ m68k first compilable version (still needs a lot of testing):
assembler generator, system information , inline
assembler reader.
Revision 1.29 2002/08/12 15:08:42 carl
+ stab register indexes for powerpc (moved from gdb to cpubase)
+ tprocessor enumeration moved to cpuinfo
+ linker in target_info is now a class
* many many updates for m68k (will soon start to compile)
- removed some ifdef or correct them for correct cpu
Revision 1.28 2002/08/11 14:32:31 peter
* renamed current_library to objectlibrary
Revision 1.27 2002/08/11 13:24:17 peter
* saving of asmsymbols in ppu supported
* asmsymbollist global is removed and moved into a new class
tasmlibrarydata that will hold the info of a .a file which
corresponds with a single module. Added librarydata to tmodule
to keep the library info stored for the module. In the future the
objectfiles will also be stored to the tasmlibrarydata class
* all getlabel/newasmsymbol and friends are moved to the new class
Revision 1.26 2002/07/26 21:15:44 florian
* rewrote the system handling
Revision 1.25 2002/07/01 18:46:34 peter
* internal linker
* reorganized aasm layer
Revision 1.24 2002/05/18 13:34:25 peter
* readded missing revisions
Revision 1.23 2002/05/16 19:46:52 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.21 2002/04/15 19:12:09 carl
+ target_info.size_of_pointer -> pointer_size
+ some cleanup of unused types/variables
* move several constants from cpubase to their specific units
(where they are used)
+ att_Reg2str -> gas_reg2str
+ int_reg2str -> std_reg2str
Revision 1.20 2002/04/14 17:01:52 carl
+ att_reg2str -> gas_reg2str
Revision 1.19 2002/04/04 19:06:13 peter
* removed unused units
* use tlocation.size in cg.a_*loc*() routines
Revision 1.18 2002/04/02 17:11:39 peter
* tlocation,treference update
* LOC_CONSTANT added for better constant handling
* secondadd splitted in multiple routines
* location_force_reg added for loading a location to a register
of a specified size
* secondassignment parses now first the right and then the left node
(this is compatible with Kylix). This saves a lot of push/pop especially
with string operations
* adapted some routines to use the new cg methods
Revision 1.17 2002/03/28 20:48:25 carl
- remove go32v1 support
Revision 1.16 2002/01/24 18:25:53 peter
* implicit result variable generation for assembler routines
* removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
}

View File

@ -32,10 +32,11 @@ unit cgcpu;
cgbase,cgobj,cg64f64,cgx86,
aasmbase,aasmtai,aasmcpu,
cpubase,cpuinfo,cpupara,
node,symconst;
node,symconst,rgx86;
type
tcgx86_64 = class(tcgx86)
procedure init_register_allocators;override;
class function reg_cgsize(const reg: tregister): tcgsize; override;
procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
end;
@ -48,6 +49,19 @@ unit cgcpu;
rgobj,tgobj,rgcpu;
procedure Tcgx86_64.init_register_allocators;
begin
inherited init_register_allocators;
if cs_create_pic in aktmoduleswitches then
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
else
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
rgfpu:=Trgx86fpu.create;
end;
class function tcgx86_64.reg_cgsize(const reg: tregister): tcgsize;
const subreg2cgsize:array[Tsubregister] of Tcgsize =
(OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO);
@ -206,7 +220,11 @@ begin
end.
{
$Log$
Revision 1.8 2004-01-13 18:08:58 florian
Revision 1.9 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.8 2004/01/13 18:08:58 florian
* x86-64 compilation fixed
Revision 1.7 2003/12/24 01:47:23 florian

View File

@ -123,7 +123,7 @@ const
This value can be deduced from the CALLED_USED_REGISTERS array in the
GCC source.
}
std_saved_registers = [RS_ESI,RS_EDI,RS_EBX];
saved_standard_registers : array[0..4] of tsuperregister = (RS_EBX,RS_R12,RS_R13,RS_R14,RS_R15);
{ Required parameter alignment when calling a routine declared as
stdcall and cdecl. The alignment value should be the one defined
by GCC or the target ABI.
@ -135,7 +135,11 @@ const
{
$Log$
Revision 1.9 2003-12-22 19:00:17 florian
Revision 1.10 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.9 2003/12/22 19:00:17 florian
* fixed some x86-64 issues
Revision 1.8 2003/09/25 13:13:32 florian

View File

@ -49,11 +49,12 @@ unit cpupara;
uses
verbose,
cpuinfo,cgbase,
cpuinfo,cgbase,systems,
defutil;
const
intreg_nr2reg : array[1..6] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
parammsupregs : array[0..7] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7);
function getparaloc(p : tdef) : tcgloc;
@ -120,15 +121,17 @@ unit cpupara;
end;
end;
function tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint): tparalocation;
begin
fillchar(result,sizeof(tparalocation),0);
result.size:=OS_INT;
if nr<1 then
internalerror(200304303)
else if nr<=6 then
else if nr<=high(paraintsupregs)+1 then
begin
result.loc:=LOC_REGISTER;
result.register:=newreg(R_INTREGISTER,intreg_nr2reg[nr],R_SUBWHOLE);
result.register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
end
else
begin
@ -140,11 +143,82 @@ unit cpupara;
function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
var
hp : tparaitem;
paraloc : tparalocation;
subreg : tsubregister;
pushaddr : boolean;
l,intparareg,mmparareg,
varalign,
paraalign,
parasize : longint;
begin
{ set default para_alignment to target_info.stackalignment }
{ if para_alignment=0 then
para_alignment:=aktalignment.paraalign;
}
intparareg:=0;
mmparareg:=0;
parasize:=0;
paraalign:=get_para_align(p.proccalloption);
{ Register parameters are assigned from left to right }
hp:=tparaitem(p.para.first);
while assigned(hp) do
begin
pushaddr:=push_addr_param(hp.paratyp,hp.paratype.def,p.proccalloption);
if pushaddr then
paraloc.size:=OS_ADDR
else
paraloc.size:=def_cgsize(hp.paratype.def);
paraloc.alignment:=paraalign;
if (intparareg<=high(paraintsupregs)) and
not(
((hp.paratype.def.deftype in [floatdef,recorddef,arraydef]) and
(not pushaddr))
) then
begin
paraloc.loc:=LOC_REGISTER;
if paraloc.size=OS_NO then
subreg:=R_SUBWHOLE
else
subreg:=cgsize2subreg(paraloc.size);
paraloc.alignment:=paraalign;
paraloc.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
inc(intparareg);
end
else if (mmparareg<=high(parammsupregs)) then
begin
end
else
begin
paraloc.loc:=LOC_REFERENCE;
if side=callerside then
paraloc.reference.index:=NR_STACK_POINTER_REG
else
paraloc.reference.index:=NR_FRAME_POINTER_REG;
l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
// varalign:=size_2_align(l);
paraloc.reference.offset:=parasize;
// varalign:=used_align(varalign,paraalign,paraalign);
// parasize:=align(parasize+l,varalign);
end;
hp.paraloc[side]:=paraloc;
hp:=tparaitem(hp.next);
end;
{ Register parameters are assigned from left-to-right, adapt offset
for calleeside to be reversed }
hp:=tparaitem(p.para.first);
while assigned(hp) do
begin
if (hp.paraloc[side].loc=LOC_REFERENCE) then
begin
l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
// varalign:=used_align(size_2_align(l),paraalign,paraalign);
// l:=align(l,varalign);
hp.paraloc[side].reference.offset:=parasize-hp.paraloc[side].reference.offset-l;
if side=calleeside then
inc(hp.paraloc[side].reference.offset,target_info.first_parm_offset);
end;
hp:=tparaitem(hp.next);
end;
{ We need to return the size allocated }
result:=parasize;
end;
@ -153,7 +227,11 @@ begin
end.
{
$Log$
Revision 1.5 2003-12-24 00:10:03 florian
Revision 1.6 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
Revision 1.5 2003/12/24 00:10:03 florian
- delete parameter in cg64 methods removed
Revision 1.4 2003/04/30 20:53:32 florian

View File

@ -0,0 +1,76 @@
{
$Id$
Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
Does the parsing for the i386 GNU AS styled inline assembler.
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 rax64att;
{$i fpcdefs.inc}
interface
uses
rax86att;
type
tx8664attreader = class(tx86attreader)
procedure handleopcode;override;
end;
implementation
uses
rabase,systems,rax86,aasmcpu;
procedure tx8664attreader.handleopcode;
var
instr : Tx86Instruction;
begin
instr:=Tx86Instruction.Create(Tx86Operand);
instr.OpOrder:=op_att;
BuildOpcode(instr);
instr.AddReferenceSizes;
instr.SetInstructionOpsize;
{
instr.CheckOperandSizes;
}
instr.ConcatInstruction(curlist);
instr.Free;
end;
const
asmmode_x86_64_gas_info : tasmmodeinfo =
(
id : asmmode_x86_64_gas;
idtxt : 'GAS';
casmreader : tx8664attreader;
);
initialization
RegisterAsmMode(asmmode_x86_64_gas_info);
end.
{
$Log$
Revision 1.1 2004-01-14 23:39:05 florian
* another bunch of x86-64 fixes mainly calling convention and
assembler reader related
}