mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-15 10:29:29 +02:00
+ support for vmov.xx vreg,#imm on arm
git-svn-id: trunk@39297 -
This commit is contained in:
parent
ec7a3a023e
commit
4f5f3c4a09
@ -232,6 +232,7 @@ interface
|
||||
{$if defined(arm) or defined(aarch64)}
|
||||
,top_conditioncode
|
||||
,top_shifterop
|
||||
,top_realconst
|
||||
{$endif defined(arm) or defined(aarch64)}
|
||||
{$ifdef m68k}
|
||||
{ m68k only }
|
||||
@ -435,6 +436,7 @@ interface
|
||||
{$if defined(arm) or defined(aarch64)}
|
||||
top_shifterop : (shifterop : pshifterop);
|
||||
top_conditioncode : (cc : TAsmCond);
|
||||
top_realconst : (val_real:bestreal);
|
||||
{$endif defined(arm) or defined(aarch64)}
|
||||
{$ifdef m68k}
|
||||
top_regset : (dataregset,addrregset,fpuregset: tcpuregisterset);
|
||||
|
@ -76,6 +76,7 @@ uses
|
||||
OT_IMMTINY = $00002100;
|
||||
OT_IMMSHIFTER= $00002200;
|
||||
OT_IMMEDIATEZERO = $10002200;
|
||||
OT_IMMEDIATEMM = $00002400;
|
||||
OT_IMMEDIATE24 = OT_IMM24;
|
||||
OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
|
||||
OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
|
||||
@ -200,6 +201,8 @@ uses
|
||||
procedure loadconditioncode(opidx:longint;const cond:tasmcond);
|
||||
procedure loadmodeflags(opidx:longint;const flags:tcpumodeflags);
|
||||
procedure loadspecialreg(opidx:longint;const areg:tregister; const aflags:tspecialregflags);
|
||||
procedure loadrealconst(opidx:longint;const _value:bestreal);
|
||||
|
||||
constructor op_none(op : tasmop);
|
||||
|
||||
constructor op_reg(op : tasmop;_op1 : tregister);
|
||||
@ -237,6 +240,8 @@ uses
|
||||
{ *M*LL }
|
||||
constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
|
||||
|
||||
constructor op_reg_realconst(op : tasmop;_op1: tregister;_op2: bestreal);
|
||||
|
||||
{ this is for Jmp instructions }
|
||||
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
|
||||
|
||||
@ -332,6 +337,19 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure taicpu.loadrealconst(opidx:longint;const _value:bestreal);
|
||||
begin
|
||||
allocate_oper(opidx+1);
|
||||
with oper[opidx]^ do
|
||||
begin
|
||||
if typ<>top_realconst then
|
||||
clearop(opidx);
|
||||
val_real:=_value;
|
||||
typ:=top_realconst;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure taicpu.loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset; ausermode: boolean);
|
||||
var
|
||||
i : byte;
|
||||
@ -504,6 +522,15 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg_realconst(op : tasmop; _op1 : tregister; _op2 : bestreal);
|
||||
begin
|
||||
inherited create(op);
|
||||
ops:=2;
|
||||
loadreg(0,_op1);
|
||||
loadrealconst(1,_op2);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
|
||||
begin
|
||||
inherited create(op);
|
||||
@ -2363,6 +2390,10 @@ implementation
|
||||
begin
|
||||
ot:=OT_MODEFLAGS;
|
||||
end;
|
||||
top_realconst:
|
||||
begin
|
||||
ot:=OT_IMMEDIATEMM;
|
||||
end;
|
||||
else
|
||||
internalerror(2004022623);
|
||||
end;
|
||||
@ -2719,6 +2750,8 @@ implementation
|
||||
refoper : poper;
|
||||
msb : longint;
|
||||
r: byte;
|
||||
singlerec : tcompsinglerec;
|
||||
doublerec : tcompdoublerec;
|
||||
|
||||
procedure setshifterop(op : byte);
|
||||
var
|
||||
@ -3881,35 +3914,73 @@ implementation
|
||||
end;
|
||||
PF_F32:
|
||||
begin
|
||||
if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
|
||||
(getregtype(oper[1]^.reg)<>R_MMREGISTER) then
|
||||
if (getregtype(oper[0]^.reg)<>R_MMREGISTER) then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
|
||||
case oper[1]^.typ of
|
||||
top_realconst:
|
||||
begin
|
||||
if not(IsVFPFloatImmediate(s32real,oper[1]^.val_real)) then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
singlerec.value:=oper[1]^.val_real;
|
||||
singlerec:=tcompsinglerec(NtoLE(DWord(singlerec)));
|
||||
|
||||
bytes:=bytes or ((singlerec.bytes[2] shr 3) and $f);
|
||||
bytes:=bytes or (DWord((singlerec.bytes[2] shr 7) and $1) shl 16) or (DWord(singlerec.bytes[3] and $3) shl 17) or (DWord((singlerec.bytes[3] shr 7) and $1) shl 19);
|
||||
end;
|
||||
top_reg:
|
||||
begin
|
||||
if getregtype(oper[1]^.reg)<>R_MMREGISTER then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
Rm:=getmmreg(oper[1]^.reg);
|
||||
bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
|
||||
bytes:=bytes or ((Rm and $1) shl 5);
|
||||
end;
|
||||
else
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
end;
|
||||
Rd:=getmmreg(oper[0]^.reg);
|
||||
Rm:=getmmreg(oper[1]^.reg);
|
||||
|
||||
bytes:=bytes or (((Rd and $1E) shr 1) shl 12);
|
||||
bytes:=bytes or ((Rd and $1) shl 22);
|
||||
|
||||
bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
|
||||
bytes:=bytes or ((Rm and $1) shl 5);
|
||||
end;
|
||||
PF_F64:
|
||||
begin
|
||||
if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
|
||||
(getregtype(oper[1]^.reg)<>R_MMREGISTER) then
|
||||
if (getregtype(oper[0]^.reg)<>R_MMREGISTER) then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
|
||||
case oper[1]^.typ of
|
||||
top_realconst:
|
||||
begin
|
||||
if not(IsVFPFloatImmediate(s64real,oper[1]^.val_real)) then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
doublerec.value:=oper[1]^.val_real;
|
||||
doublerec:=tcompdoublerec(NtoLE(QWord(doublerec)));
|
||||
|
||||
// 32c: eeb41b00 vmov.f64 d1, #64 ; 0x40
|
||||
|
||||
// 32c: eeb61b00 vmov.f64 d1, #96 ; 0x60
|
||||
bytes:=bytes or (doublerec.bytes[6] and $f);
|
||||
bytes:=bytes or (DWord((doublerec.bytes[6] shr 4) and $7) shl 16) or (DWord((doublerec.bytes[7] shr 7) and $1) shl 19);
|
||||
end;
|
||||
top_reg:
|
||||
begin
|
||||
if getregtype(oper[1]^.reg)<>R_MMREGISTER then
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
Rm:=getmmreg(oper[1]^.reg);
|
||||
bytes:=bytes or (Rm and $F);
|
||||
bytes:=bytes or ((Rm and $10) shl 1);
|
||||
end;
|
||||
else
|
||||
Message(asmw_e_invalid_opcode_and_operands);
|
||||
end;
|
||||
Rd:=getmmreg(oper[0]^.reg);
|
||||
Rm:=getmmreg(oper[1]^.reg);
|
||||
|
||||
bytes:=bytes or (1 shl 8);
|
||||
|
||||
bytes:=bytes or ((Rd and $F) shl 12);
|
||||
bytes:=bytes or (((Rd and $10) shr 4) shl 22);
|
||||
|
||||
bytes:=bytes or (Rm and $F);
|
||||
bytes:=bytes or ((Rm and $10) shl 1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -318,6 +318,11 @@ unit agarmgas;
|
||||
if srF in o.specialflags then getopstr:=getopstr+'f';
|
||||
if srS in o.specialflags then getopstr:=getopstr+'s';
|
||||
end;
|
||||
end;
|
||||
top_realconst:
|
||||
begin
|
||||
str(o.val_real,Result);
|
||||
Result:='#'+Result;
|
||||
end
|
||||
else
|
||||
internalerror(2002070604);
|
||||
|
@ -428,7 +428,9 @@ reg32,immshifter \xB\x1\xE0 ARM32,ARMv4
|
||||
|
||||
[VMOVcc]
|
||||
vreg,vreg \x90\xEE\xB0\xA\x40 THUMB32,VFPv2
|
||||
vreg,vreg \x40\xE\xB0\xA\x40 ARM32,VFPv2
|
||||
vreg,vreg \x40\xE\xB0\xA\x40 ARM32,VFPv2
|
||||
vreg,immmm \x90\xEE\xB0\xA\x0 THUMB32,VFPv3
|
||||
vreg,immmm \x40\xE\xB0\xA\x0 ARM32,VFPv3
|
||||
|
||||
reg32,vreg \x90\xEE\x10\xA\x10 THUMB32,VFPv2
|
||||
vreg,reg32 \x90\xEE\x00\xA\x10 THUMB32,VFPv2
|
||||
|
@ -1,2 +1,2 @@
|
||||
{ don't edit, this file is generated from armins.dat }
|
||||
956;
|
||||
958;
|
||||
|
@ -1470,6 +1470,20 @@
|
||||
code : #64#14#176#10#64;
|
||||
flags : if_arm32 or if_vfpv2
|
||||
),
|
||||
(
|
||||
opcode : A_VMOV;
|
||||
ops : 2;
|
||||
optypes : (ot_vreg,ot_immediatemm,ot_none,ot_none,ot_none,ot_none);
|
||||
code : #144#238#176#10#0;
|
||||
flags : if_thumb32 or if_vfpv3
|
||||
),
|
||||
(
|
||||
opcode : A_VMOV;
|
||||
ops : 2;
|
||||
optypes : (ot_vreg,ot_immediatemm,ot_none,ot_none,ot_none,ot_none);
|
||||
code : #64#14#176#10#0;
|
||||
flags : if_arm32 or if_vfpv3
|
||||
),
|
||||
(
|
||||
opcode : A_VMOV;
|
||||
ops : 2;
|
||||
|
@ -387,6 +387,8 @@ unit cpubase;
|
||||
function GenerateThumbCode : boolean;
|
||||
function GenerateThumb2Code : boolean;
|
||||
|
||||
function IsVFPFloatImmediate(ft : tfloattype;value : bestreal) : boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -736,5 +738,32 @@ unit cpubase;
|
||||
end;
|
||||
|
||||
|
||||
function IsVFPFloatImmediate(ft : tfloattype;value : bestreal) : boolean;
|
||||
var
|
||||
singlerec : tcompsinglerec;
|
||||
doublerec : tcompdoublerec;
|
||||
begin
|
||||
Result:=false;
|
||||
case ft of
|
||||
s32real:
|
||||
begin
|
||||
singlerec.value:=value;
|
||||
singlerec:=tcompsinglerec(NtoLE(DWord(singlerec)));
|
||||
Result:=(singlerec.bytes[0]=0) and (singlerec.bytes[1]=0) and ((singlerec.bytes[2] and 7)=0) and
|
||||
(((singlerec.bytes[3] and $7e)=$40) or ((singlerec.bytes[3] and $7e)=$3e));
|
||||
end;
|
||||
s64real:
|
||||
begin
|
||||
doublerec.value:=value;
|
||||
doublerec:=tcompdoublerec(NtoLE(QWord(doublerec)));
|
||||
Result:=(doublerec.bytes[0]=0) and (doublerec.bytes[1]=0) and (doublerec.bytes[2]=0) and
|
||||
(doublerec.bytes[3]=0) and (doublerec.bytes[4]=0) and (doublerec.bytes[5]=0) and
|
||||
((((doublerec.bytes[6] and $7f)=$40) and ((doublerec.bytes[7] and $c0)=0)) or
|
||||
(((doublerec.bytes[6] and $7f)=$3f) and ((doublerec.bytes[7] and $c0)=$c0)));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
@ -123,6 +123,12 @@ interface
|
||||
0 : (bytes:array[0..7] of byte);
|
||||
1 : (value:double);
|
||||
end;
|
||||
{ Use a variant record to be sure that the array if aligned correctly }
|
||||
tcompsinglerec=record
|
||||
case byte of
|
||||
0 : (bytes:array[0..3] of byte);
|
||||
1 : (value:single);
|
||||
end;
|
||||
tcompextendedrec=record
|
||||
case byte of
|
||||
0 : (bytes:array[0..9] of byte);
|
||||
|
Loading…
Reference in New Issue
Block a user