mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-19 20:19:25 +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;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user