+ support for vmov.xx vreg,#imm on arm

git-svn-id: trunk@39297 -
This commit is contained in:
florian 2018-06-24 12:39:59 +00:00
parent ec7a3a023e
commit 4f5f3c4a09
8 changed files with 142 additions and 13 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -1,2 +1,2 @@
{ don't edit, this file is generated from armins.dat }
956;
958;

View File

@ -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;

View File

@ -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.

View File

@ -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);