mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 04:06:08 +02:00
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:
parent
588256f79a
commit
d000b1bc7c
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user