mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 18:09:27 +02:00
Correctly handle loads of different sizes. Fixes 1 test. Might be more, but some other bugs might hide it.
m68k/cgcpu.pas, tcg68k: * a_load_ref_cgpara: use pashsize instead of paraloc^.size as the latter could be OS_NO and thus a "move" instead of a "move.x" will be generated resulting in a word move when a long or byte move might have been necessary * a_load_reg_ref: use the smallest size when moving the value to a reference * a_load_ref_ref: when the size is different always use a temporary register for a ref to ref move * a_load_ref_ref: when doing a fixed move for Coldfire use the correct ref (that's another embarrasing error...) and size (fixes usage of String[Index] for a const array parameter) * a_load_ref_reg: use the smallest size when moving the value from a reference * g_concatcopy: don't use source.alignment as that doesn't contain the correct value and also load the value into the temp register using the correct size (fixes passing of small values as parameters, like chars) git-svn-id: trunk@25624 -
This commit is contained in:
parent
c108a24cc8
commit
0cb2bda0a5
@ -327,7 +327,7 @@ unit cgcpu;
|
||||
else
|
||||
pushsize:=int_cgsize(cgpara.alignment);
|
||||
|
||||
reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[paraloc^.size]);
|
||||
reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[pushsize]);
|
||||
ref.direction := dir_dec;
|
||||
|
||||
if tcgsize2size[paraloc^.size]<cgpara.alignment then
|
||||
@ -774,14 +774,19 @@ unit cgcpu;
|
||||
procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
|
||||
var
|
||||
href : treference;
|
||||
size : tcgsize;
|
||||
begin
|
||||
href := ref;
|
||||
fixref(list,href);
|
||||
{$ifdef DEBUG_CHARLIE}
|
||||
list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
|
||||
{$endif DEBUG_CHARLIE}
|
||||
if tcgsize2size[fromsize]<tcgsize2size[tosize] then
|
||||
size:=fromsize
|
||||
else
|
||||
size:=tosize;
|
||||
{ move to destination reference }
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[size],register,href));
|
||||
end;
|
||||
|
||||
|
||||
@ -789,6 +794,7 @@ unit cgcpu;
|
||||
var
|
||||
aref: treference;
|
||||
bref: treference;
|
||||
tmpref : treference;
|
||||
dofix : boolean;
|
||||
hreg: TRegister;
|
||||
begin
|
||||
@ -799,6 +805,16 @@ unit cgcpu;
|
||||
{$ifdef DEBUG_CHARLIE}
|
||||
// writeln('a_load_ref_ref');
|
||||
{$endif DEBUG_CHARLIE}
|
||||
if fromsize<>tosize then
|
||||
begin
|
||||
{ if we need to change the size then always use a temporary
|
||||
register }
|
||||
hreg:=getintregister(list,fromsize);
|
||||
list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
|
||||
sign_extend(list,fromsize,hreg);
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,bref));
|
||||
exit;
|
||||
end;
|
||||
{ Coldfire dislikes certain move combinations }
|
||||
if current_settings.cputype in cpu_coldfire then
|
||||
begin
|
||||
@ -845,8 +861,9 @@ unit cgcpu;
|
||||
if dofix then
|
||||
begin
|
||||
hreg:=getaddressregister(list);
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,S_L,bref,hreg));
|
||||
list.concat(taicpu.op_reg_ref(A_MOVE,S_L{TCGSize2OpSize[fromsize]},hreg,bref));
|
||||
reference_reset_base(tmpref,hreg,0,0);
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,S_L,aref,hreg));
|
||||
list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],tmpref,bref));
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
@ -871,10 +888,15 @@ unit cgcpu;
|
||||
procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
|
||||
var
|
||||
href : treference;
|
||||
size : tcgsize;
|
||||
begin
|
||||
href:=ref;
|
||||
fixref(list,href);
|
||||
list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
|
||||
if tcgsize2size[fromsize]<tcgsize2size[tosize] then
|
||||
size:=fromsize
|
||||
else
|
||||
size:=tosize;
|
||||
list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[size],href,register));
|
||||
{ extend the value in the register }
|
||||
sign_extend(list, fromsize, register);
|
||||
end;
|
||||
@ -1554,14 +1576,14 @@ unit cgcpu;
|
||||
{ move a word }
|
||||
if len>1 then
|
||||
begin
|
||||
if (orglen<source.alignment) and
|
||||
if (orglen<sizeof(aint)) and
|
||||
(source.base=NR_FRAME_POINTER_REG) and
|
||||
(source.offset>0) then
|
||||
{ copy of param to local location }
|
||||
alignsize:=int_cgsize(source.alignment)
|
||||
alignsize:=OS_INT
|
||||
else
|
||||
alignsize:=OS_16;
|
||||
a_load_ref_reg(list,alignsize,OS_16,srcref,hregister);
|
||||
a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
|
||||
a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
|
||||
inc(srcref.offset,2);
|
||||
inc(dstref.offset,2);
|
||||
@ -1570,14 +1592,14 @@ unit cgcpu;
|
||||
{ move a single byte }
|
||||
if len>0 then
|
||||
begin
|
||||
if (orglen<source.alignment) and
|
||||
if (orglen<sizeof(aint)) and
|
||||
(source.base=NR_FRAME_POINTER_REG) and
|
||||
(source.offset>0) then
|
||||
{ copy of param to local location }
|
||||
alignsize:=int_cgsize(source.alignment)
|
||||
alignsize:=OS_INT
|
||||
else
|
||||
alignsize:=OS_8;
|
||||
a_load_ref_reg(list,alignsize,OS_8,srcref,hregister);
|
||||
a_load_ref_reg(list,alignsize,alignsize,srcref,hregister);
|
||||
a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
|
||||
end
|
||||
end
|
||||
|
@ -395,8 +395,13 @@ unit cpupara;
|
||||
writeln('loc reference');
|
||||
{$endif DEBUG_CHARLIE}
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
|
||||
if paradef.typ<>orddef then
|
||||
paracgsize:=int_cgsize(paralen);
|
||||
if paracgsize=OS_NO then
|
||||
paraloc^.size:=OS_INT
|
||||
else
|
||||
paraloc^.size:=paracgsize;
|
||||
if (side = callerside) then
|
||||
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user