mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 07:28:26 +02:00
Fix big endian issues
git-svn-id: trunk@21672 -
This commit is contained in:
parent
aa8747f5c9
commit
74eb121d1c
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user