mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 19:29:09 +02:00
* several arm fixes
git-svn-id: trunk@4742 -
This commit is contained in:
parent
506f44dc7a
commit
67ba76f090
@ -394,7 +394,7 @@ unit cgcpu;
|
|||||||
OP_SHL:
|
OP_SHL:
|
||||||
begin
|
begin
|
||||||
if a>32 then
|
if a>32 then
|
||||||
internalerror(200308291);
|
internalerror(200308294);
|
||||||
if a<>0 then
|
if a<>0 then
|
||||||
begin
|
begin
|
||||||
shifterop_reset(so);
|
shifterop_reset(so);
|
||||||
@ -422,7 +422,7 @@ unit cgcpu;
|
|||||||
OP_SAR:
|
OP_SAR:
|
||||||
begin
|
begin
|
||||||
if a>32 then
|
if a>32 then
|
||||||
internalerror(200308291);
|
internalerror(200308295);
|
||||||
if a<>0 then
|
if a<>0 then
|
||||||
begin
|
begin
|
||||||
shifterop_reset(so);
|
shifterop_reset(so);
|
||||||
@ -465,7 +465,7 @@ unit cgcpu;
|
|||||||
else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a-1,l1) and not(cgsetflags or setflags) then
|
else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a-1,l1) and not(cgsetflags or setflags) then
|
||||||
begin
|
begin
|
||||||
if l1>32 then{roozbeh does this ever happen?}
|
if l1>32 then{roozbeh does this ever happen?}
|
||||||
internalerror(200308291);
|
internalerror(200308296);
|
||||||
shifterop_reset(so);
|
shifterop_reset(so);
|
||||||
so.shiftmode:=SM_LSL;
|
so.shiftmode:=SM_LSL;
|
||||||
so.shiftimm:=l1;
|
so.shiftimm:=l1;
|
||||||
@ -844,7 +844,7 @@ unit cgcpu;
|
|||||||
OS_S32:
|
OS_S32:
|
||||||
oppostfix:=PF_None;
|
oppostfix:=PF_None;
|
||||||
else
|
else
|
||||||
InternalError(200308291);
|
InternalError(200308297);
|
||||||
end;
|
end;
|
||||||
if Ref.alignment<>0 then
|
if Ref.alignment<>0 then
|
||||||
begin
|
begin
|
||||||
@ -1020,7 +1020,15 @@ unit cgcpu;
|
|||||||
LOC_FPUREGISTER,LOC_CFPUREGISTER:
|
LOC_FPUREGISTER,LOC_CFPUREGISTER:
|
||||||
a_loadfpu_ref_reg(list,size,ref,hloc^.register);
|
a_loadfpu_ref_reg(list,size,ref,hloc^.register);
|
||||||
LOC_REGISTER :
|
LOC_REGISTER :
|
||||||
a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
case hloc^.size of
|
||||||
|
OS_F32:
|
||||||
|
a_load_ref_reg(list,OS_32,OS_32,href,hloc^.register);
|
||||||
|
OS_64,
|
||||||
|
OS_F64:
|
||||||
|
cg64.a_param64_ref(list,href,paraloc);
|
||||||
|
else
|
||||||
|
a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
||||||
|
end;
|
||||||
LOC_REFERENCE :
|
LOC_REFERENCE :
|
||||||
begin
|
begin
|
||||||
reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset);
|
reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset);
|
||||||
@ -1046,8 +1054,10 @@ unit cgcpu;
|
|||||||
oppostfix:toppostfix;
|
oppostfix:toppostfix;
|
||||||
begin
|
begin
|
||||||
case size of
|
case size of
|
||||||
|
OS_32,
|
||||||
OS_F32:
|
OS_F32:
|
||||||
oppostfix:=PF_S;
|
oppostfix:=PF_S;
|
||||||
|
OS_64,
|
||||||
OS_F64:
|
OS_F64:
|
||||||
oppostfix:=PF_D;
|
oppostfix:=PF_D;
|
||||||
OS_F80:
|
OS_F80:
|
||||||
|
@ -288,7 +288,7 @@ unit cpupara;
|
|||||||
OS_F32:
|
OS_F32:
|
||||||
paraloc^.size:=OS_32;
|
paraloc^.size:=OS_32;
|
||||||
OS_F64:
|
OS_F64:
|
||||||
paraloc^.size:=OS_64;
|
paraloc^.size:=OS_32;
|
||||||
else
|
else
|
||||||
internalerror(2005082901);
|
internalerror(2005082901);
|
||||||
end
|
end
|
||||||
|
@ -1047,18 +1047,18 @@ implementation
|
|||||||
in memory. They are like a regular reference, but contain an extra bit
|
in memory. They are like a regular reference, but contain an extra bit
|
||||||
offset (either constant -startbit- or variable -bitindexreg, always OS_INT)
|
offset (either constant -startbit- or variable -bitindexreg, always OS_INT)
|
||||||
and a bit length (always constant).
|
and a bit length (always constant).
|
||||||
|
|
||||||
Bit packed values are stored differently in memory depending on whether we
|
Bit packed values are stored differently in memory depending on whether we
|
||||||
are on a big or a little endian system (compatible with at least GPC). The
|
are on a big or a little endian system (compatible with at least GPC). The
|
||||||
size of the basic working unit is always the smallest power-of-2 byte size
|
size of the basic working unit is always the smallest power-of-2 byte size
|
||||||
which can contain the bit value (so 1..8 bits -> 1 byte, 9..16 bits -> 2
|
which can contain the bit value (so 1..8 bits -> 1 byte, 9..16 bits -> 2
|
||||||
bytes, 17..32 bits -> 4 bytes etc).
|
bytes, 17..32 bits -> 4 bytes etc).
|
||||||
|
|
||||||
On a big endian, 5-bit: values are stored like this:
|
On a big endian, 5-bit: values are stored like this:
|
||||||
11111222 22333334 44445555 56666677 77788888
|
11111222 22333334 44445555 56666677 77788888
|
||||||
The leftmost bit of each 5-bit value corresponds to the most significant
|
The leftmost bit of each 5-bit value corresponds to the most significant
|
||||||
bit.
|
bit.
|
||||||
|
|
||||||
On little endian, it goes like this:
|
On little endian, it goes like this:
|
||||||
22211111 43333322 55554444 77666665 88888777
|
22211111 43333322 55554444 77666665 88888777
|
||||||
In this case, per byte the left-most bit is more significant than those on
|
In this case, per byte the left-most bit is more significant than those on
|
||||||
@ -1066,10 +1066,10 @@ implementation
|
|||||||
those in the previous byte (e.g., the 222 in the first byte are the low
|
those in the previous byte (e.g., the 222 in the first byte are the low
|
||||||
three bits of that value, while the 22 in the second byte are the upper
|
three bits of that value, while the 22 in the second byte are the upper
|
||||||
three bits.
|
three bits.
|
||||||
|
|
||||||
Big endian, 9 bit values:
|
Big endian, 9 bit values:
|
||||||
11111111 12222222 22333333 33344444 ...
|
11111111 12222222 22333333 33344444 ...
|
||||||
|
|
||||||
Little endian, 9 bit values:
|
Little endian, 9 bit values:
|
||||||
11111111 22222221 33333322 44444333 ...
|
11111111 22222221 33333322 44444333 ...
|
||||||
This is memory representation and the 16 bit values are byteswapped.
|
This is memory representation and the 16 bit values are byteswapped.
|
||||||
@ -1080,7 +1080,7 @@ implementation
|
|||||||
alignment can be guaranteed), this becomes:
|
alignment can be guaranteed), this becomes:
|
||||||
22222221 11111111 44444333 33333322 ...
|
22222221 11111111 44444333 33333322 ...
|
||||||
(l)ow u l l u l u
|
(l)ow u l l u l u
|
||||||
|
|
||||||
The startbit/bitindex in a subsetreference always refers to
|
The startbit/bitindex in a subsetreference always refers to
|
||||||
a) on big endian: the most significant bit of the value
|
a) on big endian: the most significant bit of the value
|
||||||
(bits counted from left to right, both memory an registers)
|
(bits counted from left to right, both memory an registers)
|
||||||
@ -1101,13 +1101,13 @@ implementation
|
|||||||
intloadsize: aint;
|
intloadsize: aint;
|
||||||
begin
|
begin
|
||||||
intloadsize := packedbitsloadsize(sref.bitlen);
|
intloadsize := packedbitsloadsize(sref.bitlen);
|
||||||
|
|
||||||
{$ifdef cpurequiresproperalignment}
|
{$ifdef cpurequiresproperalignment}
|
||||||
{ may need to be split into several smaller loads/stores }
|
{ may need to be split into several smaller loads/stores }
|
||||||
if intloadsize <> sref.ref.alignment then
|
if intloadsize <> sref.ref.alignment then
|
||||||
internalerror(2006082011);
|
internalerror(2006082011);
|
||||||
{$endif cpurequiresproperalignment}
|
{$endif cpurequiresproperalignment}
|
||||||
|
|
||||||
if (intloadsize = 0) then
|
if (intloadsize = 0) then
|
||||||
internalerror(2006081310);
|
internalerror(2006081310);
|
||||||
|
|
||||||
@ -1205,7 +1205,7 @@ implementation
|
|||||||
a_op_const_reg(list,OP_SUB,OS_INT,1,tmpreg);
|
a_op_const_reg(list,OP_SUB,OS_INT,1,tmpreg);
|
||||||
{ if (tmpreg = cpu_bit_size) then extra_value_reg := 0 }
|
{ if (tmpreg = cpu_bit_size) then extra_value_reg := 0 }
|
||||||
a_op_reg_reg(list,OP_AND,OS_INT,tmpreg,extra_value_reg);
|
a_op_reg_reg(list,OP_AND,OS_INT,tmpreg,extra_value_reg);
|
||||||
end;
|
end;
|
||||||
{$endif x86}
|
{$endif x86}
|
||||||
{ merge }
|
{ merge }
|
||||||
a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
|
a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
|
||||||
@ -1301,7 +1301,7 @@ implementation
|
|||||||
destreg := makeregsize(list,destreg,tosize);
|
destreg := makeregsize(list,destreg,tosize);
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tcg.a_load_reg_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference);
|
procedure tcg.a_load_reg_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference);
|
||||||
var
|
var
|
||||||
@ -1315,7 +1315,7 @@ implementation
|
|||||||
{ the register must be able to contain the requested value }
|
{ the register must be able to contain the requested value }
|
||||||
if (tcgsize2size[fromsize]*8 < sref.bitlen) then
|
if (tcgsize2size[fromsize]*8 < sref.bitlen) then
|
||||||
internalerror(2006081613);
|
internalerror(2006081613);
|
||||||
|
|
||||||
get_subsetref_load_info(sref,loadsize,extra_load);
|
get_subsetref_load_info(sref,loadsize,extra_load);
|
||||||
loadbitsize := tcgsize2size[loadsize]*8;
|
loadbitsize := tcgsize2size[loadsize]*8;
|
||||||
|
|
||||||
@ -1418,7 +1418,7 @@ implementation
|
|||||||
a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
|
a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
|
||||||
valuereg := makeregsize(list,valuereg,loadsize);
|
valuereg := makeregsize(list,valuereg,loadsize);
|
||||||
a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
|
a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
|
||||||
|
|
||||||
{ transfer second part }
|
{ transfer second part }
|
||||||
if (target_info.endian = endian_big) then
|
if (target_info.endian = endian_big) then
|
||||||
begin
|
begin
|
||||||
@ -1470,7 +1470,7 @@ implementation
|
|||||||
|
|
||||||
a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
|
a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
|
||||||
a_op_reg_reg(list,OP_AND,OS_INT,maskreg,valuereg);
|
a_op_reg_reg(list,OP_AND,OS_INT,maskreg,valuereg);
|
||||||
|
|
||||||
{ insert the value }
|
{ insert the value }
|
||||||
tmpreg := getintregister(list,OS_INT);
|
tmpreg := getintregister(list,OS_INT);
|
||||||
a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg);
|
a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg);
|
||||||
@ -1527,13 +1527,13 @@ implementation
|
|||||||
{ if (tmpreg = cpu_bit_size) then tmpreg := maskreg := 0 }
|
{ if (tmpreg = cpu_bit_size) then tmpreg := maskreg := 0 }
|
||||||
a_op_reg_reg(list,OP_AND,OS_INT,valuereg,tmpreg);
|
a_op_reg_reg(list,OP_AND,OS_INT,valuereg,tmpreg);
|
||||||
a_op_reg_reg(list,OP_AND,OS_INT,valuereg,maskreg);
|
a_op_reg_reg(list,OP_AND,OS_INT,valuereg,maskreg);
|
||||||
end;
|
end;
|
||||||
{$endif x86}
|
{$endif x86}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
|
a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
|
||||||
a_op_reg_reg(list,OP_AND,OS_INT,maskreg,extra_value_reg);
|
a_op_reg_reg(list,OP_AND,OS_INT,maskreg,extra_value_reg);
|
||||||
|
|
||||||
if (target_info.endian = endian_big) then
|
if (target_info.endian = endian_big) then
|
||||||
a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,tmpreg)
|
a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,tmpreg)
|
||||||
else
|
else
|
||||||
@ -1614,7 +1614,7 @@ implementation
|
|||||||
a_load_subsetref_reg(list,fromsubsetsize,tosubsetsize,fromsref,tmpreg);
|
a_load_subsetref_reg(list,fromsubsetsize,tosubsetsize,fromsref,tmpreg);
|
||||||
a_load_reg_subsetreg(list,tosubsetsize,tosubsetsize,tmpreg,tosreg);
|
a_load_reg_subsetreg(list,tosubsetsize,tosubsetsize,tmpreg,tosreg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tcg.a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference);
|
procedure tcg.a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference);
|
||||||
var
|
var
|
||||||
|
@ -76,6 +76,7 @@ implementation
|
|||||||
uses
|
uses
|
||||||
systems,
|
systems,
|
||||||
cutils,verbose,globals,
|
cutils,verbose,globals,
|
||||||
|
cpuinfo,
|
||||||
symconst,symtable,defutil,paramgr,
|
symconst,symtable,defutil,paramgr,
|
||||||
cgbase,pass_2,
|
cgbase,pass_2,
|
||||||
aasmbase,aasmtai,aasmdata,
|
aasmbase,aasmtai,aasmdata,
|
||||||
@ -575,32 +576,38 @@ implementation
|
|||||||
location_reset(location,LOC_REGISTER,cgsize);
|
location_reset(location,LOC_REGISTER,cgsize);
|
||||||
{$ifndef cpu64bit}
|
{$ifndef cpu64bit}
|
||||||
if cgsize in [OS_64,OS_S64] then
|
if cgsize in [OS_64,OS_S64] then
|
||||||
begin
|
begin
|
||||||
retloc:=procdefinition.funcretloc[callerside];
|
retloc:=procdefinition.funcretloc[callerside];
|
||||||
if retloc.loc<>LOC_REGISTER then
|
if retloc.loc<>LOC_REGISTER then
|
||||||
internalerror(200409141);
|
internalerror(200409141);
|
||||||
{ the function result registers are already allocated }
|
{ the function result registers are already allocated }
|
||||||
if getsupreg(retloc.register64.reglo)<first_int_imreg then
|
if getsupreg(retloc.register64.reglo)<first_int_imreg then
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
|
||||||
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
|
||||||
if getsupreg(retloc.register64.reghi)<first_int_imreg then
|
if getsupreg(retloc.register64.reghi)<first_int_imreg then
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
|
||||||
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{$endif cpu64bit}
|
{$endif cpu64bit}
|
||||||
begin
|
begin
|
||||||
{ change register size after the unget because the
|
{ change register size after the unget because the
|
||||||
getregister was done for the full register
|
getregister was done for the full register
|
||||||
def_cgsize(resulttype.def) is used here because
|
def_cgsize(resulttype.def) is used here because
|
||||||
it could be a constructor call }
|
it could be a constructor call }
|
||||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
|
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||||
location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resulttype.def));
|
location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resulttype.def));
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resulttype.def),procdefinition.funcretloc[callerside].register,location.register);
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resulttype.def),procdefinition.funcretloc[callerside].register,location.register);
|
||||||
end;
|
end;
|
||||||
|
{$ifdef arm}
|
||||||
|
if (resulttype.def.deftype=floatdef) and (aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
|
||||||
|
begin
|
||||||
|
location_force_mem(current_asmdata.CurrAsmList,location);
|
||||||
|
end;
|
||||||
|
{$endif arm}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -1578,7 +1578,7 @@ implementation
|
|||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
href : treference;
|
href : treference;
|
||||||
sizeleft : aint;
|
sizeleft : aint;
|
||||||
{$ifdef sparc}
|
{$if defined(sparc) or defined(arm)}
|
||||||
tempref : treference;
|
tempref : treference;
|
||||||
{$endif sparc}
|
{$endif sparc}
|
||||||
begin
|
begin
|
||||||
@ -1696,8 +1696,8 @@ implementation
|
|||||||
end;
|
end;
|
||||||
LOC_CFPUREGISTER :
|
LOC_CFPUREGISTER :
|
||||||
begin
|
begin
|
||||||
{$ifdef sparc}
|
{$if defined(sparc) or defined(arm)}
|
||||||
{ Sparc passes floats in int registers, when loading to fpu register
|
{ Arm and Sparc passes floats in int registers, when loading to fpu register
|
||||||
we need a temp }
|
we need a temp }
|
||||||
sizeleft := TCGSize2Size[currpara.initialloc.size];
|
sizeleft := TCGSize2Size[currpara.initialloc.size];
|
||||||
tg.GetTemp(list,sizeleft,tt_normal,tempref);
|
tg.GetTemp(list,sizeleft,tt_normal,tempref);
|
||||||
|
Loading…
Reference in New Issue
Block a user