m68k: basic 68881 fpu support. probably still broken at umpzillion places, and mostly untested, but at least it builds the RTL and all packages successfully with -Cp68020 -Cf68881 instead of dying with random internalerrors() and now even emits actual FPU opcodes.

git-svn-id: trunk@29370 -
This commit is contained in:
Károly Balogh 2015-01-02 05:29:45 +00:00
parent 588256f79a
commit d000b1bc7c
4 changed files with 74 additions and 73 deletions

View File

@ -464,6 +464,7 @@ type
result:=operand_read; result:=operand_read;
case opcode of case opcode of
// CPU opcodes
A_MOVE, A_MOVEQ, A_MOVEA, A_MVZ, A_MVS, A_MOV3Q, A_LEA: A_MOVE, A_MOVEQ, A_MOVEA, A_MVZ, A_MVS, A_MOV3Q, A_LEA:
if opnr=1 then if opnr=1 then
result:=operand_write; result:=operand_write;
@ -483,6 +484,17 @@ type
result:=operand_readwrite; result:=operand_readwrite;
A_TST,A_CMP,A_CMPI: A_TST,A_CMP,A_CMPI:
begin end; { Do nothing, default operand_read is fine here. } begin end; { Do nothing, default operand_read is fine here. }
// FPU opcodes
A_FMOVE:
if opnr=1 then
result:=operand_write;
A_FADD, A_FSUB, A_FMUL, A_FDIV:
if opnr=1 then
result:=operand_readwrite;
A_FCMP:
begin end; { operand_read }
else begin else begin
internalerror(2004040903); internalerror(2004040903);
end; end;
@ -508,17 +520,17 @@ type
function spilling_create_store(r:tregister; const ref:treference):Taicpu; function spilling_create_store(r:tregister; const ref:treference):Taicpu;
begin begin
case getregtype(r) of case getregtype(r) of
R_INTREGISTER : R_INTREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref); result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_ADDRESSREGISTER : R_ADDRESSREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref); result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_FPUREGISTER : R_FPUREGISTER :
// no need to handle sizes here // no need to handle sizes here
result:=taicpu.op_reg_ref(A_FMOVE,S_FS,r,ref); result:=taicpu.op_reg_ref(A_FMOVE,S_FS,r,ref);
else else
internalerror(200602012); internalerror(200602012);
end; end;
end; end;

View File

@ -964,20 +964,16 @@ unit cgcpu;
var var
instr : taicpu; instr : taicpu;
begin begin
{ in emulation mode, only 32-bit single is supported } instr:=taicpu.op_reg_reg(A_FMOVE,S_FX,reg1,reg2);
if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then add_move_instruction(instr);
instr:=taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2) list.concat(instr);
else
instr:=taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2);
add_move_instruction(instr);
list.concat(instr);
end; end;
procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
var var
opsize : topsize; opsize : topsize;
href : treference; href : treference;
begin begin
opsize := tcgsize2opsize[fromsize]; opsize := tcgsize2opsize[fromsize];
{ extended is not supported, since it is not available on Coldfire } { extended is not supported, since it is not available on Coldfire }
@ -985,30 +981,21 @@ unit cgcpu;
internalerror(20020729); internalerror(20020729);
href := ref; href := ref;
fixref(list,href); fixref(list,href);
{ in emulation mode, only 32-bit single is supported } list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
else
begin
list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
if (tosize < fromsize) then
a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
end;
end; end;
procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference); procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
var var
opsize : topsize; opsize : topsize;
href : treference;
begin begin
opsize := tcgsize2opsize[tosize]; opsize := tcgsize2opsize[tosize];
{ extended is not supported, since it is not available on Coldfire } { extended is not supported, since it is not available on Coldfire }
if opsize = S_FX then if opsize = S_FX then
internalerror(20020729); internalerror(20020729);
{ in emulation mode, only 32-bit single is supported } href := ref;
if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then fixref(list,href);
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref)) list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg,href));
else
list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
end; end;
@ -1018,8 +1005,7 @@ unit cgcpu;
LOC_REFERENCE,LOC_CREFERENCE: LOC_REFERENCE,LOC_CREFERENCE:
begin begin
case size of case size of
OS_F64: OS_F64,
cg64.a_load64_ref_cgpara(list,ref,cgpara);
OS_F32: OS_F32:
a_load_ref_cgpara(list,size,ref,cgpara); a_load_ref_cgpara(list,size,ref,cgpara);
else else

View File

@ -138,56 +138,53 @@ implementation
if nf_swapped in flags then if nf_swapped in flags then
swapleftright; swapleftright;
// put both operands in a register case current_settings.fputype of
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true); fpu_68881:
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true); begin
// put both operands in a register
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
// initialize de result // initialize the result
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef)); location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
if left.location.loc = LOC_FPUREGISTER then location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
location.register := left.location.register
else if right.location.loc = LOC_FPUREGISTER then
location.register := right.location.register
else
location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
// emit the actual operation // emit the actual operation
{ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FMOVE,S_FX,left.location.register,location.register));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_FX,right.location.register,location.register));
location.register,left.location.register, end;
right.location.register)) else
} // softfpu should be handled in pass1, others are not yet supported...
internalerror(2015010201);
end;
end; end;
procedure t68kaddnode.second_cmpfloat; procedure t68kaddnode.second_cmpfloat;
begin begin
pass_left_right; pass_left_right;
{
if (nf_swapped in flags) then if (nf_swapped in flags) then
swapleftright; swapleftright;
}
{ force fpureg as location, left right doesn't matter
as both will be in a fpureg }
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
location_reset(location,LOC_FLAGS,OS_NO); case current_settings.fputype of
location.resflags:=getresflags(true); fpu_68881:
{ begin
if nodetype in [equaln,unequaln] then location_reset(location,LOC_FLAGS,OS_NO);
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
left.location.register,right.location.register),
cgsize2fpuoppostfix[def_cgsize(resultdef)]))
else
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
left.location.register,right.location.register),
cgsize2fpuoppostfix[def_cgsize(resultdef)]));
location_reset(location,LOC_FLAGS,OS_NO); { force fpureg as location, left right doesn't matter
location.resflags:=getresflags(false); as both will be in a fpureg }
} hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
// emit compare
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCMP,S_FX,right.location.register,left.location.register));
location.resflags:=getresflags(false);
end;
else
// softfpu should be handled in pass1, others are not yet supported...
internalerror(2015010201);
end;
end; end;

View File

@ -68,8 +68,14 @@ implementation
end end
else else
{ converting a 64bit integer to a float requires a helper } { converting a 64bit integer to a float requires a helper }
if is_64bitint(left.resultdef) then if is_64bitint(left.resultdef) or
is_currency(left.resultdef) then
begin begin
{ hack to avoid double division by 10000, as it's
already done by typecheckpass.resultdef_int_to_real }
if is_currency(left.resultdef) then
left.resultdef := s64inttype;
if is_signed(left.resultdef) then if is_signed(left.resultdef) then
fname := 'fpc_int64_to_double' fname := 'fpc_int64_to_double'
else else