* fixed several arm calling conventions issues

* fixed reference reading in the assembler reader
  * fixed a_loadaddr_ref_reg
This commit is contained in:
florian 2003-12-03 17:39:04 +00:00
parent e418971c77
commit 1a87a5ed45
8 changed files with 250 additions and 167 deletions

View File

@ -1689,6 +1689,14 @@ implementation
reg:=r;
typ:=top_reg;
end;
{$ifdef ARM}
{ R15 is the PC on the ARM thus moves to R15 are jumps.
Due to speed considerations we don't use a virtual overridden method here.
Because the pc/r15 isn't handled by the reg. allocator this should never cause
problems with iregs getting r15.
}
is_jmp:=(opcode=A_MOV) and (opidx=0) and (r=NR_R15);
{$endif ARM}
end;
@ -1811,55 +1819,86 @@ implementation
var
wasload: boolean;
begin
{ oper[1] can also be ref in case of "lis r3,symbol@ha" or so }
if not((oper[1]^.typ=top_ref) and
spilling_decode_loadstore(opcode,op,wasload)) then
Exit;
{ the register that's being stored/loaded }
supreg:=getsupreg(oper[0]^.reg);
if supregset_in(r,supreg) 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),supreg,
getsupreg(oper[1]^.ref^.base),
getsupreg(oper[1]^.ref^.index),
unusedregsint);
rgget(list,pos,R_SUBWHOLE,helpreg);
spill_registers := true;
if wasload then
if oper[1]^.typ=top_const then
begin
helpins:=spilling_create_loadstore(opcode,helpreg,oper[1]^.ref^);
loadref(1,spilltemplist[supreg]);
opcode := op;
// Example:
// mov r20d, 1 ; r20d must be spilled into -60(r1)
//
// Change into:
//
// mov r21d, 1
// st? r21d, -60(r1)
//
pos := get_insert_pos(tai(previous),supreg,
RS_INVALID,
RS_INVALID,
unusedregsint);
rgget(list,pos,R_SUBWHOLE,helpreg);
spill_registers := true;
helpins:=spilling_create_store(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),unusedregsint);
// list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);}
end
else
helpins:=spilling_create_loadstore(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),unusedregsint);
{ list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);}
else if oper[1]^.typ=top_ref 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),supreg,
getsupreg(oper[1]^.ref^.base),
getsupreg(oper[1]^.ref^.index),
unusedregsint);
rgget(list,pos,R_SUBWHOLE,helpreg);
spill_registers := true;
if wasload then
begin
helpins:=spilling_create_loadstore(opcode,helpreg,oper[1]^.ref^);
loadref(1,spilltemplist[supreg]);
opcode := op;
end
else
helpins:=spilling_create_loadstore(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),unusedregsint);
// list.insertafter(tai_comment.Create(strpnew('Spilling!')),helpins);}
end;
end;
{ oper[1] can also be ref in case of "lis r3,symbol@ha" or so }
if not((oper[1]^.typ=top_ref) and
spilling_decode_loadstore(opcode,op,wasload)) then
Exit;
{ now the registers used in the reference }
{ a) base }
supreg := getsupreg(oper[1]^.ref^.base);
@ -2188,8 +2227,10 @@ implementation
end.
{
$Log$
Revision 1.56 2003-12-01 18:43:31 peter
* s128real type is not compatible with s80real
Revision 1.57 2003-12-03 17:39:04 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.55 2003/11/12 16:05:39 florian
* assembler readers OOPed

View File

@ -309,6 +309,11 @@ implementation
begin
counterpart := A_STR;
end;
A_STR:
begin
wasload:=false;
counterpart := A_LDR;
end;
A_LDM:
internalerror(2003070602);
else
@ -369,7 +374,12 @@ implementation
end.
{
$Log$
Revision 1.16 2003-11-30 19:35:29 florian
Revision 1.17 2003-12-03 17:39:05 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.16 2003/11/30 19:35:29 florian
* fixed several arm related problems
Revision 1.15 2003/11/29 17:36:56 peter

View File

@ -43,6 +43,7 @@ unit cgcpu;
procedure init_register_allocators;override;
procedure done_register_allocators;override;
procedure ungetreference(list:Taasmoutput;const r:Treference);override;
function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
@ -133,6 +134,15 @@ unit cgcpu;
procinfo,cpupi;
procedure tcgarm.ungetreference(list:Taasmoutput;const r:Treference);
begin
if r.base<>NR_NO then
ungetregister(list,r.base);
if r.index<>NR_NO then
ungetregister(list,r.index);
end;
procedure tcgarm.init_register_allocators;
begin
rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
@ -887,7 +897,7 @@ unit cgcpu;
reference_reset(ref);
ref.index:=NR_STACK_POINTER_REG;
ref.addressmode:=AM_PREINDEXED;
list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R12,RS_R15]),PF_FD));
list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R12,RS_R14,RS_R15]),PF_DB));
list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
@ -919,7 +929,7 @@ unit cgcpu;
{ restore int registers and return }
reference_reset(ref);
ref.index:=NR_FRAME_POINTER_REG;
list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_EA));
list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_DB));
end;
end;
@ -944,18 +954,34 @@ unit cgcpu;
begin
if tmpref.shiftmode<>SM_None then
internalerror(200308294);
if tmpref.signindex<0 then
internalerror(200312023);
tmpref.base:=tmpref.index;
tmpref.index:=NR_NO;
end;
if assigned(tmpref.symbol) or
not(is_shifter_const(dword(tmpref.offset),b)) or
((tmpref.base<>NR_NO) and (tmpref.index<>NR_NO)) then
not((is_shifter_const(dword(tmpref.offset),b)) or
(is_shifter_const(dword(-tmpref.offset),b))
) then
fixref(list,tmpref);
{ expect a base here }
if tmpref.base=NR_NO then
internalerror(200312022);
if tmpref.index<>NR_NO then
begin
{!!!!!!!}
if tmpref.shiftmode<>SM_None then
internalerror(200312021);
if tmpref.signindex<0 then
list.concat(taicpu.op_reg_reg_reg(A_SUB,r,tmpref.base,tmpref.index))
else
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,tmpref.base,tmpref.index));
if tmpref.offset>0 then
list.concat(taicpu.op_reg_reg_const(A_ADD,r,r,tmpref.offset))
else if tmpref.offset<0 then
list.concat(taicpu.op_reg_reg_const(A_SUB,r,r,-tmpref.offset));
end
else
begin
@ -1294,7 +1320,12 @@ begin
end.
{
$Log$
Revision 1.25 2003-11-30 19:35:29 florian
Revision 1.26 2003-12-03 17:39:05 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.25 2003/11/30 19:35:29 florian
* fixed several arm related problems
Revision 1.24 2003/11/24 15:17:37 florian

View File

@ -293,11 +293,11 @@ unit cpupara;
end;
if side=calleeside then
begin
{$warning FIXME Calleeside offset needs to be calculated}
{!!!!!!
if (paraloc.loc = LOC_REFERENCE) then
paraloc.reference.offset := tvarsym(hp.parasym).adjusted_address;
}
if paraloc.loc=LOC_REFERENCE then
begin
paraloc.reference.index:=NR_FRAME_POINTER_REG;
inc(paraloc.reference.offset,4);
end;
end;
hp.paraloc[side]:=paraloc;
hp:=tparaitem(hp.next);
@ -336,7 +336,12 @@ begin
end.
{
$Log$
Revision 1.9 2003-11-07 15:58:32 florian
Revision 1.10 2003-12-03 17:39:05 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.9 2003/11/07 15:58:32 florian
* Florian's culmutative nr. 1; contains:
- invalid calling conventions for a certain cpu are rejected
- arm softfloat calling conventions

View File

@ -107,7 +107,15 @@ unit cpupi;
procedure tarmprocinfo.set_first_temp_offset;
begin
tg.setfirsttemp(0);
{ We allocate enough space to save all registers because we can't determine
the necessary space because the used registers aren't known before
secondpass is run. Even worse, patching
the local offsets after generating the code could cause trouble because
"shifter" constants could change to non-"shifter" constants. This
is especially a problem when taking the address of a local. For now,
this extra memory should hurt less than generating all local contants with offsets
>256 as non shifter constants }
tg.setfirsttemp(-12-28);
end;
procedure tarmprocinfo.allocate_push_parasize(size:longint);
@ -120,7 +128,7 @@ unit cpupi;
function tarmprocinfo.calc_stackframe_size:longint;
begin
{ align to 4 bytes at least }
result:=Align(tg.direction*tg.lasttemp,max(aktalignment.localalignmin,4));
result:=Align(tg.direction*tg.lasttemp+maxpushedparasize,max(aktalignment.localalignmin,4));
end;
@ -129,7 +137,12 @@ begin
end.
{
$Log$
Revision 1.4 2003-11-30 19:35:29 florian
Revision 1.5 2003-12-03 17:39:05 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.4 2003/11/30 19:35:29 florian
* fixed several arm related problems
Revision 1.3 2003/11/24 15:17:37 florian

View File

@ -150,16 +150,16 @@ Unit raarmgas;
Procedure tarmattreader.BuildReference(oper : tarmoperand);
procedure Consume_RParen;
procedure Consume_RBracket;
begin
if actasmtoken <> AS_RPAREN then
if actasmtoken<>AS_RBRACKET then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
end
else
begin
Consume(AS_RPAREN);
Consume(AS_RBRACKET);
if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
Begin
Message(asmr_e_invalid_reference_syntax);
@ -168,112 +168,47 @@ Unit raarmgas;
end;
end;
var
l : longint;
procedure read_index;
begin
Consume(AS_COMMA);
if actasmtoken=AS_REGISTER then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
end;
end;
begin
Consume(AS_LPAREN);
Case actasmtoken of
AS_HASH: { Constant expression }
Begin
Consume(AS_HASH);
BuildConstantOperand(oper);
end;
AS_DOLLAR: { Constant expression }
Begin
Consume(AS_DOLLAR);
BuildConstantOperand(oper);
end;
AS_INTNUM,
AS_MINUS,
AS_PLUS:
Begin
{ offset(offset) is invalid }
If oper.opr.Ref.Offset <> 0 Then
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(true);
End
Else
Begin
oper.opr.Ref.Offset:=BuildConstExpression(false,true);
Consume_RParen;
end;
exit;
End;
AS_REGISTER: { (reg ... }
Begin
if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
message(asmr_e_cannot_index_relative_var);
oper.opr.ref.base:=actasmregister;
Consume(AS_REGISTER);
{ can either be a register or a right parenthesis }
{ (reg) }
if actasmtoken=AS_RPAREN then
Begin
Consume_RParen;
exit;
end;
{ (reg,reg .. }
Consume(AS_COMMA);
if actasmtoken=AS_REGISTER then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
Consume_RParen;
end
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end; {end case }
AS_ID:
Begin
ReadSym(oper);
{ add a constant expression? }
if (actasmtoken=AS_PLUS) then
begin
l:=BuildConstExpression(true,true);
case oper.opr.typ of
OPR_CONSTANT :
inc(oper.opr.val,l);
OPR_LOCAL :
inc(oper.opr.localsymofs,l);
OPR_REFERENCE :
inc(oper.opr.ref.offset,l);
else
internalerror(200309202);
end;
end;
Consume(AS_RPAREN);
End;
AS_COMMA: { (, ... can either be scaling, or index }
Begin
Consume(AS_COMMA);
{ Index }
if (actasmtoken=AS_REGISTER) then
Begin
oper.opr.ref.index:=actasmregister;
Consume(AS_REGISTER);
{ check for scaling ... }
Consume_RParen;
end
else
begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end;
Consume(AS_LBRACKET);
if actasmtoken=AS_REGISTER then
begin
oper.opr.ref.base:=actasmregister;
Consume(AS_REGISTER);
{ can either be a register or a right parenthesis }
{ (reg) }
if actasmtoken=AS_RBRACKET then
Begin
Consume_RBracket;
oper.opr.ref.addressmode:=AM_POSTINDEXED;
if actasmtoken=AS_COMMA then
read_index;
exit;
end;
if actasmtoken=AS_COMMA then
read_index;
if actasmtoken=AS_NOT then
begin
consume(AS_NOT);
oper.opr.ref.addressmode:=AM_PREINDEXED;
end;
end {end case }
else
Begin
Message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
end;
end;
end;
@ -391,7 +326,7 @@ Unit raarmgas;
Begin
expr:='';
case actasmtoken of
AS_LPAREN: { Memory reference or constant expression }
AS_LBRACKET: { Memory reference or constant expression }
Begin
oper.InitRef;
BuildReference(oper);
@ -675,6 +610,21 @@ Unit raarmgas;
actcondition:=C_None;
{ first, handle B else BLS is read wrong }
if ((hs[1]='B') and (length(hs)=3)) then
begin
for icond:=low(tasmcond) to high(tasmcond) do
begin
if copy(hs,2,3)=uppercond2str[icond] then
begin
actopcode:=A_B;
actasmtoken:=AS_OPCODE;
actcondition:=icond;
is_asmopcode:=true;
exit;
end;
end;
end;
maxlen:=max(length(hs),5);
for j:=maxlen downto 1 do
begin
@ -755,6 +705,7 @@ Unit raarmgas;
}
instr.ConcatInstruction(curlist);
instr.Free;
actoppostfix:=PF_None;
end;
@ -783,7 +734,12 @@ initialization
end.
{
$Log$
Revision 1.3 2003-11-24 15:17:37 florian
Revision 1.4 2003-12-03 17:39:05 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.3 2003/11/24 15:17:37 florian
* changed some types to prevend range check errors
Revision 1.2 2003/11/21 16:29:26 florian

View File

@ -1061,6 +1061,7 @@ implementation
p:=_asm_statement;
{$ifndef sparc}
{$ifndef arm}
if (po_assembler in current_procinfo.procdef.procoptions) then
begin
{ set the framepointer to esp for assembler functions when the
@ -1085,6 +1086,7 @@ implementation
current_procinfo.framepointer:=NR_STACK_POINTER_REG;
end;
end;
{$endif arm}
{$endif sparc}
{ Flag the result as assigned when it is returned in a
@ -1104,7 +1106,12 @@ implementation
end.
{
$Log$
Revision 1.122 2003-11-12 16:05:39 florian
Revision 1.123 2003-12-03 17:39:04 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.122 2003/11/12 16:05:39 florian
* assembler readers OOPed
+ typed currency constants
+ typed 128 bit float constants if the CPU supports it

View File

@ -47,7 +47,8 @@ unit raatt;
AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
AS_REALNUM,AS_COMMA,AS_LPAREN,
AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,AS_HASH,AS_LSBRACKET,AS_RSBRACKET,
AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
AS_HASH,AS_LSBRACKET,AS_RSBRACKET,AS_LBRACKET,AS_RBRACKET,
{------------------ Assembler directives --------------------}
AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
@ -68,7 +69,8 @@ unit raatt;
'','Label','LLabel','string','integer',
'float',',','(',
')',':','.','+','-','*',
';','identifier','register','opcode','/','$','#','{','}',
';','identifier','register','opcode','/','$',
'#','{','}','[',']',
'.byte','.word','.long','.quad','.globl',
'.align','.balign','.p2align','.ascii',
'.asciz','.lcomm','.comm','.single','.double','.tfloat',
@ -574,6 +576,19 @@ unit raatt;
exit;
end;
'[' :
begin
actasmtoken:=AS_LBRACKET;
c:=current_scanner.asmgetchar;
exit;
end;
']' :
begin
actasmtoken:=AS_RBRACKET;
c:=current_scanner.asmgetchar;
exit;
end;
{$ifdef arm}
// the arm assembler uses { ... } for register sets
'{' :
@ -1455,7 +1470,12 @@ end.
{
$Log$
Revision 1.4 2003-11-29 16:27:19 jonas
Revision 1.5 2003-12-03 17:39:04 florian
* fixed several arm calling conventions issues
* fixed reference reading in the assembler reader
* fixed a_loadaddr_ref_reg
Revision 1.4 2003/11/29 16:27:19 jonas
* fixed several ppc assembler reader related problems
* local vars in assembler procedures now start at offset 4
* fixed second_int_to_bool (apparently an integer can be in LOC_JUMP??)