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 else
pushsize:=int_cgsize(cgpara.alignment); 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; ref.direction := dir_dec;
if tcgsize2size[paraloc^.size]<cgpara.alignment then 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); procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
var var
href : treference; href : treference;
size : tcgsize;
begin begin
href := ref; href := ref;
fixref(list,href); fixref(list,href);
{$ifdef DEBUG_CHARLIE} {$ifdef DEBUG_CHARLIE}
list.concat(tai_comment.create(strpnew('a_load_reg_ref'))); list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
{$endif DEBUG_CHARLIE} {$endif DEBUG_CHARLIE}
if tcgsize2size[fromsize]<tcgsize2size[tosize] then
size:=fromsize
else
size:=tosize;
{ move to destination reference } { 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; end;
@ -789,6 +794,7 @@ unit cgcpu;
var var
aref: treference; aref: treference;
bref: treference; bref: treference;
tmpref : treference;
dofix : boolean; dofix : boolean;
hreg: TRegister; hreg: TRegister;
begin begin
@ -799,6 +805,16 @@ unit cgcpu;
{$ifdef DEBUG_CHARLIE} {$ifdef DEBUG_CHARLIE}
// writeln('a_load_ref_ref'); // writeln('a_load_ref_ref');
{$endif DEBUG_CHARLIE} {$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 } { Coldfire dislikes certain move combinations }
if current_settings.cputype in cpu_coldfire then if current_settings.cputype in cpu_coldfire then
begin begin
@ -845,8 +861,9 @@ unit cgcpu;
if dofix then if dofix then
begin begin
hreg:=getaddressregister(list); hreg:=getaddressregister(list);
list.concat(taicpu.op_ref_reg(A_LEA,S_L,bref,hreg)); reference_reset_base(tmpref,hreg,0,0);
list.concat(taicpu.op_reg_ref(A_MOVE,S_L{TCGSize2OpSize[fromsize]},hreg,bref)); 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; exit;
end; end;
end; end;
@ -871,10 +888,15 @@ unit cgcpu;
procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister); procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
var var
href : treference; href : treference;
size : tcgsize;
begin begin
href:=ref; href:=ref;
fixref(list,href); 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 } { extend the value in the register }
sign_extend(list, fromsize, register); sign_extend(list, fromsize, register);
end; end;
@ -1554,14 +1576,14 @@ unit cgcpu;
{ move a word } { move a word }
if len>1 then if len>1 then
begin begin
if (orglen<source.alignment) and if (orglen<sizeof(aint)) and
(source.base=NR_FRAME_POINTER_REG) and (source.base=NR_FRAME_POINTER_REG) and
(source.offset>0) then (source.offset>0) then
{ copy of param to local location } { copy of param to local location }
alignsize:=int_cgsize(source.alignment) alignsize:=OS_INT
else else
alignsize:=OS_16; 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); a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
inc(srcref.offset,2); inc(srcref.offset,2);
inc(dstref.offset,2); inc(dstref.offset,2);
@ -1570,14 +1592,14 @@ unit cgcpu;
{ move a single byte } { move a single byte }
if len>0 then if len>0 then
begin begin
if (orglen<source.alignment) and if (orglen<sizeof(aint)) and
(source.base=NR_FRAME_POINTER_REG) and (source.base=NR_FRAME_POINTER_REG) and
(source.offset>0) then (source.offset>0) then
{ copy of param to local location } { copy of param to local location }
alignsize:=int_cgsize(source.alignment) alignsize:=OS_INT
else else
alignsize:=OS_8; 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); a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
end end
end end

View File

@ -395,8 +395,13 @@ unit cpupara;
writeln('loc reference'); writeln('loc reference');
{$endif DEBUG_CHARLIE} {$endif DEBUG_CHARLIE}
paraloc^.loc:=LOC_REFERENCE; paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc); 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 if (side = callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG paraloc^.reference.index:=NR_STACK_POINTER_REG
else else