summaryrefslogtreecommitdiff
path: root/compiler/x86
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/x86')
-rw-r--r--compiler/x86/aasmcpu.pas197
-rw-r--r--compiler/x86/agx86att.pas24
-rw-r--r--compiler/x86/agx86nsm.pas2
-rw-r--r--compiler/x86/nx86add.pas27
-rw-r--r--compiler/x86/nx86mat.pas8
-rw-r--r--compiler/x86/rax86.pas28
-rw-r--r--compiler/x86/rax86att.pas4
-rw-r--r--compiler/x86/rax86int.pas63
-rw-r--r--compiler/x86/symx86.pas120
9 files changed, 317 insertions, 156 deletions
diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas
index 89995f8df8..9462f72f01 100644
--- a/compiler/x86/aasmcpu.pas
+++ b/compiler/x86/aasmcpu.pas
@@ -1239,7 +1239,7 @@ implementation
assembler }
end;
else
- internalerror(200402261);
+ internalerror(200402266);
end;
end;
end;
@@ -1827,9 +1827,13 @@ implementation
{No register, so memory reference.}
if (input.typ<>top_ref) then
internalerror(200409262);
- if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
+
+ if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)=R_MMREGISTER) and (input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) or // vector memory (AVX2)
+ ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER) and (getregtype(input.ref^.index)<>R_MMREGISTER)) or
((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
- internalerror(200301081);
+ internalerror(200301081);
+
+
ir:=input.ref^.index;
br:=input.ref^.base;
isub:=getsubreg(ir);
@@ -1849,8 +1853,15 @@ implementation
{ it's an indirection }
begin
{ 16 bit address? }
- if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
- ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
+
+ if ((ir<>NR_NO) and (isub in [R_SUBMMX,R_SUBMMY]) and
+ (br<>NR_NO) and (bsub=R_SUBADDR)
+ ) then
+ begin
+ // vector memory (AVX2) =>> ignore
+ end
+ else if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
+ ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
message(asmw_e_16bit_not_supported);
{$ifdef OPTEA}
{ make single reg base }
@@ -1893,14 +1904,30 @@ implementation
end;
{ index }
case ir of
- NR_EAX : index:=0;
- NR_ECX : index:=1;
- NR_EDX : index:=2;
- NR_EBX : index:=3;
- NR_NO : index:=4;
- NR_EBP : index:=5;
- NR_ESI : index:=6;
- NR_EDI : index:=7;
+ NR_EAX,
+ NR_XMM0,
+ NR_YMM0: index:=0;
+ NR_ECX,
+ NR_XMM1,
+ NR_YMM1: index:=1;
+ NR_EDX,
+ NR_XMM2,
+ NR_YMM2: index:=2;
+ NR_EBX,
+ NR_XMM3,
+ NR_YMM3: index:=3;
+ NR_NO,
+ NR_XMM4,
+ NR_YMM4: index:=4;
+ NR_EBP,
+ NR_XMM5,
+ NR_YMM5: index:=5;
+ NR_ESI,
+ NR_XMM6,
+ NR_YMM6: index:=6;
+ NR_EDI,
+ NR_XMM7,
+ NR_YMM7: index:=7;
else
exit;
end;
@@ -3290,46 +3317,44 @@ implementation
RegXMMSizeMask := RegXMMSizeMask;
end;
-
-
for j := 0 to insentry^.ops -1 do
begin
if (insentry^.optypes[j] and OT_REGISTER) = OT_REGISTER then
- begin
- inc(actRegCount);
-
- NewRegSize := (insentry^.optypes[j] and OT_SIZE_MASK);
- if NewRegSize = 0 then
begin
- case insentry^.optypes[j] and (OT_MMXREG OR OT_XMMREG OR OT_YMMREG) of
- OT_MMXREG: begin
- NewRegSize := OT_BITS64;
- end;
- OT_XMMREG: begin
- NewRegSize := OT_BITS128;
- InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
- end;
- OT_YMMREG: begin
- NewRegSize := OT_BITS256;
- InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
- end;
- else NewRegSize := not(0);
+ inc(actRegCount);
+
+ NewRegSize := (insentry^.optypes[j] and OT_SIZE_MASK);
+ if NewRegSize = 0 then
+ begin
+ case insentry^.optypes[j] and (OT_MMXREG OR OT_XMMREG OR OT_YMMREG) of
+ OT_MMXREG: begin
+ NewRegSize := OT_BITS64;
+ end;
+ OT_XMMREG: begin
+ NewRegSize := OT_BITS128;
+ InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
+ end;
+ OT_YMMREG: begin
+ NewRegSize := OT_BITS256;
+ InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
+ end;
+ else NewRegSize := not(0);
+ end;
end;
- end;
actRegSize := actRegSize or NewRegSize;
actRegTypes := actRegTypes or (insentry^.optypes[j] and (OT_MMXREG OR OT_XMMREG OR OT_YMMREG));
- end
+ end
else if ((insentry^.optypes[j] and OT_MEMORY) <> 0) then
- begin
- inc(actMemCount);
-
- actMemSize := actMemSize or (insentry^.optypes[j] and OT_SIZE_MASK);
- if (insentry^.optypes[j] and OT_REGMEM) = OT_REGMEM then
begin
- actRegMemTypes := actRegMemTypes or insentry^.optypes[j];
- end;
- end
+ inc(actMemCount);
+
+ actMemSize:=actMemSize or (insentry^.optypes[j] and OT_SIZE_MASK);
+ if (insentry^.optypes[j] and OT_REGMEM) = OT_REGMEM then
+ begin
+ actRegMemTypes := actRegMemTypes or insentry^.optypes[j];
+ end;
+ end
else if ((insentry^.optypes[j] and OT_IMMEDIATE) = OT_IMMEDIATE) then
begin
inc(actConstCount);
@@ -3341,12 +3366,12 @@ implementation
if actConstCount > 0 then
begin
case actConstSize of
- 0: SConstInfo := csiNoSize;
- OT_BITS8: SConstInfo := csiMem8;
+ 0: SConstInfo := csiNoSize;
+ OT_BITS8: SConstInfo := csiMem8;
OT_BITS16: SConstInfo := csiMem16;
OT_BITS32: SConstInfo := csiMem32;
OT_BITS64: SConstInfo := csiMem64;
- else SConstInfo := csiMultiple;
+ else SConstInfo := csiMultiple;
end;
if InsTabMemRefSizeInfoCache^[AsmOp].ConstSize = csiUnkown then
@@ -3371,59 +3396,57 @@ implementation
end;
case actMemSize of
- 0: MRefInfo := msiNoSize;
- OT_BITS8: MRefInfo := msiMem8;
- OT_BITS16: MRefInfo := msiMem16;
- OT_BITS32: MRefInfo := msiMem32;
- OT_BITS64: MRefInfo := msiMem64;
+ 0: MRefInfo := msiNoSize;
+ OT_BITS8: MRefInfo := msiMem8;
+ OT_BITS16: MRefInfo := msiMem16;
+ OT_BITS32: MRefInfo := msiMem32;
+ OT_BITS64: MRefInfo := msiMem64;
OT_BITS128: MRefInfo := msiMem128;
OT_BITS256: MRefInfo := msiMem256;
OT_BITS80,
- OT_FAR,
- OT_NEAR,
- OT_SHORT: ; // ignore
- else begin
- bitcount := bitcnt(actMemSize);
-
- if bitcount > 1 then MRefInfo := msiMultiple
- else InternalError(777203);
- end;
+ OT_FAR,
+ OT_NEAR,
+ OT_SHORT: ; // ignore
+ else
+ begin
+ bitcount := bitcnt(actMemSize);
+
+ if bitcount > 1 then MRefInfo := msiMultiple
+ else InternalError(777203);
+ end;
end;
if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
- begin
- InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
- end
+ begin
+ InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
+ end
else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
- begin
- with InsTabMemRefSizeInfoCache^[AsmOp] do
begin
-
-
- if ((MemRefSize = msiMem8) OR (MRefInfo = msiMem8)) then MemRefSize := msiMultiple8
- else if ((MemRefSize = msiMem16) OR (MRefInfo = msiMem16)) then MemRefSize := msiMultiple16
- else if ((MemRefSize = msiMem32) OR (MRefInfo = msiMem32)) then MemRefSize := msiMultiple32
- else if ((MemRefSize = msiMem64) OR (MRefInfo = msiMem64)) then MemRefSize := msiMultiple64
- else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
- else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
-
- else MemRefSize := msiMultiple;
- end;
+ with InsTabMemRefSizeInfoCache^[AsmOp] do
+ begin
+ if ((MemRefSize = msiMem8) OR (MRefInfo = msiMem8)) then MemRefSize := msiMultiple8
+ else if ((MemRefSize = msiMem16) OR (MRefInfo = msiMem16)) then MemRefSize := msiMultiple16
+ else if ((MemRefSize = msiMem32) OR (MRefInfo = msiMem32)) then MemRefSize := msiMultiple32
+ else if ((MemRefSize = msiMem64) OR (MRefInfo = msiMem64)) then MemRefSize := msiMultiple64
+ else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
+ else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
+ else MemRefSize := msiMultiple;
+ end;
end;
if actRegCount > 0 then
- begin
- case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG) of
- OT_MMXREG: RegMMXSizeMask := RegMMXSizeMask or actMemSize;
- OT_XMMREG: RegXMMSizeMask := RegXMMSizeMask or actMemSize;
- OT_YMMREG: RegYMMSizeMask := RegYMMSizeMask or actMemSize;
- else begin
- RegMMXSizeMask := not(0);
- RegXMMSizeMask := not(0);
- RegYMMSizeMask := not(0);
- end;
+ begin
+ case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG) of
+ OT_MMXREG: RegMMXSizeMask := RegMMXSizeMask or actMemSize;
+ OT_XMMREG: RegXMMSizeMask := RegXMMSizeMask or actMemSize;
+ OT_YMMREG: RegYMMSizeMask := RegYMMSizeMask or actMemSize;
+ else begin
+ RegMMXSizeMask := not(0);
+ RegXMMSizeMask := not(0);
+ RegYMMSizeMask := not(0);
+ end;
+ end;
end;
- end;
end;
else InternalError(777202);
end;
diff --git a/compiler/x86/agx86att.pas b/compiler/x86/agx86att.pas
index 3c58323d9c..ab2970b762 100644
--- a/compiler/x86/agx86att.pas
+++ b/compiler/x86/agx86att.pas
@@ -163,18 +163,19 @@ interface
if assigned(relsymbol) then
owner.AsmWrite('-'+relsymbol.name);
if ref.refaddr=addr_pic then
-{$ifdef x86_64}
begin
- { local symbols don't have to (and in case of Mac OS X: cannot)
- be accessed via the GOT
- }
- if not assigned(ref.symbol) or
- (ref.symbol.bind<>AB_LOCAL) then
- owner.AsmWrite('@GOTPCREL');
- end;
+ { @GOT and @GOTPCREL references are only allowed for symbol alone,
+ indexing, relsymbol or offset cannot be present. }
+ if assigned(relsymbol) or (offset<>0) or (index<>NR_NO) then
+ InternalError(2015011801);
+{$ifdef x86_64}
+ if (base<>NR_RIP) then
+ InternalError(2015011802);
+ owner.AsmWrite('@GOTPCREL');
{$else x86_64}
- owner.AsmWrite('@GOT');
+ owner.AsmWrite('@GOT');
{$endif x86_64}
+ end;
if offset<0 then
owner.AsmWrite(tostr(offset))
else
@@ -469,7 +470,8 @@ interface
asmcmd : '--64 -o $OBJ $EXTRAOPT $ASM';
supported_targets : [system_x86_64_linux,system_x86_64_freebsd,
system_x86_64_win64,system_x86_64_embedded,
- system_x86_64_openbsd,system_x86_64_netbsd];
+ system_x86_64_openbsd,system_x86_64_netbsd,
+ system_x86_64_dragonfly];
flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
labelprefix : '.L';
comment : '# ';
@@ -527,7 +529,7 @@ interface
supported_targets : [system_i386_GO32V2,system_i386_linux,system_i386_Win32,system_i386_freebsd,system_i386_solaris,system_i386_beos,
system_i386_netbsd,system_i386_Netware,system_i386_qnx,system_i386_wdosx,system_i386_openbsd,
system_i386_netwlibc,system_i386_wince,system_i386_embedded,system_i386_symbian,system_i386_haiku,system_x86_6432_linux,
- system_i386_nativent,system_i386_android];
+ system_i386_nativent,system_i386_android,system_i386_aros];
flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
labelprefix : '.L';
comment : '# ';
diff --git a/compiler/x86/agx86nsm.pas b/compiler/x86/agx86nsm.pas
index ed02093c58..1deaba8e28 100644
--- a/compiler/x86/agx86nsm.pas
+++ b/compiler/x86/agx86nsm.pas
@@ -1302,6 +1302,8 @@ interface
case target_info.system of
system_i8086_msdos:
FormatName:='obj';
+ else
+ internalerror(2014082060);
end;
{$endif i8086}
{$ifdef i386}
diff --git a/compiler/x86/nx86add.pas b/compiler/x86/nx86add.pas
index 1f147bec76..1c57544131 100644
--- a/compiler/x86/nx86add.pas
+++ b/compiler/x86/nx86add.pas
@@ -47,6 +47,7 @@ unit nx86add;
procedure second_addfloatsse;
procedure second_addfloatavx;
public
+ function use_fma : boolean;override;
procedure second_addfloat;override;
{$ifndef i8086}
procedure second_addsmallset;override;
@@ -273,6 +274,15 @@ unit nx86add;
procedure tx86addnode.prepare_x87_locations(out refnode: tnode);
begin
refnode:=nil;
+
+ { later on, no mm registers are allowed, so transfer everything to memory here
+ below it is loaded into an fpu register if neede }
+ if left.location.loc in [LOC_CMMREGISTER,LOC_MMREGISTER] then
+ hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
+
+ if right.location.loc in [LOC_CMMREGISTER,LOC_MMREGISTER] then
+ hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
+
case ord(left.location.loc=LOC_FPUREGISTER)+ord(right.location.loc=LOC_FPUREGISTER) of
0:
begin
@@ -603,6 +613,8 @@ unit nx86add;
pass_left_right;
cmpop:=false;
+ op:=A_NOP;
+
mmxbase:=mmx_type(left.resultdef);
location_reset(location,LOC_MMXREGISTER,def_cgsize(resultdef));
case nodetype of
@@ -679,6 +691,9 @@ unit nx86add;
internalerror(2003042214);
end;
+ if op = A_NOP then
+ internalerror(201408201);
+
{ left and right no register? }
{ then one must be demanded }
if (left.location.loc<>LOC_MMXREGISTER) then
@@ -1072,6 +1087,18 @@ unit nx86add;
end;
+ function tx86addnode.use_fma : boolean;
+ begin
+{$ifndef i8086}
+ { test if the result stays in an xmm register, fiddeling with fpu registers and fma makes no sense }
+ Result:=use_vectorfpu(resultdef) and
+ ((cpu_capabilities[current_settings.cputype]*[CPUX86_HAS_FMA,CPUX86_HAS_FMA4])<>[]);
+{$else i8086}
+ Result:=inherited use_fma;
+{$endif i8086}
+ end;
+
+
procedure tx86addnode.second_cmpfloatvector;
var
op : tasmop;
diff --git a/compiler/x86/nx86mat.pas b/compiler/x86/nx86mat.pas
index d056f364bf..5d41b57650 100644
--- a/compiler/x86/nx86mat.pas
+++ b/compiler/x86/nx86mat.pas
@@ -99,6 +99,7 @@ interface
op : tasmop;
hreg : tregister;
begin
+ op:=A_NONE;
secondpass(left);
location_reset(location,LOC_MMXREGISTER,OS_NO);
hreg:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
@@ -142,6 +143,9 @@ interface
mmxs32bit,mmxu32bit:
op:=A_PSUBD;
end;
+ if op = A_NONE then
+ internalerror(201408202);
+
emit_reg_reg(op,S_NO,location.register,hreg);
emit_reg_reg(A_MOVQ,S_NO,hreg,location.register);
end;
@@ -523,8 +527,8 @@ interface
else
emit_reg_reg(A_XOR,opsize,regd,regd);
- {Division depends on the right type.}
- if is_signed(right.resultdef) then
+ { Division depends on the result type }
+ if is_signed(resultdef) then
op:=A_IDIV
else
op:=A_DIV;
diff --git a/compiler/x86/rax86.pas b/compiler/x86/rax86.pas
index 391ed7ad05..e3b91a0ac0 100644
--- a/compiler/x86/rax86.pas
+++ b/compiler/x86/rax86.pas
@@ -47,8 +47,9 @@ type
Function CheckOperand: boolean; override;
end;
+ { Operands are always in AT&T order.
+ Intel reader attaches them right-to-left, then shifts to start with 1 }
Tx86Instruction=class(TInstruction)
- OpOrder : TOperandOrder;
opsize : topsize;
constructor Create(optype : tcoperand);override;
{ Operand sizes }
@@ -56,7 +57,6 @@ type
procedure SetInstructionOpsize;
procedure CheckOperandSizes;
procedure CheckNonCommutativeOpcodes;
- procedure SwapOperands;
{ Additional actions required by specific reader }
procedure FixupOpcode;virtual;
{ opcode adding }
@@ -295,16 +295,6 @@ begin
end;
-procedure Tx86Instruction.SwapOperands;
-begin
- Inherited SwapOperands;
- { mark the correct order }
- if OpOrder=op_intel then
- OpOrder:=op_att
- else
- OpOrder:=op_intel;
-end;
-
const
{$ifdef x86_64}
topsize2memsize: array[topsize] of integer =
@@ -437,7 +427,11 @@ begin
memopsize := 0;
case operands[i].opr.typ of
OPR_LOCAL: memopsize := operands[i].opr.localvarsize * 8;
- OPR_REFERENCE: memopsize := operands[i].opr.varsize * 8;
+ OPR_REFERENCE:
+ if operands[i].opr.ref.refaddr = addr_pic then
+ memopsize := sizeof(pint) * 8
+ else
+ memopsize := operands[i].opr.varsize * 8;
end;
if memopsize = 0 then memopsize := topsize2memsize[tx86operand(operands[i]).opsize];
@@ -800,8 +794,6 @@ procedure Tx86Instruction.SetInstructionOpsize;
begin
if opsize<>S_NO then
exit;
- if (OpOrder=op_intel) then
- SwapOperands;
case ops of
0 : ;
1 :
@@ -937,8 +929,6 @@ end;
but before swapping in the NASM and TASM writers PM }
procedure Tx86Instruction.CheckNonCommutativeOpcodes;
begin
- if (OpOrder=op_intel) then
- SwapOperands;
if (
(ops=2) and
(operands[1].opr.typ=OPR_REGISTER) and
@@ -998,8 +988,6 @@ var
ai : taicpu;
begin
ConcatInstruction:=nil;
- if (OpOrder=op_intel) then
- SwapOperands;
ai:=nil;
for i:=1 to Ops do
@@ -1160,7 +1148,7 @@ begin
ai:=taicpu.op_none(opcode,siz);
ai.fileinfo:=filepos;
- ai.SetOperandOrder(OpOrder);
+ ai.SetOperandOrder(op_att);
ai.Ops:=Ops;
ai.Allocate_oper(Ops);
for i:=1 to Ops do
diff --git a/compiler/x86/rax86att.pas b/compiler/x86/rax86att.pas
index b13c587dde..85f60629e0 100644
--- a/compiler/x86/rax86att.pas
+++ b/compiler/x86/rax86att.pas
@@ -98,9 +98,6 @@ Implementation
procedure Tx86attInstruction.FixupOpcode;
begin
- if (OpOrder=op_intel) then
- SwapOperands;
-
case opcode of
A_MOVQ:
begin
@@ -973,7 +970,6 @@ Implementation
instr : Tx86Instruction;
begin
instr:=Tx86attInstruction.Create(Tx86Operand);
- instr.OpOrder:=op_att;
BuildOpcode(instr);
instr.AddReferenceSizes;
instr.SetInstructionOpsize;
diff --git a/compiler/x86/rax86int.pas b/compiler/x86/rax86int.pas
index ab39284882..9e2080659e 100644
--- a/compiler/x86/rax86int.pas
+++ b/compiler/x86/rax86int.pas
@@ -65,7 +65,7 @@ Unit Rax86int;
procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean);
procedure BuildConstSymbolExpression(needofs,isref,startingminus:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
function BuildConstExpression:aint;
- function BuildRefConstExpression:aint;
+ function BuildRefConstExpression(startingminus:boolean=false):aint;
procedure BuildReference(oper : tx86operand);
procedure BuildOperand(oper: tx86operand;istypecast:boolean);
procedure BuildConstantOperand(oper: tx86operand);
@@ -1141,13 +1141,13 @@ Unit Rax86int;
end;
- Function tx86intreader.BuildRefConstExpression:aint;
+ Function tx86intreader.BuildRefConstExpression(startingminus:boolean):aint;
var
l : aint;
hs : string;
hssymtyp : TAsmsymtype;
begin
- BuildConstSymbolExpression(false,true,false,l,hs,hssymtyp);
+ BuildConstSymbolExpression(false,true,startingminus,l,hs,hssymtyp);
if hs<>'' then
Message(asmr_e_relocatable_symbol_not_allowed);
BuildRefConstExpression:=l;
@@ -1190,7 +1190,8 @@ Unit Rax86int;
(SearchIConstant(actasmpattern,l) or
SearchRecordType(actasmpattern)) then
begin
- l:=BuildRefConstExpression;
+ l:=BuildRefConstExpression(negative);
+ negative:=false; { "l" was negated if necessary }
GotPlus:=(prevasmtoken=AS_PLUS);
GotStar:=(prevasmtoken=AS_STAR);
case oper.opr.typ of
@@ -1198,23 +1199,15 @@ Unit Rax86int;
begin
if GotStar then
Message(asmr_e_invalid_reference_syntax);
- if negative then
- Dec(oper.opr.localsymofs,l)
- else
- Inc(oper.opr.localsymofs,l);
+ Inc(oper.opr.localsymofs,l);
end;
OPR_REFERENCE :
begin
if GotStar then
oper.opr.ref.scalefactor:=l
else
- begin
- if negative then
- Dec(oper.opr.ref.offset,l)
- else
- Inc(oper.opr.ref.offset,l);
- end;
- end;
+ Inc(oper.opr.ref.offset,l);
+ end;
end;
end
else
@@ -1427,6 +1420,11 @@ Unit Rax86int;
begin
if (oper.opr.localindexreg<>NR_NO) then
Message(asmr_e_multiple_index);
+{$ifdef x86_64}
+ { Locals/parameters cannot be accessed RIP-relative. Need a dedicated error message here? }
+ if (hreg=NR_RIP) then
+ Message(asmr_e_no_local_or_para_allowed);
+{$endif x86_64}
oper.opr.localindexreg:=hreg;
if scale<>0 then
begin
@@ -1980,6 +1978,7 @@ Unit Rax86int;
operandnum : longint;
is_far_const:boolean;
i:byte;
+ tmp: toperand;
begin
PrefixOp:=A_None;
OverrideOp:=A_None;
@@ -1989,7 +1988,6 @@ Unit Rax86int;
if is_prefix(actopcode) then
with instr do
begin
- OpOrder:=op_intel;
PrefixOp:=ActOpcode;
opcode:=ActOpcode;
condition:=ActCondition;
@@ -2001,7 +1999,6 @@ Unit Rax86int;
if is_override(actopcode) then
with instr do
begin
- OpOrder:=op_intel;
OverrideOp:=ActOpcode;
opcode:=ActOpcode;
condition:=ActCondition;
@@ -2025,7 +2022,6 @@ Unit Rax86int;
{ Fill the instr object with the current state }
with instr do
begin
- OpOrder:=op_intel;
Opcode:=ActOpcode;
condition:=ActCondition;
opsize:=ActOpsize;
@@ -2052,15 +2048,13 @@ Unit Rax86int;
{$endif x86_64}
;
{ We are reading operands, so opcode will be an AS_ID }
- operandnum:=1;
+ { process operands backwards to get them in AT&T order }
+ operandnum:=max_operands;
is_far_const:=false;
Consume(AS_OPCODE);
{ Zero operand opcode ? }
if actasmtoken in [AS_SEPARATOR,AS_END] then
- begin
- operandnum:=0;
- exit;
- end;
+ exit;
{ Read Operands }
repeat
case actasmtoken of
@@ -2072,10 +2066,13 @@ Unit Rax86int;
{ Operand delimiter }
AS_COMMA :
begin
- if operandnum > Max_Operands then
+ { should have something before the comma }
+ if instr.operands[operandnum].opr.typ=OPR_NONE then
+ Message(asmr_e_syntax_error);
+ if operandnum <= 1 then
Message(asmr_e_too_many_operands)
else
- Inc(operandnum);
+ Dec(operandnum);
Consume(AS_COMMA);
end;
@@ -2083,10 +2080,10 @@ Unit Rax86int;
AS_COLON:
begin
is_far_const:=true;
- if operandnum>1 then
+ if operandnum<max_operands then
message(asmr_e_too_many_operands)
else
- inc(operandnum);
+ dec(operandnum);
consume(AS_COLON);
end;
@@ -2116,6 +2113,15 @@ Unit Rax86int;
BuildOperand(instr.Operands[operandnum] as tx86operand,false);
end; { end case }
until false;
+
+ { shift operands to start from 1, exchange to make sure they are destroyed correctly }
+ for i:=operandnum to max_operands do
+ begin
+ tmp:=instr.operands[i+1-operandnum];
+ instr.operands[i+1-operandnum]:=instr.operands[i];
+ instr.operands[i]:=tmp;
+ end;
+ operandnum:=(max_operands+1)-operandnum;
instr.ops:=operandnum;
{ Check operands }
for i:=1 to operandnum do
@@ -2303,9 +2309,6 @@ Unit Rax86int;
BuildOpcode(instr);
with instr do
begin
- { We need AT&T style operands }
- Swapoperands;
- { Must be done with args in ATT order }
CheckNonCommutativeOpcodes;
AddReferenceSizes;
SetInstructionOpsize;
diff --git a/compiler/x86/symx86.pas b/compiler/x86/symx86.pas
index 45c93a8cd3..500e4443c7 100644
--- a/compiler/x86/symx86.pas
+++ b/compiler/x86/symx86.pas
@@ -26,7 +26,7 @@ unit symx86;
interface
uses
- globtype,
+ globtype, cclasses,
symconst, symtype,symdef,symsym;
type
@@ -45,10 +45,62 @@ type
end;
tx86pointerdefclass = class of tx86pointerdef;
+ tx86PtrDefKey = packed record
+ def: tdef;
+ x86typ:tx86pointertyp;
+ end;
+
+ { tx86PtrDefHashSet }
+
+ tx86PtrDefHashSet = class(TPtrDefHashSet)
+ private
+ class procedure Key2FullKey(Key: Pointer; out FullKey: tx86PtrDefKey);
+ public
+ function Find(Key: Pointer; KeyLen: Integer): PHashSetItem;override;
+ function FindOrAdd(Key: Pointer; KeyLen: Integer;
+ var Found: Boolean): PHashSetItem;override;
+ function FindOrAdd(Key: Pointer; KeyLen: Integer): PHashSetItem;override;
+ function Get(Key: Pointer; KeyLen: Integer): TObject;override;
+ end;
+
+ { returns a pointerdef for def, reusing an existing one in case it exists
+ in the current module }
+ function getx86pointerdef(def: tdef;x86typ:tx86pointertyp): tpointerdef;
+
implementation
uses
- globals, verbose;
+ globals, verbose,
+ symbase, fmodule;
+
+ function getx86pointerdef(def: tdef;x86typ:tx86pointertyp): tpointerdef;
+ var
+ res: PHashSetItem;
+ oldsymtablestack: tsymtablestack;
+ key: tx86PtrDefKey;
+ begin
+ if not assigned(current_module) then
+ internalerror(2011071101);
+ key.def:=def;
+ key.x86typ:=x86typ;
+ res:=current_module.ptrdefs.FindOrAdd(@key,sizeof(key));
+ if not assigned(res^.Data) then
+ begin
+ { since these pointerdefs can be reused anywhere in the current
+ unit, add them to the global/staticsymtable }
+ oldsymtablestack:=symtablestack;
+ { do not simply push/pop current_module.localsymtable, because
+ that can have side-effects (e.g., it removes helpers) }
+ symtablestack:=nil;
+ res^.Data:=tx86pointerdefclass(cpointerdef).createx86(def,x86typ);
+ if assigned(current_module.localsymtable) then
+ current_module.localsymtable.insertdef(tdef(res^.Data))
+ else
+ current_module.globalsymtable.insertdef(tdef(res^.Data));
+ symtablestack:=oldsymtablestack;
+ end;
+ result:=tpointerdef(res^.Data);
+ end;
{****************************************************************************
tx86pointerdef
@@ -136,5 +188,69 @@ implementation
end;
+{****************************************************************************
+ tx86PtrDefHashSet
+****************************************************************************}
+
+ class procedure tx86PtrDefHashSet.Key2FullKey(Key: Pointer; out FullKey: tx86PtrDefKey);
+ type
+ pdef=^tdef;
+ begin
+ FullKey.def:=pdef(Key)^;
+ FullKey.x86typ:=tx86pointerdefclass(cpointerdef).default_x86_data_pointer_type;
+ end;
+
+ function tx86PtrDefHashSet.Find(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ var
+ FullKey: tx86PtrDefKey;
+ begin
+ if KeyLen=SizeOf(tdef) then
+ begin
+ Key2FullKey(Key, FullKey);
+ Result:=inherited Find(@FullKey, SizeOf(FullKey));
+ end
+ else
+ Result:=inherited Find(Key, KeyLen);
+ end;
+
+ function tx86PtrDefHashSet.FindOrAdd(Key: Pointer; KeyLen: Integer; var Found: Boolean): PHashSetItem;
+ var
+ FullKey: tx86PtrDefKey;
+ begin
+ if KeyLen=SizeOf(tdef) then
+ begin
+ Key2FullKey(Key, FullKey);
+ Result:=inherited FindOrAdd(@FullKey, SizeOf(FullKey), Found);
+ end
+ else
+ Result:=inherited FindOrAdd(Key, KeyLen, Found);
+ end;
+
+ function tx86PtrDefHashSet.FindOrAdd(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ var
+ FullKey: tx86PtrDefKey;
+ begin
+ if KeyLen=SizeOf(tdef) then
+ begin
+ Key2FullKey(Key, FullKey);
+ Result:=inherited FindOrAdd(@FullKey, SizeOf(FullKey));
+ end
+ else
+ Result:=inherited FindOrAdd(Key, KeyLen);
+ end;
+
+ function tx86PtrDefHashSet.Get(Key: Pointer; KeyLen: Integer): TObject;
+ var
+ FullKey: tx86PtrDefKey;
+ begin
+ if KeyLen=SizeOf(tdef) then
+ begin
+ Key2FullKey(Key, FullKey);
+ Result:=inherited Get(@FullKey, SizeOf(FullKey));
+ end
+ else
+ Result:=inherited Get(Key, KeyLen);
+ end;
+
end.