* fixed procedure entry/exit code

* started to fix reference handling
This commit is contained in:
florian 2003-08-29 21:36:28 +00:00
parent 04501b6fff
commit 301df6dab9
4 changed files with 317 additions and 57 deletions

View File

@ -42,6 +42,7 @@ uses
oppostfix : TOpPostfix; oppostfix : TOpPostfix;
roundingmode : troundingmode; roundingmode : troundingmode;
procedure loadshifterop(opidx:longint;const so:tshifterop); procedure loadshifterop(opidx:longint;const so:tshifterop);
procedure loadregset(opidx:longint;const s:tsupregset);
constructor op_none(op : tasmop); constructor op_none(op : tasmop);
constructor op_reg(op : tasmop;_op1 : tregister); constructor op_reg(op : tasmop;_op1 : tregister);
@ -50,6 +51,7 @@ uses
constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister); constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint); constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
constructor op_reg_regset(op:tasmop; _op1: tregister; _op2: tsupregset);
constructor op_const_const(op : tasmop;_op1,_op2 : longint); constructor op_const_const(op : tasmop;_op1,_op2 : longint);
@ -108,13 +110,30 @@ implementation
with oper[opidx] do with oper[opidx] do
begin begin
if typ<>top_shifterop then if typ<>top_shifterop then
new(shifterop); begin
clearop(opidx);
new(shifterop);
end;
shifterop^:=so; shifterop^:=so;
typ:=top_shifterop; typ:=top_shifterop;
end; end;
end; end;
procedure taicpu.loadregset(opidx:longint;const s:tsupregset);
begin
if opidx>=ops then
ops:=opidx+1;
with oper[opidx] do
begin
if typ<>top_regset then
clearop(opidx);
regset:=s;
typ:=top_regset;
end;
end;
{***************************************************************************** {*****************************************************************************
taicpu Constructors taicpu Constructors
*****************************************************************************} *****************************************************************************}
@ -167,6 +186,17 @@ implementation
end; end;
constructor taicpu.op_reg_regset(op:tasmop; _op1: tregister; _op2: tsupregset);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031208);
ops:=2;
loadreg(0,_op1);
loadregset(1,_op2);
end;
constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
begin begin
inherited create(op); inherited create(op);
@ -693,7 +723,11 @@ implementation
end. end.
{ {
$Log$ $Log$
Revision 1.6 2003-08-28 00:05:29 florian Revision 1.7 2003-08-29 21:36:28 florian
* fixed procedure entry/exit code
* started to fix reference handling
Revision 1.6 2003/08/28 00:05:29 florian
* today's arm patches * today's arm patches
Revision 1.5 2003/08/27 00:27:56 florian Revision 1.5 2003/08/27 00:27:56 florian

View File

@ -43,6 +43,10 @@ unit agarmgas;
var var
gas_reg2str : reg2strtable; gas_reg2str : reg2strtable;
const
gas_shiftmode2str : array[tshiftmode] of string[3] = (
'','lsl','lsr','asr','ror','rrx');
function gas_regnum_search(const s:string):Tnewregister; function gas_regnum_search(const s:string):Tnewregister;
function gas_regname(const r:Tnewregister):string; function gas_regname(const r:Tnewregister):string;
@ -77,50 +81,62 @@ unit agarmgas;
); );
function getreferencestring(var ref : treference) : string; function getreferencestring(var ref : treference) : string;
var var
s : string; s : string;
begin nobase,noindex : boolean;
with ref do begin
begin with ref do
inc(offset,offsetfixup); begin
inc(offset,offsetfixup);
if not assigned(symbol) then noindex:=(index.enum=R_NO) or ((index.enum=R_INTREGISTER) and (index.number=NR_NO));
s := '[' {$ifdef extdebug}
else nobase:=(base.enum=R_NO) or ((base.enum=R_INTREGISTER) and (base.number=NR_NO));
s:='['+symbol.name; //!!!! if nobase then
//!!!! internalerror(200308292);
if offset<0 then // !!! if (not(noindex) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
s:=s+tostr(offset) // !!! internalerror(200308293);
else {$endif extdebug}
if (offset>0) then if base.enum=R_INTREGISTER then
begin s:='['+gas_regname(base.number)
if assigned(symbol) then else
s:=s+'+'+tostr(offset) s:='['+gas_reg2str[base.enum];
else if addressmode=AM_POSTINDEXED then
s:=s+tostr(offset); s:=s+']';
end;
if (index.enum=R_NO) and (base.enum<>R_NO) then if not(noindex) then
begin begin
if offset=0 then if signindex<0 then
begin s:=s+', -'
if assigned(symbol) then else
s:=s+'+0' s:=s+', ';
else
s:=s+'0'; if index.enum=R_INTREGISTER then
end; s:=s+gas_regname(index.number)
if base.enum=R_INTREGISTER then else
s:=s+'('+gas_regname(base.number)+')' s:=s+gas_reg2str[index.enum];
else
s:=s+'('+gas_reg2str[base.enum]+')'; if shiftmode<>SM_None then
end s:=s+' ,'+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
else if (index.enum<>R_NO) and (base.enum<>R_NO) and (offset=0) then end
s:=s+std_reg2str[base.enum]+','+std_reg2str[index.enum] else
else if ((index.enum<>R_NO) or (base.enum<>R_NO)) then begin
internalerror(19992); { handle symbol and index }
end; if offset<>0 then
getreferencestring:=s; s:=s+', #'+tostr(offset);
end; { !!!!!}
end;
case addressmode of
AM_OFFSET:
s:=s+']';
AM_PREINDEXED:
s:=s+']!';
end;
end;
getreferencestring:=s;
end;
function getopstr_jmp(const o:toper) : string; function getopstr_jmp(const o:toper) : string;
@ -170,6 +186,8 @@ unit agarmgas;
function getopstr(const o:toper) : string; function getopstr(const o:toper) : string;
var var
hs : string; hs : string;
first : boolean;
r : tnewregister;
begin begin
case o.typ of case o.typ of
top_reg: top_reg:
@ -194,6 +212,20 @@ unit agarmgas;
end; end;
top_const: top_const:
getopstr:='#'+tostr(longint(o.val)); getopstr:='#'+tostr(longint(o.val));
top_regset:
begin
getopstr:='{';
first:=true;
for r:=RS_R0 to RS_R15 do
if r in o.regset then
begin
if not(first) then
getopstr:=getopstr+',';
getopstr:=getopstr+'r'+tostr(r-RS_R0);
first:=false;
end;
getopstr:=getopstr+'}';
end;
top_ref: top_ref:
getopstr:=getreferencestring(o.ref^); getopstr:=getreferencestring(o.ref^);
top_symbol: top_symbol:
@ -225,9 +257,9 @@ unit agarmgas;
sep: string[3]; sep: string[3];
begin begin
op:=taicpu(hp).opcode; op:=taicpu(hp).opcode;
{
if is_calljmp(op) then if is_calljmp(op) then
begin begin
{
{ direct BO/BI in op[0] and op[1] not supported, put them in condition! } { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
case op of case op of
A_B,A_BA,A_BL,A_BLA: A_B,A_BA,A_BL,A_BLA:
@ -240,12 +272,12 @@ unit agarmgas;
if (taicpu(hp).oper[0].typ <> top_none) then if (taicpu(hp).oper[0].typ <> top_none) then
s:=s+getopstr_jmp(taicpu(hp).oper[0]); s:=s+getopstr_jmp(taicpu(hp).oper[0]);
}
end end
else else
}
{ process operands } { process operands }
begin begin
s:=#9+std_op2str[op]; s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix];
if taicpu(hp).ops<>0 then if taicpu(hp).ops<>0 then
begin begin
{ {
@ -292,7 +324,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.5 2003-08-28 13:26:10 florian Revision 1.6 2003-08-29 21:36:28 florian
* fixed procedure entry/exit code
* started to fix reference handling
Revision 1.5 2003/08/28 13:26:10 florian
* another couple of arm fixes * another couple of arm fixes
Revision 1.4 2003/08/28 00:05:29 florian Revision 1.4 2003/08/28 00:05:29 florian

View File

@ -54,6 +54,7 @@ unit cgcpu;
size: tcgsize; src1, src2, dst: tregister); override; size: tcgsize; src1, src2, dst: tregister); override;
{ move instructions } { move instructions }
procedure handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);override; procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);override;
procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override; procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override; procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
@ -267,7 +268,7 @@ unit cgcpu;
tmpreg : tregister; tmpreg : tregister;
so : tshifterop; so : tshifterop;
begin begin
if is_shifter_const(a,shift) and (op<>OP_MUL) then if is_shifter_const(a,shift) and (not(op in [OP_IMUL,OP_MUL])) then
case op of case op of
OP_NEG,OP_NOT, OP_NEG,OP_NOT,
OP_DIV,OP_IDIV: OP_DIV,OP_IDIV:
@ -316,6 +317,7 @@ unit cgcpu;
size: tcgsize; src1, src2, dst: tregister); size: tcgsize; src1, src2, dst: tregister);
var var
so : tshifterop; so : tshifterop;
tmpreg : tregister;
begin begin
case op of case op of
OP_NEG: OP_NEG:
@ -345,6 +347,23 @@ unit cgcpu;
so.shiftertype:=SO_LSL; so.shiftertype:=SO_LSL;
list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src1,so)); list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src1,so));
end; end;
OP_IMUL,
OP_MUL:
begin
{ the arm doesn't allow that rd and rm are the same }
if dst.number=src2.number then
begin
if src1.number<>src2.number then
list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
else
begin
writeln('Warning: Fix MUL');
list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
end;
end
else
list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
end;
else else
list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1)); list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
end; end;
@ -398,13 +417,128 @@ unit cgcpu;
end; end;
procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
var
tmpreg : tregister;
tmpref : treference;
instr : taicpu;
begin
tmpreg.enum:=R_INTREGISTER;
tmpreg.number:=NR_NO;
{ Be sure to have a base register }
if (ref.base.number=NR_NO) then
begin
if ref.shiftmode<>SM_None then
internalerror(200308294);
ref.base:=ref.index;
ref.index.number:=NR_NO;
end;
{ When need to use SETHI, do it first }
if assigned(ref.symbol) or
(ref.offset<-4095) or
(ref.offset>4095) then
begin
{
tmpreg:=rg.getregisterint(list,OS_INT);
reference_reset(tmpref);
tmpref.symbol:=ref.symbol;
tmpref.offset:=ref.offset;
tmpref.symaddr:=refs_hi;
list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
{ Load the low part is left }
{$warning TODO Maybe not needed to load symbol}
tmpref.symaddr:=refs_lo;
list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
{ The offset and symbol are loaded, reset in reference }
ref.offset:=0;
ref.symbol:=nil;
{ Only an index register or offset is allowed }
if tmpreg.number<>NR_NO then
begin
if (ref.index.number<>NR_NO) then
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
ref.index:=tmpreg;
end
else
begin
if ref.base.number<>NR_NO then
ref.index:=tmpreg
else
ref.base:=tmpreg;
end;
end;
}
end;
{
if (ref.base.number<>NR_NO) then
begin
if (ref.index.number<>NR_NO) and
((ref.offset<>0) or assigned(ref.symbol)) then
begin
if tmpreg.number=NR_NO then
tmpreg:=rg.getregisterint(list,OS_INT);
if (ref.index.number<>NR_NO) then
begin
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
ref.index.number:=NR_NO;
end;
end;
end;
}
instr:=taicpu.op_reg_ref(op,reg,ref);
instr.oppostfix:=oppostfix;
list.concat(instr);
if (tmpreg.number<>NR_NO) then
rg.ungetregisterint(list,tmpreg);
end;
procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference); procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
var
oppostfix:toppostfix;
begin begin
case ToSize of
{ signed integer registers }
OS_8,
OS_S8:
oppostfix:=PF_B;
OS_16,
OS_S16:
oppostfix:=PF_H;
OS_32,
OS_S32:
oppostfix:=PF_None;
else
InternalError(200308295);
end;
handle_load_store(list,A_STR,oppostfix,reg,ref);
end; end;
procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister); procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
var
oppostfix:toppostfix;
begin begin
case ToSize of
{ signed integer registers }
OS_8:
oppostfix:=PF_B;
OS_S8:
oppostfix:=PF_SB;
OS_16:
oppostfix:=PF_H;
OS_S16:
oppostfix:=PF_SH;
OS_32,
OS_S32:
oppostfix:=PF_None;
else
InternalError(200308291);
end;
handle_load_store(list,A_LDR,oppostfix,reg,ref);
end; end;
@ -522,12 +656,59 @@ unit cgcpu;
procedure tcgarm.g_stackframe_entry(list : taasmoutput;localsize : longint); procedure tcgarm.g_stackframe_entry(list : taasmoutput;localsize : longint);
var
rip,rsp,rfp : tregister;
instr : taicpu;
begin begin
rsp.enum:=R_INTREGISTER;
rsp.number:=NR_STACK_POINTER_REG;
a_reg_alloc(list,rsp);
rfp.enum:=R_INTREGISTER;
rfp.number:=NR_FRAME_POINTER_REG;
a_reg_alloc(list,rfp);
rip.enum:=R_INTREGISTER;
rip.number:=NR_R12;
a_reg_alloc(list,rip);
list.concat(taicpu.op_reg_reg(A_MOV,rip,rsp));
{ restore int registers and return }
instr:=taicpu.op_reg_regset(A_STM,rsp,rg.used_in_proc_int-[RS_R0..RS_R4]+[RS_R11,RS_R12,RS_R15]);
instr.oppostfix:=PF_FD;
list.concat(instr);
list.concat(taicpu.op_reg_reg_const(A_SUB,rfp,rip,4));
a_reg_alloc(list,rip);
{ allocate necessary stack size }
list.concat(taicpu.op_reg_reg_const(A_SUB,rsp,rsp,4));
end; end;
procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword); procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword);
var
r1,r2 : tregister;
instr : taicpu;
begin begin
if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
begin
r1.enum:=R_INTREGISTER;
r1.number:=NR_R15;
r2.enum:=R_INTREGISTER;
r2.number:=NR_R14;
list.concat(taicpu.op_reg_reg(A_MOV,r1,r2));
end
else
begin
r1.enum:=R_INTREGISTER;
r1.number:=NR_R11;
{ restore int registers and return }
instr:=taicpu.op_reg_regset(A_LDM,r1,rg.used_in_proc_int-[RS_R0..RS_R4]+[RS_R11,RS_R13,RS_R15]);
instr.oppostfix:=PF_EA;
list.concat(instr);
end;
end; end;
@ -617,7 +798,11 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.7 2003-08-28 13:26:10 florian Revision 1.8 2003-08-29 21:36:28 florian
* fixed procedure entry/exit code
* started to fix reference handling
Revision 1.7 2003/08/28 13:26:10 florian
* another couple of arm fixes * another couple of arm fixes
Revision 1.6 2003/08/28 00:05:29 florian Revision 1.6 2003/08/28 00:05:29 florian

