Fix big endian issues

git-svn-id: trunk@21672 -
This commit is contained in:
pierre 2012-06-21 11:52:57 +00:00
parent aa8747f5c9
commit 74eb121d1c
2 changed files with 121 additions and 48 deletions

View File

@ -1337,6 +1337,7 @@ var
ra_save,framesave : taicpu;
fmask,mask : dword;
saveregs : tcpuregisterset;
StoreOp : TAsmOp;
href: treference;
usesfpr, usesgpr, gotgot : boolean;
reg : Tsuperregister;
@ -1368,6 +1369,8 @@ begin
fmask:=fmask or (1 shl ord(reg));
href.offset:=nextoffset;
lastfpuoffset:=nextoffset;
if cs_asm_source in current_settings.globalswitches then
helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_FPUREGISTER,reg,R_SUBFS))+' register saved.')));
helplist.concat(taicpu.op_reg_ref(A_SWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
inc(nextoffset,4);
end;
@ -1396,7 +1399,11 @@ begin
else if (reg=RS_R31) then
ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
else
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
begin
if cs_asm_source in current_settings.globalswitches then
helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))+' register saved.')));
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
end;
inc(nextoffset,4);
end;
end;
@ -1411,10 +1418,16 @@ begin
if (-LocalSize >= simm16lo) and (-LocalSize <= simm16hi) then
begin
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size')));
list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-LocalSize));
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('RA register saved.')));
list.concat(ra_save);
if assigned(framesave) then
begin
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Frame S8/FP register saved.')));
list.concat(framesave);
list.concat(Taicpu.op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,
NR_STACK_POINTER_REG,LocalSize));
@ -1422,14 +1435,22 @@ begin
end
else
begin
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size using R1 register')));
list.concat(Taicpu.Op_reg_const(A_LI,NR_R1,-LocalSize));
list.concat(Taicpu.Op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R1));
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('RA register saved.')));
list.concat(ra_save);
if assigned(framesave) then
begin
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Frame register saved.')));
list.concat(framesave);
list.concat(Taicpu.op_reg_reg_reg(A_SUB,NR_FRAME_POINTER_REG,
NR_STACK_POINTER_REG,NR_R3));
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Frame register updated to $SP+R1 value')));
list.concat(Taicpu.op_reg_reg_reg(A_ADDU,NR_FRAME_POINTER_REG,
NR_STACK_POINTER_REG,NR_R1));
end;
end;
@ -1449,11 +1470,47 @@ begin
//if current_procinfo.framepointer=NR_STACK_POINTER_REG then
// href.offset:=register_offset[i]+Localsize
//else
href.offset:=register_offset[i];
href.offset:=register_offset[i];
{$ifdef MIPSEL}
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Var '+
register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+' saved to offset '+tostr(href.offset))));
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
end;
{$else not MIPSEL, for big endian, size matters}
case register_size[i] of
OS_8,
OS_S8:
StoreOp := A_SB;
OS_16,
OS_S16:
StoreOp := A_SH;
OS_32,
OS_NO,
OS_F32,
OS_S32:
StoreOp := A_SW;
OS_F64,
OS_64,
OS_S64:
begin
{$ifdef cpu64bitalu}
StoreOp:=A_SD;
{$else not cpu64bitalu}
StoreOp:= A_SW;
{$endif not cpu64bitalu}
end
else
internalerror(2012061801);
end;
if cs_asm_source in current_settings.globalswitches then
list.concat(tai_comment.Create(strpnew('Var '+
register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+' saved to offset '+tostr(href.offset))));
list.concat(taicpu.op_reg_ref(StoreOp, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
{$endif}
end;
end;
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin
@ -1792,8 +1849,15 @@ procedure TCGMIPS.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCG
procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
var
tmpref: treference;
tmpreg: tregister;
begin
{ Override this function to prevent loading the reference twice }
if target_info.endian = endian_big then
begin
tmpreg := reg.reglo;
reg.reglo := reg.reghi;
reg.reghi := tmpreg;
end;
tmpref := ref;
cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
Inc(tmpref.offset, 4);
@ -1804,8 +1868,15 @@ end;
procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
var
tmpref: treference;
tmpreg: tregister;
begin
{ Override this function to prevent loading the reference twice }
if target_info.endian = endian_big then
begin
tmpreg := reg.reglo;
reg.reglo := reg.reghi;
reg.reghi := tmpreg;
end;
tmpref := ref;
cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
Inc(tmpref.offset, 4);

View File

@ -61,6 +61,8 @@ interface
type
tparasupregs = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tsuperregister;
tparasupregsused = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of boolean;
tparasupregsize = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tcgsize;
tparasuprename = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of shortstring;
tparasupregsoffset = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of longint;
const
@ -68,10 +70,6 @@ interface
type
TMIPSParaManager=class(TParaManager)
var
param_offset:array[0..MIPS_MAX_OFFSET] of ^Aint;
intparareg,
parasize : longint;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
@ -83,6 +81,8 @@ interface
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
private
intparareg,
intparasize : longint;
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
end;
@ -130,11 +130,6 @@ implementation
begin
loc:=LOC_REGISTER;
register:=newreg(R_INTREGISTER,parasupregs[nr],R_SUBWHOLE);
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[nr]:=true;
TMIPSProcInfo(current_procinfo).register_offset[nr]:=nr*mips_sizeof_register_param;
end;
end
else
begin
@ -144,6 +139,10 @@ implementation
reference.offset:=nr*mips_sizeof_register_param;
end;
size:=OS_INT;
{ Be sure to reserve enough stack space tp cope with
that parameter }
if assigned(current_procinfo) then
TMIPSProcinfo(current_procinfo).allocate_push_parasize((nr+1)*mips_sizeof_register_param);
end;
end;
@ -221,7 +220,6 @@ implementation
in this case we use the first register R4 for it }
if ret_in_param(def,p.proccalloption) then
begin
{ Reserve first register for ret_in_param }
if intparareg=0 then
inc(intparareg);
if side=calleeside then
@ -232,6 +230,14 @@ implementation
{ return is at offset zero }
paraloc^.reference.offset:=0;
paraloc^.size:=retcgsize;
{ Reserve first register for ret_in_param }
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
TMIPSProcInfo(current_procinfo).register_size[0]:=retcgsize;
TMIPSProcInfo(current_procinfo).register_name[0]:='ret_in_param_result';
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
end;
end
else
begin
@ -304,8 +310,6 @@ implementation
can_use_float := true;
for i:=0 to paras.count-1 do
begin
if i<=MIPS_MAX_OFFSET then
param_offset[i] := Nil;
hp:=tparavarsym(paras[i]);
paradef := hp.vardef;
@ -351,11 +355,11 @@ implementation
hp.paraloc[side].intsize:=paralen;
hp.paraloc[side].size:=paracgsize;
{ check the alignment, mips O32ABI require a nature alignment }
tmp := align(parasize, alignment) - parasize;
tmp := align(intparasize, alignment) - intparasize;
while tmp > 0 do
begin
inc(intparareg);
inc(parasize,4);
inc(intparasize,4);
dec(tmp,4);
end;
@ -381,6 +385,8 @@ implementation
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
TMIPSProcInfo(current_procinfo).register_name[0]:='result';
TMIPSProcInfo(current_procinfo).register_size[0]:=paracgsize;
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
end;
//if (intparareg<>1) then
@ -402,10 +408,8 @@ implementation
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
end;
paraloc^.reference.offset:=0;
if i<=MIPS_MAX_OFFSET then
param_offset[i] := @paraloc^.reference.offset;
end;
inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
inc(intparasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
end
{ In case of po_delphi_nested_cc, the parent frame pointer
is always passed on the stack. }
@ -424,16 +428,16 @@ implementation
begin
paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFD);
inc(fpparareg);
inc(intparareg);
inc(intparareg);
inc(parasize,8);
inc(intparareg);
inc(intparareg);
inc(intparasize,8);
end
else
begin
paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFS);
inc(fpparareg);
inc(intparareg);
inc(parasize,sizeof(aint));
inc(intparareg);
inc(intparasize,sizeof(aint));
end;
end
else { not can use float }
@ -441,6 +445,8 @@ implementation
if assigned(current_procinfo) then
begin
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paracgsize;
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
end;
if side=callerside then
@ -462,7 +468,7 @@ implementation
paraloc^.reference.offset:=intparareg*mips_sizeof_register_param;
end;
inc(intparareg);
inc(parasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
end;
end
else
@ -471,7 +477,7 @@ implementation
if side=callerside then
begin
paraloc^.reference.index := NR_STACK_POINTER_REG;
paraloc^.reference.offset:=parasize;
paraloc^.reference.offset:=intparasize;
end
else
begin
@ -483,34 +489,35 @@ implementation
if assigned(current_procinfo) then
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
end;
paraloc^.reference.offset:=parasize;
if i<=MIPS_MAX_OFFSET then
param_offset[i] := @paraloc^.reference.offset;
paraloc^.reference.offset:=intparasize;
end;
inc(parasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
end;
dec(paralen,tcgsize2size[paraloc^.size]);
end;
end;
{ O32 ABI reqires at least 16 bytes }
if (intparasize < 16) then
intparasize := 16;
if assigned(current_procinfo) then
begin
TMIPSProcinfo(current_procinfo).allocate_push_parasize(intparasize);
end;
end;
function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
begin
intparareg:=0;
parasize:=0;
intparasize:=0;
{ Create Function result paraloc }
create_funcretloc_info(p,callerside);
{ calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras);
{ append the varargs }
create_paraloc_info_intern(p,callerside,varargspara);
{ At least 16 bytes must be reserved for parameter
area in O32 ABI, this can be used by called function,
even if it has less parameter }
if (parasize < 16) then
parasize := 16;
result:=parasize;
{ We need to return the size allocated on the stack }
result:=intparasize;
end;
@ -518,17 +525,12 @@ implementation
function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
begin
intparareg:=0;
parasize:=0;
intparasize:=0;
{ Create Function result paraloc }
create_funcretloc_info(p,side);
create_paraloc_info_intern(p,side,p.paras);
{ We need to return the size allocated on the stack }
{ At least 16 bytes must be reserved for parameter
area in O32 ABI, this can be used by called function,
even if it has less parameter }
if (parasize < 16) then
parasize := 16;
result:=parasize;
result:=intparasize;
end;