From 0cb2bda0a58fc62963d99555e8e67cbdaca1a71b Mon Sep 17 00:00:00 2001 From: svenbarth Date: Wed, 2 Oct 2013 20:14:16 +0000 Subject: [PATCH] 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 - --- compiler/m68k/cgcpu.pas | 44 +++++++++++++++++++++++++++++---------- compiler/m68k/cpupara.pas | 7 ++++++- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas index f5a48d4ec2..b2d8e32897 100644 --- a/compiler/m68k/cgcpu.pas +++ b/compiler/m68k/cgcpu.pas @@ -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]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]1 then begin - if (orglen0) 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 (orglen0) 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 diff --git a/compiler/m68k/cpupara.pas b/compiler/m68k/cpupara.pas index 233232c081..0660e8f750 100644 --- a/compiler/m68k/cpupara.pas +++ b/compiler/m68k/cpupara.pas @@ -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