View File

@ -134,7 +134,7 @@ uses
last_supreg = RS_R15; last_supreg = RS_R15;
{ registers which may be destroyed by calls } { registers which may be destroyed by calls }
VOLATILE_INTREGISTERS = [RS_R0..RS_R3]; VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
VOLATILE_FPUREGISTERS = [R_F0..R_F3]; VOLATILE_FPUREGISTERS = [R_F0..R_F3];
{ Number of first and last imaginary register. } { Number of first and last imaginary register. }
@ -201,7 +201,7 @@ uses
{ load/store } { load/store }
PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T, PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
{ multiple load/store address modes } { multiple load/store address modes }
PF_IA,PF_IB,PF_DA,PF_DB,PF_DF,PF_FA,PF_ED,PF_EA PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
); );
TRoundingMode = (RM_None,RM_P,RM_M,RM_Z); TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
@ -211,7 +211,7 @@ uses
's', 's',
'd','e','p','ep', 'd','e','p','ep',
'b','sb','bt','h','sh','t', 'b','sb','bt','h','sh','t',
'ia','ib','da','db','df','fa','ed','ea'); 'ia','ib','da','db','fd','fa','ed','ea');
roundingmode2str : array[TRoundingMode] of string[1] = ('', roundingmode2str : array[TRoundingMode] of string[1] = ('',
'p','m','z'); 'p','m','z');
@ -253,14 +253,15 @@ uses
trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup); trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED); taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
tshiftmode = (SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX); tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
{ reference record } { reference record }
preference = ^treference; preference = ^treference;
treference = packed record treference = packed record
base, base,
index : tregister; index : tregister;
scalefactor : byte; shiftimm : byte;
signindex : shortint;
offset : longint; offset : longint;
symbol : tasmsymbol; symbol : tasmsymbol;
offsetfixup : longint; offsetfixup : longint;
@ -483,8 +484,8 @@ uses
Constants Constants
*****************************************************************************} *****************************************************************************}
firstsaveintreg = R_R4; firstsaveintreg = RS_R4;
lastsaveintreg = R_R10; lastsaveintreg = RS_R10;
firstsavefpureg = R_F4; firstsavefpureg = R_F4;
lastsavefpureg = R_F7; lastsavefpureg = R_F7;
firstsavemmreg = R_S16; firstsavemmreg = R_S16;
@ -690,7 +691,11 @@ uses
end. end.
{ {
$Log$ $Log$
Revision 1.8 2003-08-28 00:05:29 florian Revision 1.9 2003-08-29 21:36:28 florian
* fixed procedure entry/exit code
* started to fix reference handling
Revision 1.8 2003/08/28 00:05:29 florian
* today's arm patches * today's arm patches
Revision 1.7 2003/08/25 23:20:38 florian Revision 1.7 2003/08/25 23:20:38 florian