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:
svenbarth 2013-10-02 20:14:16 +00:00
parent c108a24cc8
commit 0cb2bda0a5
2 changed files with 39 additions and 12 deletions

View File

@ -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

View File

@ -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