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;
case opcode of
// CPU opcodes
A_MOVE, A_MOVEQ, A_MOVEA, A_MVZ, A_MVS, A_MOV3Q, A_LEA:
if opnr=1 then
result:=operand_write;
@ -483,6 +484,17 @@ type
result:=operand_readwrite;
A_TST,A_CMP,A_CMPI:
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
internalerror(2004040903);
end;
@ -508,17 +520,17 @@ type
function spilling_create_store(r:tregister; const ref:treference):Taicpu;
begin
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_ADDRESSREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_FPUREGISTER :
case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_ADDRESSREGISTER :
result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
R_FPUREGISTER :
// no need to handle sizes here
result:=taicpu.op_reg_ref(A_FMOVE,S_FS,r,ref);
else
internalerror(200602012);
end;
end;
end;

View File

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

View File

@ -138,56 +138,53 @@ implementation
if nf_swapped in flags then
swapleftright;
// 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);
case current_settings.fputype of
fpu_68881:
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
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
if left.location.loc = LOC_FPUREGISTER then
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);
// initialize the result
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
// emit the actual operation
{
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
location.register,left.location.register,
right.location.register))
}
// 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(op,S_FX,right.location.register,location.register));
end;
else
// softfpu should be handled in pass1, others are not yet supported...
internalerror(2015010201);
end;
end;
procedure t68kaddnode.second_cmpfloat;
begin
pass_left_right;
{
if (nf_swapped in flags) then
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);
location.resflags:=getresflags(true);
{
if nodetype in [equaln,unequaln] then
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)]));
case current_settings.fputype of
fpu_68881:
begin
location_reset(location,LOC_FLAGS,OS_NO);
location_reset(location,LOC_FLAGS,OS_NO);
location.resflags:=getresflags(false);
}
{ 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);
// 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;

View File

@ -68,8 +68,14 @@ implementation
end
else
{ 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
{ 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
fname := 'fpc_int64_to_double'
else