m68k: support 32x32 to 64bit MUL generation when targeting CPUs which support this instruction

git-svn-id: trunk@36339 -
This commit is contained in:
Károly Balogh 2017-05-25 22:35:12 +00:00
parent f5d17b2884
commit 87e8010f05
2 changed files with 71 additions and 1 deletions

View File

@ -65,8 +65,10 @@ type
{ this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : treference);
{ this is used for divx/remx regpair generation }
{ this is used for mulx/divx/remx regpair generation }
constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint; _op2,_op3 : tregister);
constructor op_ref_reg_reg(op : tasmop;_size : topsize;_op1 : treference; _op2,_op3 : tregister);
constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: tregister);
@ -321,6 +323,26 @@ type
loadreg(2,_op3);
end;
constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint; _op2,_op3 : tregister);
begin
inherited create(op);
init(_size);
ops:=3;
loadconst(0,aword(_op1));
loadreg(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_ref_reg_reg(op : tasmop;_size : topsize;_op1 : treference; _op2,_op3 : tregister);
begin
inherited create(op);
init(_size);
ops:=3;
loadref(0,_op1);
loadreg(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
Begin
inherited create(op);

View File

@ -37,6 +37,7 @@ interface
procedure second_mul64bit;
protected
function use_generic_mul64bit: boolean; override;
function use_generic_mul32to64: boolean; override;
procedure second_addfloat;override;
procedure second_cmpfloat;override;
procedure second_addordinal;override;
@ -359,8 +360,13 @@ implementation
*****************************************************************************}
procedure t68kaddnode.second_addordinal;
const
mul_op_signed: array[boolean] of tasmop = ( A_MULU, A_MULS );
var
cgop : topcg;
asmop : tasmop;
list : tasmlist;
href : treference;
begin
{ if we need to handle overflow checking, fall back to the generic cg }
if (nodetype in [addn,subn,muln]) and
@ -372,6 +378,8 @@ implementation
exit;
end;
list:=current_asmdata.CurrAsmList;
case nodetype of
addn: cgop:=OP_ADD;
xorn: cgop:=OP_XOR;
@ -398,6 +406,41 @@ implementation
{ initialize the result }
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
{ this is only true, if the CPU supports 32x32 -> 64 bit MUL, see the relevant method }
if (nodetype=muln) and is_64bit(resultdef) then
begin
list.concat(tai_comment.create(strpnew('second_addordinal: mul32to64bit')));
asmop:=mul_op_signed[cgop = OP_IMUL];
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
cg.a_load_reg_reg(list,left.location.size,OS_INT,left.location.register,location.register64.reglo);
if not (right.location.size in [OS_S32, OS_32]) or
not (right.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_CONSTANT,LOC_REFERENCE,LOC_CREFERENCE]) or
((right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and needs_unaligned(right.location.reference.alignment,def_cgsize(resultdef))) then
hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
case right.location.loc of
LOC_REGISTER,
LOC_CREGISTER:
list.concat(taicpu.op_reg_reg_reg(asmop,S_L,right.location.register,location.register64.reghi,location.register64.reglo));
LOC_CONSTANT:
list.concat(taicpu.op_const_reg_reg(asmop,S_L,right.location.value,location.register64.reghi,location.register64.reglo));
LOC_REFERENCE,
LOC_CREFERENCE:
begin
href:=right.location.reference;
tcg68k(cg).fixref(list,href,false);
list.concat(taicpu.op_ref_reg_reg(asmop,S_L,href,location.register64.reghi,location.register64.reglo));
end;
else
internalerror(2017052601);
end;
exit;
end;
location.register := cg.getintregister(current_asmdata.CurrAsmList,location.size);
cg.a_load_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register);
@ -527,6 +570,11 @@ implementation
64-bit
*****************************************************************************}
function t68kaddnode.use_generic_mul32to64: boolean;
begin
result:=not (CPUM68K_HAS_64BITMUL in cpu_capabilities[current_settings.cputype]);
end;
function t68kaddnode.use_generic_mul64bit: boolean;
begin
result:=(cs_check_overflow in current_settings.localswitches) or