diff options
Diffstat (limited to 'compiler/x86')
-rw-r--r-- | compiler/x86/aasmcpu.pas | 197 | ||||
-rw-r--r-- | compiler/x86/agx86att.pas | 24 | ||||
-rw-r--r-- | compiler/x86/agx86nsm.pas | 2 | ||||
-rw-r--r-- | compiler/x86/nx86add.pas | 27 | ||||
-rw-r--r-- | compiler/x86/nx86mat.pas | 8 | ||||
-rw-r--r-- | compiler/x86/rax86.pas | 28 | ||||
-rw-r--r-- | compiler/x86/rax86att.pas | 4 | ||||
-rw-r--r-- | compiler/x86/rax86int.pas | 63 | ||||
-rw-r--r-- | compiler/x86/symx86.pas | 120 |
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. |