* ARM compiler compiles again

This commit is contained in:
florian 2003-09-04 21:07:03 +00:00
parent ed7610985b
commit 024d08e05a
7 changed files with 112 additions and 356 deletions

View File

@ -69,14 +69,14 @@ uses
function is_nop: boolean; override;
function is_move:boolean; override;
function spill_registers(list:Taasmoutput;
rgget:Trggetproc;
rgunget:Trgungetproc;
r:tsuperregisterset;
var unusedregsint:tsuperregisterset;
const spilltemplist:Tspill_temp_list):boolean; override;
end;
{ register spilling code }
function spilling_decode_loadstore(op: tasmop; var counterpart: tasmop; var wasload: boolean): boolean;override;
function spilling_create_loadstore(op: tasmop; r:tregister; const ref:treference): tai;override;
function spilling_create_load(const ref:treference;r:tregister): tai;override;
function spilling_create_store(r:tregister; const ref:treference): tai;override;
end;
tai_align = class(tai_align_abstract)
{ nothing to add }
end;
@ -247,16 +247,6 @@ implementation
end;
constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : longint; _op3: tasmsymbol);
begin
inherited create(op);
ops:=3;
loadconst(0,aword(_op1));
loadconst(1,aword(_op2));
loadsymbol(2,_op3,0);
end;
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
begin
inherited create(op);
@ -306,278 +296,38 @@ implementation
end;
function taicpu.spill_registers(list:Taasmoutput;
rgget:Trggetproc;
rgunget:Trgungetproc;
r:tsuperregisterset;
var unusedregsint:tsuperregisterset;
const spilltemplist:Tspill_temp_list): boolean;
function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
var back:tsuperregisterset;
function taicpu.spilling_decode_loadstore(op: tasmop; var counterpart: tasmop; var wasload: boolean): boolean;
begin
back:=unusedregsint;
get_insert_pos:=p;
while (p<>nil) and (p.typ=ait_regalloc) do
begin
{Rewind the register allocation.}
if Tai_regalloc(p).allocation then
include(unusedregsint,Tai_regalloc(p).reg.number shr 8)
else
begin
exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8);
if Tai_regalloc(p).reg.number shr 8=huntfor1 then
begin
get_insert_pos:=Tai(p.previous);
back:=unusedregsint;
end;
if Tai_regalloc(p).reg.number shr 8=huntfor2 then
begin
get_insert_pos:=Tai(p.previous);
back:=unusedregsint;
end;
if Tai_regalloc(p).reg.number shr 8=huntfor3 then
begin
get_insert_pos:=Tai(p.previous);
back:=unusedregsint;
end;
end;
p:=Tai(p.previous);
end;
unusedregsint:=back;
end;
procedure forward_allocation(p:Tai);
begin
{Forward the register allocation again.}
while (p<>self) do
begin
if p.typ<>ait_regalloc then
internalerror(200305311);
if Tai_regalloc(p).allocation then
exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8)
else
include(unusedregsint,Tai_regalloc(p).reg.number shr 8);
p:=Tai(p.next);
end;
end;
function decode_loadstore(op: tasmop; var counterpart: tasmop; wasload: boolean): boolean;
begin
result := true;
wasload := true;
case op of
A_LDR:
begin
counterpart := A_STR;
end;
A_LDM:
internalerror(2003070602);
else
result := false;
end;
end;
var i:byte;
supreg, reg1, reg2, reg3: Tsuperregister;
helpreg:Tregister;
helpins:Taicpu;
op:Tasmop;
pos:Tai;
wasload: boolean;
begin
spill_registers:=false;
if (ops = 2) and
(oper[1].typ=top_ref) and
{ oper[1] can also be ref in case of "lis r3,symbol@ha" or so }
decode_loadstore(opcode,op,wasload) then
begin
{ the register that's being stored/loaded }
supreg:=oper[0].reg.number shr 8;
if supreg in r then
begin
// Example:
// l?? r20d, 8(r1) ; r20d must be spilled into -60(r1)
//
// Change into:
//
// l?? r21d, 8(r1)
// st? r21d, -60(r1)
//
// And:
//
// st? r20d, 8(r1) ; r20d must be spilled into -60(r1)
//
// Change into:
//
// l?? r21d, -60(r1)
// st? r21d, 8(r1)
pos := get_insert_pos(Tai(previous),oper[0].reg.number shr 8,
oper[1].ref^.base.number shr 8,oper[1].ref^.index.number shr 8);
rgget(list,pos,0,helpreg);
spill_registers := true;
if wasload then
begin
helpins := taicpu.op_reg_ref(opcode,helpreg,oper[1].ref^);
loadref(1,spilltemplist[supreg]);
opcode := op;
end
else
helpins := taicpu.op_reg_ref(op,helpreg,spilltemplist[supreg]);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
loadreg(0,helpreg);
rgunget(list,helpins,helpreg);
forward_allocation(tai(helpins.next));
{$ifdef debugra}
writeln('spilling!');
list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
{$endif debugra}
end;
{ now the registers used in the reference }
{ a) base }
supreg := oper[1].ref^.base.number shr 8;
if supreg in r then
begin
if wasload then
pos:=get_insert_pos(Tai(previous),oper[1].ref^.index.number shr 8,oper[0].reg.number shr 8,0)
else
pos:=get_insert_pos(Tai(previous),oper[1].ref^.index.number shr 8,0,0);
rgget(list,pos,0,helpreg);
spill_registers:=true;
helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
oper[1].ref^.base:=helpreg;
rgunget(list,helpins,helpreg);
forward_allocation(Tai(helpins.next));
{$ifdef debugra}
writeln('spilling!');
list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
{$endif debugra}
end;
{ b) index }
supreg := oper[1].ref^.index.number shr 8;
if supreg in r then
begin
if wasload then
pos:=get_insert_pos(Tai(previous),oper[1].ref^.base.number shr 8,oper[0].reg.number shr 8,0)
else
pos:=get_insert_pos(Tai(previous),oper[1].ref^.base.number shr 8,0,0);
rgget(list,pos,0,helpreg);
spill_registers:=true;
helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
oper[1].ref^.index:=helpreg;
rgunget(list,helpins,helpreg);
forward_allocation(Tai(helpins.next));
{$ifdef debugra}
writeln('spilling!');
list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
{$endif debugra}
end;
{ load/store is done }
exit;
end;
{ all other instructions the compiler generates are the same (I hope): }
{ operand 0 is a register and is the destination, the others are sources }
{ and can be either registers or constants }
{ exception: branches (is_jmp isn't always set for them) }
if oper[0].typ <> top_reg then
exit;
reg1 := oper[0].reg.number shr 8;
if oper[1].typ = top_reg then
reg2 := oper[1].reg.number shr 8
else
reg2 := 0;
if (ops >= 3) and
(oper[2].typ = top_reg) then
reg3 := oper[2].reg.number shr 8
else
reg3 := 0;
supreg:=reg1;
if supreg in r then
begin
// Example:
// add r20d, r21d, r22d ; r20d must be spilled into -60(r1)
//
// Change into:
//
// lwz r23d, -60(r1)
// add r23d, r21d, r22d
// stw r23d, -60(r1)
pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
rgget(list,pos,0,helpreg);
spill_registers := true;
helpins := taicpu.op_reg_ref(A_STR,helpreg,spilltemplist[supreg]);
list.insertafter(helpins,self);
helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
loadreg(0,helpreg);
rgunget(list,helpins,helpreg);
forward_allocation(tai(helpins.next));
{$ifdef debugra}
writeln('spilling!');
list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
{$endif debugra}
end;
for i := 1 to 2 do
if (oper[i].typ = top_reg) then
result := true;
wasload := true;
case op of
A_LDR:
begin
supreg:=oper[i].reg.number;
if supreg in r then
begin
// Example:
// add r20d, r21d, r22d ; r20d must be spilled into -60(r1)
//
// Change into:
//
// lwz r23d, -60(r1)
// add r23d, r21d, r22d
// stw r23d, -60(r1)
pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
rgget(list,pos,0,helpreg);
spill_registers := true;
helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
loadreg(i,helpreg);
rgunget(list,helpins,helpreg);
forward_allocation(tai(helpins.next));
{$ifdef debugra}
writeln('spilling!');
list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);
{$endif debugra}
end;
counterpart := A_STR;
end;
A_LDM:
internalerror(2003070602);
else
result := false;
end;
end;
function taicpu.spilling_create_loadstore(op: tasmop; r:tregister; const ref:treference): tai;
begin
result:=taicpu.op_reg_ref(opcode,r,ref);
end;
function taicpu.spilling_create_load(const ref:treference;r:tregister): tai;
begin
result:=taicpu.op_reg_ref(A_LDR,r,ref);
end;
function taicpu.spilling_create_store(r:tregister; const ref:treference): tai;
begin
result:=taicpu.op_reg_ref(A_STR,r,ref);
end;
@ -615,7 +365,10 @@ implementation
end.
{
$Log$
Revision 1.9 2003-09-04 00:15:29 florian
Revision 1.10 2003-09-04 21:07:03 florian
* ARM compiler compiles again
Revision 1.9 2003/09/04 00:15:29 florian
* first bunch of adaptions of arm compiler for new register type
Revision 1.8 2003/09/03 11:18:37 florian

View File

@ -85,8 +85,8 @@ unit cgcpu;
procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override;
procedure g_restore_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override;
procedure g_save_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);override;
procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);override;
procedure g_save_all_registers(list : taasmoutput);override;
procedure g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);override;
@ -206,9 +206,7 @@ unit cgcpu;
var
r : tregister;
begin
r.enum:=R_INTREGISTER;
r.number:=NR_PC;
list.concat(taicpu.op_reg_reg(A_MOV,r,reg));
list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
if not(pi_do_call in current_procinfo.flags) then
internalerror(2003060704);
end;
@ -218,9 +216,7 @@ unit cgcpu;
var
r : tregister;
begin
r.enum:=R_INTREGISTER;
r.number:=NR_PC;
a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,r);
a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_PC);
if not(pi_do_call in current_procinfo.flags) then
internalerror(2003060705);
end;
@ -348,9 +344,9 @@ unit cgcpu;
OP_MUL:
begin
{ the arm doesn't allow that rd and rm are the same }
if dst.number=src2.number then
if dst=src2 then
begin
if src1.number<>src2.number then
if src1<>src2 then
list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
else
begin
@ -420,16 +416,15 @@ unit cgcpu;
tmpref : treference;
l : tasmlabel;
begin
tmpreg.enum:=R_INTREGISTER;
tmpreg.number:=NR_NO;
tmpreg:=NR_NO;
{ Be sure to have a base register }
if (ref.base.number=NR_NO) then
if (ref.base=NR_NO) then
begin
if ref.shiftmode<>SM_None then
internalerror(200308294);
ref.base:=ref.index;
ref.index.number:=NR_NO;
ref.index:=NR_NO;
end;
{ absolute symbols can't be handled directly, we've to store the symbol reference
@ -464,13 +459,12 @@ unit cgcpu;
tmpreg:=rg.getregisterint(list,OS_INT);
reference_reset(tmpref);
tmpref.symbol:=l;
tmpref.base.enum:=R_INTREGISTER;
tmpref.base.number:=NR_R15;
tmpref.base:=NR_R15;
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
if (ref.base.number<>NR_NO) then
if (ref.base<>NR_NO) then
begin
if ref.index.number<>NR_NO then
if ref.index<>NR_NO then
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
rg.ungetregister(list,ref.base);
@ -490,7 +484,7 @@ unit cgcpu;
ref.symbol:=nil;
end;
list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
if (tmpreg.number<>NR_NO) then
if (tmpreg<>NR_NO) then
rg.ungetregisterint(list,tmpreg);
end;
@ -547,11 +541,7 @@ unit cgcpu;
so : tshifterop;
begin
shifterop_reset(so);
if (reg1.enum<>R_INTREGISTER) or (reg1.number = 0) then
internalerror(200303101);
if (reg2.enum<>R_INTREGISTER) or (reg2.number = 0) then
internalerror(200303102);
if (reg1.number<>reg2.number) or
if (reg1<>reg2) or
(tcgsize2size[tosize] < tcgsize2size[fromsize]) or
((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
(tosize <> fromsize) and
@ -649,24 +639,19 @@ unit cgcpu;
tmpreg : tregister;
b : byte;
begin
if reg.enum=R_INTREGISTER then
begin
if is_shifter_const(a,b) then
list.concat(taicpu.op_reg_const(A_CMN,reg,a))
{ CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
and CMP reg,$7fffffff regarding the flags according to the ARM manual }
else if is_shifter_const(not(a),b) and (a<>$7fffffff) and (a<>$ffffffff) then
list.concat(taicpu.op_reg_const(A_CMN,reg,not(a)))
else
begin
tmpreg:=rg.getregisterint(list,size);
a_load_const_reg(list,size,a,tmpreg);
list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
rg.ungetregisterint(list,tmpreg);
end
end
if is_shifter_const(a,b) then
list.concat(taicpu.op_reg_const(A_CMN,reg,a))
{ CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
and CMP reg,$7fffffff regarding the flags according to the ARM manual }
else if is_shifter_const(not(a),b) and (a<>$7fffffff) and (a<>$ffffffff) then
list.concat(taicpu.op_reg_const(A_CMN,reg,not(a)))
else
internalerror(200308131);
begin
tmpreg:=rg.getregisterint(list,size);
a_load_const_reg(list,size,a,tmpreg);
list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
rg.ungetregisterint(list,tmpreg);
end;
a_jmp_cond(list,cmp_op,l);
end;
@ -688,8 +673,8 @@ unit cgcpu;
var
ai : taicpu;
begin
ai := Taicpu.op_sym_cond(A_B,l,flags_to_cond(f));
ai.is_jmp := true;
ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
ai.is_jmp:=true;
list.concat(ai);
end;
@ -698,8 +683,8 @@ unit cgcpu;
var
ai : taicpu;
begin
list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f));
list.concat(setcondition(aicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
end;
@ -733,7 +718,7 @@ unit cgcpu;
procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword);
begin
if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14));
list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
else
{ restore int registers and return }
list.concat(setoppostfix(taicpu.op_reg_regset(A_LDM,NR_R11,rg.used_in_proc_int-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_EA));
@ -753,25 +738,25 @@ unit cgcpu;
begin
tmpref:=ref;
{ Be sure to have a base register }
if (tmpref.base.number=NR_NO) then
if (tmpref.base=NR_NO) then
begin
if tmpref.shiftmode<>SM_None then
internalerror(200308294);
tmpref.base:=tmpref.index;
tmpref.index.number:=NR_NO;
tmpref.index:=NR_NO;
end;
if assigned(tmpref.symbol) or
not(is_shifter_const(tmpref.offset,b)) or
((tmpref.base.number<>NR_NO) and tmpref.index.number<>NR_NO)) then
((tmpref.base<>NR_NO) and (tmpref.index<>NR_NO)) then
fixref(list,tmpref);
if ref.index.number<>NR_NO then
if ref.index<>NR_NO then
begin
end
else
{ else
list.concat(taicpu.op_reg_reg(A_MOV,r,));
ref.signindex<0 then
ref.signindex<0 then }
end;
@ -807,13 +792,12 @@ unit cgcpu;
tmpreg:=rg.getregisterint(list,OS_INT);
reference_reset(tmpref);
tmpref.symbol:=l;
tmpref.base.enum:=R_INTREGISTER;
tmpref.base.number:=NR_R15;
tmpref.base:=NR_PC;
list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
if (ref.base.number<>NR_NO) then
if (ref.base<>NR_NO) then
begin
if ref.index.number<>NR_NO then
if ref.index<>NR_NO then
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
rg.ungetregister(list,ref.base);
@ -953,13 +937,13 @@ unit cgcpu;
end;
procedure tcgarm.g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);
procedure tcgarm.g_save_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);
begin
{ we support only ARM standard calling conventions so this procedure has no use on the ARM }
end;
procedure tcgarm.g_restore_standard_registers(list : taasmoutput; usedinproc : Tsupregset);
procedure tcgarm.g_restore_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);
begin
{ we support only ARM standard calling conventions so this procedure has no use on the ARM }
end;
@ -1101,7 +1085,10 @@ begin
end.
{
$Log$
Revision 1.13 2003-09-04 00:15:29 florian
Revision 1.14 2003-09-04 21:07:03 florian
* ARM compiler compiles again
Revision 1.13 2003/09/04 00:15:29 florian
* first bunch of adaptions of arm compiler for new register type
Revision 1.12 2003/09/03 19:10:30 florian

View File

@ -116,6 +116,9 @@ unit cpubase;
{ Available Registers }
{$i rarmcon.inc}
{ aliases }
NR_PC = NR_R15;
{ Integer Super registers first and last }
{$warning Supreg shall be $00-$1f}
first_int_supreg = RS_R3;
@ -632,7 +635,10 @@ unit cpubase;
end.
{
$Log$
Revision 1.12 2003-09-04 00:15:29 florian
Revision 1.13 2003-09-04 21:07:03 florian
* ARM compiler compiles again
Revision 1.12 2003/09/04 00:15:29 florian
* first bunch of adaptions of arm compiler for new register type
Revision 1.11 2003/09/03 19:10:30 florian

View File

@ -108,8 +108,9 @@ interface
R_INVALIDREGISTER, { = 0 }
R_INTREGISTER, { = 1 }
R_FPUREGISTER, { = 2 }
{ used by Intel only }
R_MMXREGISTER, { = 3 }
R_KNIREGISTER, { = 4 }
R_MMREGISTER, { = 4 }
R_SPECIALREGISTER, { = 5 }
R_ADDRESSREGISTER { = 6 }
);
@ -270,9 +271,9 @@ implementation
R_FPUREGISTER:
t:='f';
R_MMXREGISTER:
t:='x';
R_MMREGISTER:
t:='m';
R_KNIREGISTER:
t:='k';
else
begin
result:='INVALID';
@ -305,7 +306,10 @@ implementation
end.
{
$Log$
Revision 1.24 2003-09-03 21:06:19 peter
Revision 1.25 2003-09-04 21:07:03 florian
* ARM compiler compiles again
Revision 1.24 2003/09/03 21:06:19 peter
* write INVALID as register name instead of IE
Revision 1.23 2003/09/03 16:29:37 peter

View File

@ -107,7 +107,7 @@ M29,$03,$1d,M29,v29,M29,-1
M30,$03,$1e,M30,v30,M30,-1
M31,$03,$1f,M31,v31,M31,-1
CR,$05,$00,CR,cR,CR,-1
CR,$05,$00,CR,cr,CR,-1
CR0,$05,$01,CR0,cr0,CR0,68
CR1,$05,$02,CR1,cr1,CR1,69
CR2,$05,$03,CR2,cr2,CR2,70
@ -123,7 +123,10 @@ FPSCR,$05,$0c,FPSCR,fpscr,FPSCR,-1
;
; $Log$
; Revision 1.3 2003-09-03 19:35:24 peter
; Revision 1.4 2003-09-04 21:07:03 florian
; * ARM compiler compiles again
;
; Revision 1.3 2003/09/03 19:35:24 peter
; * powerpc compiles again
;
; Revision 1.2 2003/09/03 15:55:01 peter

View File

@ -96,7 +96,7 @@
'v29',
'v30',
'v31',
'cR',
'cr',
'cr0',
'cr1',
'cr2',

View File

@ -440,7 +440,7 @@ implementation
R_FPUREGISTER :
reg2opsize:=S_FL;
R_MMXREGISTER,
R_KNIREGISTER :
R_MMREGISTER :
reg2opsize:=S_D;
R_SPECIALREGISTER :
begin
@ -563,7 +563,10 @@ implementation
end.
{
$Log$
Revision 1.15 2003-09-03 15:55:02 peter
Revision 1.16 2003-09-04 21:07:03 florian
* ARM compiler compiles again
Revision 1.15 2003/09/03 15:55:02 peter
* NEWRA branch merged
Revision 1.14 2003/09/03 11:18:37 florian