diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas index 288d0cfc9a..8de6843603 100644 --- a/compiler/arm/aasmcpu.pas +++ b/compiler/arm/aasmcpu.pas @@ -93,6 +93,7 @@ uses OT_REG64 = $00201008; OT_VREG = $00201010; { vector register } OT_REGF = $00201020; { coproc register } + OT_REGS = $00201040; { special register with mask } OT_MEMORY = $00204000; { register number in 'basereg' } OT_MEM8 = $00204001; OT_MEM16 = $00204002; @@ -1453,10 +1454,6 @@ implementation procedure gather_it_info(list: TAsmList); - const - opCount: array[A_IT..A_ITTTT] of longint = - (1,2,2,3,3,3,3, - 4,4,4,4,4,4,4,4); var curtai: tai; in_it: boolean; @@ -1479,7 +1476,7 @@ implementation else begin in_it:=true; - it_count:=opCount[taicpu(curtai).opcode]; + it_count:=GetITLevels(taicpu(curtai).opcode); end; end; else @@ -1502,8 +1499,51 @@ implementation end; end; + + { Expands pseudo instructions ( mov r1,r2,lsl #4 -> lsl r1,r2,#4) } + procedure expand_instructions(list: TAsmList); + var + curtai: tai; + begin + curtai:=tai(list.First); + while assigned(curtai) do + begin + case curtai.typ of + ait_instruction: + begin + case taicpu(curtai).opcode of + A_MOV: + begin + if (taicpu(curtai).ops=3) and + (taicpu(curtai).oper[2]^.typ=top_shifterop) then + begin + case taicpu(curtai).oper[2]^.shifterop^.shiftmode of + SM_LSL: taicpu(curtai).opcode:=A_LSL; + SM_LSR: taicpu(curtai).opcode:=A_LSR; + SM_ASR: taicpu(curtai).opcode:=A_ASR; + SM_ROR: taicpu(curtai).opcode:=A_ROR; + SM_RRX: taicpu(curtai).opcode:=A_RRX; + end; + + if taicpu(curtai).oper[2]^.shifterop^.rs=NR_NO then + taicpu(curtai).loadconst(2, taicpu(curtai).oper[2]^.shifterop^.shiftimm) + else + taicpu(curtai).loadreg(2, taicpu(curtai).oper[2]^.shifterop^.rs); + end; + end; + end; + end; + end; + + curtai:=tai(curtai.Next); + end; + end; + + procedure finalizearmcode(list, listtoinsert: TAsmList); begin + expand_instructions(list); + { Do Thumb-2 16bit -> 32bit transformations } if GenerateThumb2Code then begin @@ -1712,6 +1752,9 @@ implementation else if (ot and OT_FPUREG)=OT_FPUREG then s:=s+'fpureg' + else + if (ot and OT_REGS)=OT_REGS then + s:=s+'sreg' else if (ot and OT_REGF)=OT_REGF then s:=s+'creg' @@ -2109,6 +2152,10 @@ implementation begin ot:=OT_CONDITION; end; + top_specialreg: + begin + ot:=OT_REGS; + end; else begin writeln(typ); internalerror(200402261); end; @@ -2166,10 +2213,10 @@ implementation end; { Check wideformat flag } - if ((p^.flags and IF_WIDE)<>0) <> wideformat then + if wideformat and ((p^.flags and IF_WIDE)=0) then begin - {matches:=0; - exit;} + matches:=0; + exit; end; { Check that no spurious colons or TOs are present } @@ -4079,14 +4126,27 @@ implementation if oper[0]^.typ=top_const then begin if insentry^.code[0]=#$63 then - bytes:=bytes or ((oper[0]^.val shr 1) and $FF) + bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF) else - bytes:=bytes or ((oper[0]^.val shr 1) and $3FF); + bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF); end else if oper[0]^.typ=top_reg then begin bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3); - end; + end + else if oper[0]^.typ=top_ref then + begin + offset:=0; + currsym:=objdata.symbolref(oper[0]^.ref^.symbol); + if assigned(currsym) then + offset:=currsym.offset-insoffset-8; + offset:=offset+oper[0]^.ref^.offset; + + if insentry^.code[0]=#$63 then + bytes:=bytes or (((offset+4) shr 1) and $FF) + else + bytes:=bytes or (((offset+4) shr 1) and $7FF); + end end; #$64: { Thumb: Special encodings } begin @@ -4171,7 +4231,7 @@ implementation else bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF); end; - #$68: { Thumb CB{N}Z } + #$68: { Thumb CB[N]Z } begin bytelen:=2; bytes:=0; diff --git a/compiler/arm/armins.dat b/compiler/arm/armins.dat index 51f9ed98f8..944bd87ccc 100644 --- a/compiler/arm/armins.dat +++ b/compiler/arm/armins.dat @@ -145,11 +145,11 @@ reg32,reg32,reg32,shifterop \x6\x0\x00 ARM32,ARMv4 reg32,reg32,immshifter \x7\x2\x00 ARM32,ARMv4 [Bcc] -imm32 \x62\xE0\x0 THUMB,ARMv4T +imm24 \x62\xE0\x0 THUMB,ARMv4T immshifter \x62\xE0\x0 THUMB,ARMv4T mem32 \x62\xE0\x0 THUMB,ARMv4T -imm32 \x63\xD0\x0 THUMB,ARMv4T +imm24 \x63\xD0\x0 THUMB,ARMv4T immshifter \x63\xD0\x0 THUMB,ARMv4T mem32 \x63\xD0\x0 THUMB,ARMv4T @@ -361,6 +361,7 @@ reg32,regf \x10\x01\x0F ARM32,ARMv4 [MSRcc] regf,reg32 \x12\x01\x28\xF0 ARM32,ARMv4 regf,immshifter \x13\x03\x28\xF0 ARM32,ARMv4 +regs,immshifter \x13\x03\x28\xF0 ARM32,ARMv4 [MULcc] reglo,reglo,reglo \x64\x43\x40 THUMB,ARMv4T @@ -396,6 +397,8 @@ vreg,reg32,reg32 \x40\xC\x40\xB\x10 ARM32,VFPv2 [NOP] void \x61\xBF\x0 THUMB,ARMv6T2 void \x2F\x03\x20\xF0\x0 ARM32,ARMv6K +; Before ARMv6K use mov r0,r0 +void \x2F\xE1\xA0\x0\x0 ARM32,ARMv4 [ORNcc] reg32,reg32,immshifter \x80\xF0\x60\x0\x0 THUMB32,ARMv6T2 diff --git a/compiler/arm/armnop.inc b/compiler/arm/armnop.inc index 749cd5282d..4dc48ed102 100644 --- a/compiler/arm/armnop.inc +++ b/compiler/arm/armnop.inc @@ -1,2 +1,2 @@ { don't edit, this file is generated from armins.dat } -651; +653; diff --git a/compiler/arm/armtab.inc b/compiler/arm/armtab.inc index aba97de2c0..f881eef7ed 100644 --- a/compiler/arm/armtab.inc +++ b/compiler/arm/armtab.inc @@ -255,7 +255,7 @@ ( opcode : A_B; ops : 1; - optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none); + optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none); code : #98#224#0; flags : if_thumb or if_armv4t ), @@ -276,7 +276,7 @@ ( opcode : A_B; ops : 1; - optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none); + optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none); code : #99#208#0; flags : if_thumb or if_armv4t ), @@ -1085,6 +1085,13 @@ code : #19#3#40#240; flags : if_arm32 or if_armv4 ), + ( + opcode : A_MSR; + ops : 2; + optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none); + code : #19#3#40#240; + flags : if_arm32 or if_armv4 + ), ( opcode : A_MUL; ops : 3; @@ -1225,6 +1232,13 @@ code : #47#3#32#240#0; flags : if_arm32 or if_armv6k ), + ( + opcode : A_NOP; + ops : 0; + optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none); + code : #47#225#160#0#0; + flags : if_arm32 or if_armv4 + ), ( opcode : A_ORN; ops : 3; diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas index 42baec5360..f19782fb0b 100644 --- a/compiler/arm/cpubase.pas +++ b/compiler/arm/cpubase.pas @@ -591,7 +591,6 @@ unit cpubase; var t : aint; i : longint; - imm : byte; begin {Loading 0-255 is simple} if (d and $FF) = d then @@ -611,7 +610,7 @@ unit cpubase; result:=false; for i:=1 to 31 do begin - t:=RolDWord(imm,i); + t:=RolDWord(d,i); if ((t and $FF)=t) and ((t and $80)=$80) then begin diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas index 68d3ab124b..5489456fe3 100644 --- a/compiler/ogbase.pas +++ b/compiler/ogbase.pas @@ -172,6 +172,10 @@ interface { Darwin asm is using indirect symbols resolving } indsymbol : TObjSymbol; +{$ifdef ARM} + ThumbFunc : boolean; +{$endif ARM} + constructor create(AList:TFPHashObjectList;const AName:string); function address:aword; procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype); @@ -233,9 +237,6 @@ interface ExeSection : TExeSection; USed : Boolean; VTRefList : TFPObjectList; -{$ifdef ARM} - ThumbFunc : boolean; -{$endif ARM} constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual; destructor destroy;override; function write(const d;l:aword):aword; @@ -1140,10 +1141,6 @@ implementation begin result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions); result.ObjData:=self; -{$ifdef ARM} - result.ThumbFunc:=ThumbFunc; - ThumbFunc:=false; -{$endif ARM} end; FCurrObjSec:=result; end; @@ -1181,6 +1178,11 @@ implementation result:=TObjSymbol(FObjSymbolList.Find(aname)); if not assigned(result) then result:=TObjSymbol.Create(FObjSymbolList,aname); + +{$ifdef ARM} + result.ThumbFunc:=ThumbFunc; + ThumbFunc:=false; +{$endif ARM} end; diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index ac22caed65..938b79899e 100644 --- a/compiler/ogelf.pas +++ b/compiler/ogelf.pas @@ -970,8 +970,7 @@ implementation elfsym.st_value:=objsym.address; {$ifdef ARM} - if (objsym.typ=AT_FUNCTION) and - objsym.objsection.ThumbFunc then + if objsym.ThumbFunc then inc(elfsym.st_value); {$endif ARM} diff --git a/rtl/arm/arm.inc b/rtl/arm/arm.inc index ebcb3bbc4f..9dccb0eb12 100644 --- a/rtl/arm/arm.inc +++ b/rtl/arm/arm.inc @@ -15,7 +15,7 @@ **********************************************************************} -{$asmmode gas} +{$asmmode divided} {$ifndef FPC_SYSTEM_HAS_MOVE} {$define FPC_SYSTEM_FPC_MOVE} diff --git a/rtl/arm/thumb2.inc b/rtl/arm/thumb2.inc index 921ae24345..248744d8c0 100644 --- a/rtl/arm/thumb2.inc +++ b/rtl/arm/thumb2.inc @@ -15,7 +15,7 @@ **********************************************************************} -{$asmmode gas} +{$asmmode divided} {$ifndef FPC_SYSTEM_HAS_MOVE} {$define FPC_SYSTEM_FPC_MOVE}