few fixes and advancements. 68k cg now compiles empty system unit without crashing.

git-svn-id: trunk@224 -
This commit is contained in:
Károly Balogh 2005-06-05 23:36:35 +00:00
parent 9d9d0d7b33
commit 94281c5589
3 changed files with 326 additions and 20 deletions

View File

@ -27,7 +27,7 @@ interface
uses uses
cclasses,aasmtai, cclasses,aasmtai,
aasmbase,globals,verbose, aasmbase,globals,verbose,symtype,
cpubase,cpuinfo,cgbase,cgutils; cpubase,cpuinfo,cgbase,cgutils;
@ -81,6 +81,8 @@ type
constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint); constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference); constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
function is_same_reg_move(regtype: Tregistertype):boolean;override;
private private
procedure loadregset(opidx:longint;const s:tcpuregisterset); procedure loadregset(opidx:longint;const s:tcpuregisterset);
procedure init(_size : topsize); { this need to be called by all constructor } procedure init(_size : topsize); { this need to be called by all constructor }
@ -417,6 +419,25 @@ type
end; end;
function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
begin
result:=(((opcode=A_MOVE) or (opcode=A_EXG)) and
(regtype = R_INTREGISTER) and
(ops=2) and
(oper[0]^.typ=top_reg) and
(oper[1]^.typ=top_reg) and
(oper[0]^.reg=oper[1]^.reg)
) or
((opcode=A_FMOVE) and
(regtype = R_FPUREGISTER) and
(ops=2) and
(oper[0]^.typ=top_reg) and
(oper[1]^.typ=top_reg) and
(oper[0]^.reg=oper[1]^.reg)
);
end;
function spilling_create_load(const ref:treference;r:tregister): tai; function spilling_create_load(const ref:treference;r:tregister): tai;
begin begin
{ {

View File

@ -255,19 +255,21 @@ unit cpubase;
NR_STACK_POINTER_REG = NR_SP; NR_STACK_POINTER_REG = NR_SP;
RS_STACK_POINTER_REG = RS_SP; RS_STACK_POINTER_REG = RS_SP;
{# Frame pointer register } {# Frame pointer register }
NR_FRAME_POINTER_REG = NR_A6; {$warning FIX ME!!! frame pointer is A5 on Amiga, but A6 on unixes?}
RS_FRAME_POINTER_REG = RS_A6; NR_FRAME_POINTER_REG = NR_A5;
RS_FRAME_POINTER_REG = RS_A5;
{# Register for addressing absolute data in a position independant way, {# Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific. For such as in PIC code. The exact meaning is ABI specific. For
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
} }
{$warning FIX ME!!! pic offset reg conflicts with frame pointer?}
NR_PIC_OFFSET_REG = NR_A5; NR_PIC_OFFSET_REG = NR_A5;
{ Return address for DWARF } { Return address for DWARF }
{$warning TODO just a guess!} {$warning TODO just a guess!}
NR_RETURN_ADDRESS_REG = NR_A0; NR_RETURN_ADDRESS_REG = NR_A0;
{ Results are returned in this register (32-bit values) } { Results are returned in this register (32-bit values) }
NR_FUNCTION_RETURN_REG = NR_D0; NR_FUNCTION_RETURN_REG = NR_D0;
RS_FUNCTION_RETURN_REG = NR_D0; RS_FUNCTION_RETURN_REG = RS_D0;
{ Low part of 64bit return value } { Low part of 64bit return value }
NR_FUNCTION_RETURN64_LOW_REG = NR_D0; NR_FUNCTION_RETURN64_LOW_REG = NR_D0;
RS_FUNCTION_RETURN64_LOW_REG = RS_D0; RS_FUNCTION_RETURN64_LOW_REG = RS_D0;

View File

@ -30,8 +30,8 @@ unit cpupara;
uses uses
globtype, globtype,
cpubase, cpubase,
symconst,symdef,symsym, symconst,symtype,symdef,symsym,
parabase,paramgr; parabase,paramgr,cgbase;
type type
{ Returns the location for the nr-st 32 Bit int parameter { Returns the location for the nr-st 32 Bit int parameter
@ -42,7 +42,12 @@ unit cpupara;
tm68kparamanager = class(tparamanager) tm68kparamanager = class(tparamanager)
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override; procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
private private
procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
function parseparaloc(p : tparavarsym;const s : string) : boolean;override; function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
end; end;
@ -52,7 +57,7 @@ unit cpupara;
verbose, verbose,
globals, globals,
systems, systems,
cpuinfo,cgbase, cpuinfo,cgutils,
defutil; defutil;
procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara); procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);
@ -76,43 +81,320 @@ unit cpupara;
end; end;
end; end;
function getparaloc(p : tdef) : tcgloc;
begin
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
if push_addr_param for the def is true
}
case p.deftype of
orddef:
result:=LOC_REGISTER;
floatdef:
result:=LOC_FPUREGISTER;
enumdef:
result:=LOC_REGISTER;
pointerdef:
result:=LOC_REGISTER;
formaldef:
result:=LOC_REGISTER;
classrefdef:
result:=LOC_REGISTER;
recorddef:
if (target_info.abi<>abi_powerpc_aix) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
objectdef:
if is_object(p) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
stringdef:
if is_shortstring(p) or is_longstring(p) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
procvardef:
if (po_methodpointer in tprocvardef(p).procoptions) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
filedef:
result:=LOC_REGISTER;
arraydef:
result:=LOC_REFERENCE;
setdef:
if is_smallset(p) then
result:=LOC_REGISTER
else
result:=LOC_REFERENCE;
variantdef:
result:=LOC_REFERENCE;
{ avoid problems with errornous definitions }
errordef:
result:=LOC_REGISTER;
else
internalerror(2002071001);
end;
end;
{$warning copied from ppc cg, needs work}
function tm68kparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
begin
result:=false;
{ var,out always require address }
if varspez in [vs_var,vs_out] then
begin
result:=true;
exit;
end;
case def.deftype of
variantdef,
formaldef :
result:=true;
recorddef:
result:=true;
arraydef:
result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
is_open_array(def) or
is_array_of_const(def) or
is_array_constructor(def);
objectdef :
result:=is_object(def);
setdef :
result:=(tsetdef(def).settype<>smallset);
stringdef :
result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
procvardef :
result:=po_methodpointer in tprocvardef(def).procoptions;
end;
end;
procedure tm68kparamanager.init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
begin
cur_stack_offset:=8;
curintreg:=RS_D0;
curfloatreg:=RS_FP0;
end;
procedure tm68kparamanager.create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
var
retcgsize: tcgsize;
begin
{ Constructors return self instead of a boolean }
if (p.proctypeoption=potype_constructor) then
retcgsize:=OS_ADDR
else
retcgsize:=def_cgsize(p.rettype.def);
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
{ void has no location }
if is_void(p.rettype.def) then
begin
location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
exit;
end;
{ Return in FPU register? }
if p.rettype.def.deftype=floatdef then
begin
p.funcretloc[side].loc:=LOC_FPUREGISTER;
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
p.funcretloc[side].size:=retcgsize;
end
else
{ Return in register? }
if not ret_in_param(p.rettype.def,p.proccalloption) then
begin
if retcgsize in [OS_64,OS_S64] then
begin
{ low 32bits }
p.funcretloc[side].loc:=LOC_REGISTER;
p.funcretloc[side].size:=OS_64;
if side=callerside then
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
else
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
{ high 32bits }
if side=callerside then
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
else
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
end
else
begin
p.funcretloc[side].loc:=LOC_REGISTER;
p.funcretloc[side].size:=retcgsize;
if side=callerside then
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
else
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
end;
end
else
begin
p.funcretloc[side].loc:=LOC_REFERENCE;
p.funcretloc[side].size:=retcgsize;
end;
end;
function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint; function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
var
cur_stack_offset: aword;
curintreg, curfloatreg: tsuperregister;
begin
init_values(curintreg,curfloatreg,cur_stack_offset);
result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
create_funcretloc_info(p,side);
end;
function tm68kparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
var var
paraloc : pcgparalocation; paraloc : pcgparalocation;
hp : tparavarsym; hp : tparavarsym;
paracgsize : tcgsize; paracgsize : tcgsize;
paralen : longint; paralen : aint;
parasize : longint; parasize : longint;
paradef : tdef;
i : longint; i : longint;
loc : tcgloc;
nextintreg,
nextfloatreg : tsuperregister;
stack_offset : longint;
begin begin
result:=0;
nextintreg:=curintreg;
nextfloatreg:=curfloatreg;
stack_offset:=cur_stack_offset;
parasize:=0; parasize:=0;
for i:=0 to p.paras.count-1 do for i:=0 to p.paras.count-1 do
begin begin
hp:=tparavarsym(p.paras[i]); hp:=tparavarsym(paras[i]);
paradef:=hp.vartype.def;
{ syscall for AmigaOS can have already a paraloc set }
if (vo_has_explicit_paraloc in hp.varoptions) then
begin
if not(vo_is_syscall_lib in hp.varoptions) then
internalerror(200506051);
continue;
end;
hp.paraloc[side].reset; hp.paraloc[side].reset;
{ currently only support C-style array of const } { currently only support C-style array of const }
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
is_array_of_const(hp.vartype.def) then is_array_of_const(paradef) then
begin begin
paraloc:=hp.paraloc[side].add_location; paraloc:=hp.paraloc[side].add_location;
{ hack: the paraloc must be valid, but is not actually used } { hack: the paraloc must be valid, but is not actually used }
paraloc^.loc:=LOC_REFERENCE; paraloc^.loc:=LOC_REGISTER;
if side=callerside then paraloc^.register:=NR_D0;
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
paraloc^.size:=OS_ADDR; paraloc^.size:=OS_ADDR;
paraloc^.reference.offset:=0;
break; break;
end; end;
if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then if (hp.varspez in [vs_var,vs_out]) or
push_addr_param(hp.varspez,paradef,p.proccalloption) or
is_open_array(paradef) or
is_array_of_const(paradef) then
begin
paradef:=voidpointertype.def;
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end
else
begin
if not is_special_array(paradef) then
paralen:=paradef.size
else
paralen:=tcgsize2size[def_cgsize(paradef)];
loc:=getparaloc(paradef);
paracgsize:=def_cgsize(paradef);
{ for things like formaldef }
if (paracgsize=OS_NO) then
begin
paracgsize:=OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end;
end;
hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
if (paralen = 0) then
if (paradef.deftype = recorddef) then
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc := LOC_VOID;
end
else
internalerror(200506052);
{ can become < 0 for e.g. 3-byte records }
while (paralen > 0) do
begin
paraloc:=hp.paraloc[side].add_location;
if (loc = LOC_REGISTER) and
(nextintreg <= RS_D7) then
begin
writeln('loc register');
paraloc^.loc := loc;
{ make sure we don't lose whether or not the type is signed }
if (paradef.deftype <> orddef) then
paracgsize := int_cgsize(paralen);
if (paracgsize in [OS_NO,OS_64,OS_S64]) then
paraloc^.size := OS_INT
else
paraloc^.size := paracgsize;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
dec(paralen,tcgsize2size[paraloc^.size]);
end
else if (loc = LOC_FPUREGISTER) and
(nextfloatreg <= RS_FP7) then
begin
writeln('loc fpuregister');
paraloc^.loc:=loc;
paraloc^.size := paracgsize;
paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
inc(nextfloatreg);
dec(paralen,tcgsize2size[paraloc^.size]);
end
else { LOC_REFERENCE }
begin
writeln('loc reference');
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
if (side = callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,align(paralen,4));
paralen := 0;
end;
end;
end;
result:=stack_offset;
writeln('stack offset:',stack_offset);
end;
{
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
paracgsize:=OS_ADDR paracgsize:=OS_ADDR
else else
begin begin
paracgsize:=def_cgsize(hp.vartype.def); paracgsize:=def_cgsize(paradef);
if paracgsize=OS_NO then if paracgsize=OS_NO then
paracgsize:=OS_ADDR; paracgsize:=OS_ADDR;
end; end;
@ -127,9 +409,10 @@ unit cpupara;
paraloc^.reference.index:=NR_FRAME_POINTER_REG; paraloc^.reference.index:=NR_FRAME_POINTER_REG;
paraloc^.reference.offset:=target_info.first_parm_offset+parasize; paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
end; end;
create_funcretloc_info(p,side);
result:=parasize; result:=parasize;
end; end;
}
function tm68kparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean; function tm68kparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
var var