support sign/zero extension to subreg sizes, not just always to 32bit

git-svn-id: trunk@27117 -
This commit is contained in:
Károly Balogh 2014-03-12 18:27:50 +00:00
parent 73db4db6f8
commit c7d1cef334

View File

@ -101,6 +101,8 @@ unit cgcpu;
The new value is left in the same register. The new value is left in the same register.
} }
procedure sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister); procedure sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
procedure sign_extend(list: TAsmList;_oldsize : tcgsize; _newsize : tcgsize; reg: tregister);
procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel); procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
function force_to_dataregister(list: TAsmList; size: TCGSize; reg: TRegister): TRegister; function force_to_dataregister(list: TAsmList; size: TCGSize; reg: TRegister): TRegister;
procedure move_if_needed(list: TAsmList; size: TCGSize; src: TRegister; dest: TRegister); procedure move_if_needed(list: TAsmList; size: TCGSize; src: TRegister; dest: TRegister);
@ -835,16 +837,12 @@ 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);
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[size],register,href)); sign_extend(list, fromsize, tosize, register);
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],register,href));
end; end;
@ -866,7 +864,7 @@ unit cgcpu;
register } register }
hreg:=getintregister(list,fromsize); hreg:=getintregister(list,fromsize);
list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg)); list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
sign_extend(list,fromsize,hreg); sign_extend(list,fromsize,tosize,hreg);
list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,bref)); list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[tosize],hreg,bref));
exit; exit;
end; end;
@ -931,31 +929,22 @@ unit cgcpu;
instr : taicpu; instr : taicpu;
begin begin
{ move to destination register } { move to destination register }
instr:=taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2); instr:=taicpu.op_reg_reg(A_MOVE,TCGSize2OpSize[fromsize],reg1,reg2);
add_move_instruction(instr); add_move_instruction(instr);
list.concat(instr); list.concat(instr);
sign_extend(list, fromsize, tosize, reg2);
{ zero/sign extend register to 32-bit }
if tcgsize2size[fromsize]<tcgsize2size[tosize] then
sign_extend(list, fromsize, reg2);
end; end;
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);
if tcgsize2size[fromsize]<tcgsize2size[tosize] then list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
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 }
if tcgsize2size[fromsize]<tcgsize2size[tosize] then sign_extend(list, fromsize, tosize, register);
sign_extend(list, fromsize, register);
end; end;
@ -1899,15 +1888,32 @@ unit cgcpu;
tg.UnGetTemp(list,current_procinfo.save_regs_ref); tg.UnGetTemp(list,current_procinfo.save_regs_ref);
end; end;
procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; _newsize : tcgsize; reg: tregister);
procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
begin begin
case _newsize of
OS_S16, OS_16:
case _oldsize of case _oldsize of
{ sign extend }
OS_S8: OS_S8:
begin begin { 8 -> 16 bit sign extend }
if (isaddressregister(reg)) then if (isaddressregister(reg)) then
internalerror(20020729); internalerror(2014031201);
list.concat(taicpu.op_reg(A_EXT,S_W,reg));
end;
OS_8: { 8 -> 16 bit zero extend }
begin
if (current_settings.cputype in cpu_coldfire) then
{ ColdFire has no ANDI.W }
list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg))
else
list.concat(taicpu.op_const_reg(A_AND,S_W,$FF,reg));
end;
end;
OS_S32, OS_32:
case _oldsize of
OS_S8:
begin { 8 -> 32 bit sign extend }
if (isaddressregister(reg)) then
internalerror(2014031202);
if (current_settings.cputype = cpu_MC68000) then if (current_settings.cputype = cpu_MC68000) then
begin begin
list.concat(taicpu.op_reg(A_EXT,S_W,reg)); list.concat(taicpu.op_reg(A_EXT,S_W,reg));
@ -1915,31 +1921,36 @@ unit cgcpu;
end end
else else
begin begin
// list.concat(tai_comment.create(strpnew('sign extend byte'))); //list.concat(tai_comment.create(strpnew('sign extend byte')));
list.concat(taicpu.op_reg(A_EXTB,S_L,reg)); list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
end; end;
end; end;
OS_S16: OS_8: { 8 -> 32 bit zero extend }
begin
//list.concat(tai_comment.create(strpnew('zero extend byte')));
list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
end;
OS_S16: { 16 -> 32 bit sign extend }
begin begin
if (isaddressregister(reg)) then if (isaddressregister(reg)) then
internalerror(20020729); internalerror(2014031203);
// list.concat(tai_comment.create(strpnew('sign extend word'))); //list.concat(tai_comment.create(strpnew('sign extend word')));
list.concat(taicpu.op_reg(A_EXT,S_L,reg)); list.concat(taicpu.op_reg(A_EXT,S_L,reg));
end; end;
{ zero extend }
OS_8:
begin
// list.concat(tai_comment.create(strpnew('zero extend byte')));
list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
end;
OS_16: OS_16:
begin begin
// list.concat(tai_comment.create(strpnew('zero extend word'))); //list.concat(tai_comment.create(strpnew('zero extend byte')));
list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg)); list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
end; end;
end;
end; { otherwise the size is already correct } end; { otherwise the size is already correct }
end; end;
procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
begin
sign_extend(list, _oldsize, OS_INT, reg);
end;
procedure tcg68k.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel); procedure tcg68k.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
var var