* more sparc cleanup

* accumulator removed, splitted in function_return_reg (called) and
    function_result_reg (caller)
This commit is contained in:
peter 2003-05-30 23:57:08 +00:00
parent d992e13e08
commit 414bd5fa22
32 changed files with 2534 additions and 2768 deletions

View File

@ -277,7 +277,7 @@ unit cgobj;
{#
This routine is used in exception management nodes. It should
save the exception reason currently in the accumulator. The
save the exception reason currently in the FUNCTION_RETURN_REG. The
save should be done either to a temp (pointed to by href).
or on the stack (pushing the value on the stack).
@ -297,7 +297,7 @@ unit cgobj;
procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aword);virtual;
{#
This routine is used in exception management nodes. It should
load the exception reason to the accumulator. The saved value
load the exception reason to the FUNCTION_RETURN_REG. The saved value
should either be in the temp. area (pointed to by href , href should
*NOT* be freed) or on the stack (the value should be popped).
@ -1645,7 +1645,7 @@ unit cgobj;
begin
r.enum:=R_INTREGISTER;;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RETURN_REG;
a_load_reg_ref(list, OS_S32, r, href);
end;
@ -1662,7 +1662,7 @@ unit cgobj;
begin
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RETURN_REG;
a_load_ref_reg(list, OS_S32, href, r);
end;
@ -1691,7 +1691,12 @@ finalization
end.
{
$Log$
Revision 1.102 2003-05-30 23:49:18 jonas
Revision 1.103 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.102 2003/05/30 23:49:18 jonas
* a_load_loc_reg now has an extra size parameter for the destination
register (properly fixes what I worked around in revision 1.106 of
ncgutil.pas)

View File

@ -102,6 +102,7 @@
max_scratch_regs = 1;
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
{$endif}
{*****************************************************************************
GDB Information
*****************************************************************************}
@ -145,34 +146,27 @@
*****************************************************************************}
{# Stack pointer register }
stack_pointer_reg = R_ESP;
NR_STACK_POINTER_REG = NR_ESP;
{# Frame pointer register }
frame_pointer_reg = R_EBP;
NR_FRAME_POINTER_REG = NR_EBP;
{# Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific. For
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
}
pic_offset_reg = R_EBX;
{# Results are returned in this register (32-bit values) }
accumulator = R_EAX;
RS_ACCUMULATOR = RS_EAX;
NR_ACCUMULATOR = NR_EAX;
{ The return_result_reg is used inside the called function to store its return
value when that is a scalar value otherwise a pointer to the address of the
result is placed inside it}
return_result_reg = accumulator;
RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
NR_PIC_OFFSET_REG = NR_EBX;
{ Results are returned in this register (32-bit values) }
NR_FUNCTION_RETURN_REG = NR_EAX;
RS_FUNCTION_RETURN_REG = RS_EAX;
{ High part of 64bit return value }
NR_FUNCTION_RETURNHIGH_REG = NR_EDX;
RS_FUNCTION_RETURNHIGH_REG = RS_EDX;
{ The value returned from a function is available in this register }
NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
{ The high part of 64bit value returned from a function is available in this register }
NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG;
RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG;
{the function_result_reg contains the function result after a call to a scalar
function othewise it contains a pointer to the returned result}
function_result_reg = accumulator;
{# Hi-Results are returned in this register (64-bit value high register) }
accumulatorhigh = R_EDX;
RS_ACCUMULATORHIGH = RS_EDX;
NR_ACCUMULATORHIGH = NR_EDX;
{ WARNING: don't change to R_ST0!! See comments above implementation of }
{ a_loadfpu* methods in rgcpu (JM) }
fpu_result_reg = R_ST;
@ -202,7 +196,12 @@
{
$Log$
Revision 1.3 2003-05-16 14:33:31 peter
Revision 1.4 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.3 2003/05/16 14:33:31 peter
* regvar fixes
Revision 1.2 2002/04/25 16:12:09 florian

View File

@ -60,7 +60,7 @@ unit cpupara;
case target_info.system of
system_i386_win32 :
begin
{ Win32 returns small records in the accumulator }
{ Win32 returns small records in the FUNCTION_RETURN_REG }
case def.deftype of
recorddef :
begin
@ -133,7 +133,12 @@ begin
end.
{
$Log$
Revision 1.11 2003-05-13 15:16:13 peter
Revision 1.12 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.11 2003/05/13 15:16:13 peter
* removed ret_in_acc, it's the reverse of ret_in_param
* fixed ret_in_param for win32 cdecl array

View File

@ -363,9 +363,9 @@ Begin {CheckSequence}
OrgRegResult := False;
with startRegInfo do
begin
newRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
new2OldReg[FRAME_POINTER_REG].enum := FRAME_POINTER_REG;
new2OldReg[STACK_POINTER_REG].enum := STACK_POINTER_REG;
newRegsEncountered := [R_EBP, R_ESP];
new2OldReg[R_EBP].enum := R_EBP;
new2OldReg[R_ESP].enum := R_ESP;
oldRegsEncountered := newRegsEncountered;
end;
@ -1334,7 +1334,7 @@ begin
(Taicpu(startmod).opcode = A_MOVSX) or
(Taicpu(startmod).opcode = A_LEA)) and
(Taicpu(startmod).oper[0].typ = top_ref) and
(Taicpu(startmod).oper[0].ref^.base.enum = STACK_POINTER_REG)) or
(Taicpu(startmod).oper[0].ref^.base.enum = R_ESP)) or
not(reg.enum in pTaiprop(hp1.optInfo)^.usedRegs) or
findRegDealloc(reg,p))) then
pTaiprop(startMod.optInfo)^.canBeRemoved := true;
@ -1997,7 +1997,12 @@ End.
{
$Log$
Revision 1.45 2003-05-16 14:33:31 peter
Revision 1.46 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.45 2003/05/16 14:33:31 peter
* regvar fixes
Revision 1.44 2003/04/27 11:21:35 peter

View File

@ -197,7 +197,12 @@ begin
end.
{
$Log$
Revision 1.92 2003-05-26 21:17:18 peter
Revision 1.93 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.92 2003/05/26 21:17:18 peter
* procinlinenode removed
* aktexit2label removed, fast exit removed
+ tcallnode.inlined_pass_2 added
@ -294,7 +299,7 @@ end.
* old logs removed and tabs fixed
Revision 1.69 2002/09/01 18:43:27 peter
* include accumulator in regs_to_push list
* include FUNCTION_RETURN_REG in regs_to_push list
Revision 1.68 2002/09/01 12:13:00 peter
* use a_call_reg

View File

@ -1376,7 +1376,9 @@ Begin
Taicpu(hp2).opcode := A_MOV;
Taicpu(hp2).Loadoper(1,Taicpu(hp1).oper[0]);
reference_reset_old(tmpref);
tmpRef.base .enum:= STACK_POINTER_REG;
tmpRef.base.enum:=R_INTREGISTER;
tmpRef.base.number:=NR_STACK_POINTER_REG;
convert_register_to_enum(tmpref.base);
tmpRef.offset := l;
Taicpu(hp2).loadRef(0,tmpRef);
hp4 := hp1;
@ -2058,7 +2060,12 @@ End.
{
$Log$
Revision 1.43 2003-04-27 11:21:35 peter
Revision 1.44 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.43 2003/04/27 11:21:35 peter
* aktprocdef renamed to current_procdef
* procinfo renamed to current_procinfo
* procinfo will now be stored in current_module so it can be

View File

@ -49,7 +49,8 @@ Implementation
{ parser }
scanner,
itx86att,
rax86,rautils
rax86,rautils,
cginfo,cgobj
;
type
@ -1402,6 +1403,8 @@ var
end; { end case }
end;
const
regsize_2_size: array[S_B..S_L] of longint = (1,2,4);
var
tempreg : tregister;
hl : tasmlabel;
@ -1441,7 +1444,7 @@ Begin
begin
opr.typ:=OPR_REGISTER;
opr.reg:=actasmregister;
size:=reg2opsize(actasmregister);
SetSize(regsize_2_size[reg2opsize(actasmregister)],true);
Consume(AS_REGISTER);
end
else
@ -1594,7 +1597,7 @@ Begin
Message(asmr_e_invalid_operand_type);
opr.typ:=OPR_REGISTER;
opr.reg:=tempreg;
size:=reg2opsize(opr.reg);
SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true);
end
else
Message(asmr_e_syn_operand);
@ -2134,7 +2137,12 @@ finalization
end.
{
$Log$
Revision 1.44 2003-05-22 21:32:29 peter
Revision 1.45 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.44 2003/05/22 21:32:29 peter
* removed some unit dependencies
Revision 1.43 2003/04/30 15:45:35 florian

View File

@ -52,7 +52,7 @@ Implementation
scanner,
rautils,rax86,ag386int,
{ codegen }
cgbase
cginfo,cgbase,cgobj
;
type
@ -1565,7 +1565,7 @@ Begin
Message(asmr_e_invalid_operand_type);
opr.typ:=OPR_REGISTER;
opr.reg:=tempreg;
size:=reg2opsize(opr.reg)
SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true);
end;
end;
@ -1620,7 +1620,7 @@ end;
Procedure T386IntelInstruction.BuildOpCode;
var
PrefixOp,OverrideOp: tasmop;
size : topsize;
size : tcgsize;
operandnum : longint;
Begin
PrefixOp:=A_None;
@ -1706,9 +1706,9 @@ Begin
{ load the size in a temp variable, so it can be set when the
operand is read }
Case actasmtoken of
AS_DWORD : size:=S_L;
AS_WORD : size:=S_W;
AS_BYTE : size:=S_B;
AS_DWORD : size:=OS_32;
AS_WORD : size:=OS_16;
AS_BYTE : size:=OS_8;
AS_QWORD : begin
if (opcode=A_FCOM) or
(opcode=A_FCOMP) or
@ -1721,11 +1721,11 @@ Begin
(opcode=A_FST) or
(opcode=A_FSTP) or
(opcode=A_FADD) then
size:=S_FL
size:=OS_F64
else
size:=S_IQ;
size:=OS_64;
end;
AS_TBYTE : size:=S_FX;
AS_TBYTE : size:=OS_F80;
end;
Consume(actasmtoken);
if actasmtoken=AS_PTR then
@ -1961,7 +1961,12 @@ finalization
end.
{
$Log$
Revision 1.47 2003-04-30 15:45:35 florian
Revision 1.48 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.47 2003/04/30 15:45:35 florian
* merged more x86-64/i386 code
Revision 1.46 2003/04/27 11:21:35 peter

View File

@ -426,7 +426,8 @@ implementation
begin
location_reset(location,LOC_CREFERENCE,OS_ADDR);
location.reference:=refcountedtemp;
r.enum:=accumulator;
r.enum:=R_INTREGISTER;
r.number:=NR_FUNCTION_RETURN_REG;
cg.a_reg_alloc(exprasmlist,r);
cg.a_load_reg_ref(exprasmlist,OS_ADDR,r,location.reference);
cg.a_reg_dealloc(exprasmlist,r);
@ -440,10 +441,10 @@ implementation
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
{$ifdef cpufpemu}
if cs_fp_emulation in aktmoduleswitches then
location.register.enum := accumulator
else
location.register.enum := FUNCTION_RESULT_REG
else
{$endif cpufpemu}
location.register.enum:=FPU_RESULT_REG;
location.register.enum:=FPU_RESULT_REG;
{$ifdef x86}
inc(trgcpu(rg).fpuvaroffset);
{$else x86}
@ -466,26 +467,26 @@ implementation
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
begin
{Move the function result to free registers, preferably the
accumulator/accumulatorhigh, so no move is necessary.}
{ Move the function result to free registers, preferably the
FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
hregister.enum:=R_INTREGISTER;
hregister.number:=NR_ACCUMULATORHIGH;
hregister.number:=NR_FUNCTION_RESULTHIGH_REG;
{$ifdef newra}
rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH);
rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT_REG);
rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULTHIGH_REG);
rg.ungetregisterint(exprasmlist,r);
rg.ungetregisterint(exprasmlist,hregister);
location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
{$else newra}
if RS_ACCUMULATOR in rg.unusedregsint then
location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
if RS_FUNCTION_RESULT_REG in rg.unusedregsint then
location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT_REG)
else
cg.a_reg_alloc(exprasmlist,r);
if RS_ACCUMULATORHIGH in rg.unusedregsint then
location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
if RS_FUNCTION_RESULTHIGH_REG in rg.unusedregsint then
location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RETURNHIGH_REG)
else
cg.a_reg_alloc(exprasmlist,hregister);
{ do this after both low,high are allocated, else it is possible that
@ -502,8 +503,8 @@ implementation
{$endif cpu64bit}
begin
{Move the function result to a free register, preferably the
accumulator, so no move is necessary.}
nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
FUNCTION_RESULT_REG, so no move is necessary.}
nr:=(RS_FUNCTION_RESULT_REG shl 8) or cgsize2subreg(cgsize);
r.enum:=R_INTREGISTER;
r.number:=nr;
{$ifdef newra}
@ -512,7 +513,7 @@ implementation
location.register:=rg.getregisterint(exprasmlist,cgsize);
{$else newra}
cg.a_reg_alloc(exprasmlist,r);
if RS_ACCUMULATOR in rg.unusedregsint then
if RS_FUNCTION_RESULT_REG in rg.unusedregsint then
location.register:=rg.getexplicitregisterint(exprasmlist,nr)
else
location.register:=rg.getregisterint(exprasmlist,cgsize);
@ -640,10 +641,10 @@ implementation
if (not is_void(resulttype.def)) and
(not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
begin
include(regs_to_push_int,RS_ACCUMULATOR);
include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
{$ifndef cpu64bit}
if resulttype.def.size>sizeof(aword) then
include(regs_to_push_int,RS_ACCUMULATORHIGH);
include(regs_to_push_int,RS_FUNCTION_RESULTHIGH_REG);
{$endif cpu64bit}
end;
rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
@ -1029,10 +1030,10 @@ implementation
if (not is_void(resulttype.def)) and
(not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
begin
include(regs_to_push_int,RS_ACCUMULATOR);
include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
{$ifndef cpu64bit}
if resulttype.def.size>sizeof(aword) then
include(regs_to_push_int,RS_ACCUMULATORHIGH);
include(regs_to_push_int,RS_FUNCTION_RESULTHIGH_REG);
{$endif cpu64bit}
end;
rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
@ -1232,11 +1233,16 @@ begin
end.
{
$Log$
Revision 1.77 2003-05-29 10:05:40 jonas
Revision 1.78 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.77 2003/05/29 10:05:40 jonas
* free callparatemps created for call-by-reference parameters
Revision 1.76 2003/05/28 23:58:18 jonas
* added missing initialization of rg.usedint{in,by}proc
* added missing initialization of rg.usedintin,byproc
* ppc now also saves/restores used fpu registers
* ncgcal doesn't add used registers to usedby/inproc anymore, except for
i386
@ -1478,7 +1484,7 @@ end.
* several powerpc related stuff fixed
Revision 1.18 2002/09/01 18:43:27 peter
* include accumulator in regs_to_push list
* include FUNCTION_RETURN_REG in regs_to_push list
Revision 1.17 2002/09/01 12:13:00 peter
* use a_call_reg

View File

@ -893,7 +893,7 @@ implementation
begin
cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
end;
@ -1021,7 +1021,7 @@ implementation
cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_param_reg(exprasmlist, OS_ADDR, r, paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
{ we don't need to restore esi here because reraise never }
@ -1137,8 +1137,6 @@ implementation
begin
location_reset(location,LOC_VOID,OS_NO);
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
oldflowcontrol:=flowcontrol;
flowcontrol:=[];
objectlibrary.getlabel(nextonlabel);
@ -1149,6 +1147,8 @@ implementation
cg.a_call_name(exprasmlist,'FPC_CATCHES');
{ is it this catch? No. go to next onlabel }
r.enum:=R_INTREGISTER;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,nextonlabel);
ref.symbol:=nil;
tg.GetTemp(exprasmlist,pointer_size,tt_normal,ref);
@ -1329,7 +1329,7 @@ implementation
{ the value should now be in the exception handler }
cg.g_exception_reason_load(exprasmlist,href);
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
if implicitframe then
begin
cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,endfinallylabel);
@ -1421,7 +1421,12 @@ begin
end.
{
$Log$
Revision 1.65 2003-05-30 18:55:21 jonas
Revision 1.66 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.65 2003/05/30 18:55:21 jonas
* fixed several regvar related bugs for non-i386. make cycle with -Or now
works for ppc

View File

@ -146,14 +146,14 @@ implementation
if hregister.enum<>R_INTREGISTER then
internalerror(200301171);
{ don't save the allocated register else the result will be destroyed later }
rg.saveusedintregisters(exprasmlist,pushed,[RS_ACCUMULATOR]-[hregister.number shr 8]);
rg.saveusedintregisters(exprasmlist,pushed,[RS_FUNCTION_RESULT_REG]-[hregister.number shr 8]);
reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
{ the called procedure isn't allowed to change }
{ any register except EAX }
cg.a_call_reg(exprasmlist,hregister);
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
rg.restoreusedintregisters(exprasmlist,pushed);
cg.a_label(exprasmlist,norelocatelab);
@ -922,7 +922,12 @@ begin
end.
{
$Log$
Revision 1.63 2003-05-30 23:54:08 jonas
Revision 1.64 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.63 2003/05/30 23:54:08 jonas
* forgot to commit, a_load_loc_reg change
Revision 1.62 2003/05/26 19:38:28 peter

View File

@ -618,7 +618,7 @@ implementation
cg.a_call_name(exprasmlist,'FPC_SET_IN_BYTE');
{ result of value is always one full register }
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
{ release the allocated register }
if not (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
@ -1121,7 +1121,12 @@ begin
end.
{
$Log$
Revision 1.37 2003-05-30 23:49:18 jonas
Revision 1.38 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.37 2003/05/30 23:49:18 jonas
* a_load_loc_reg now has an extra size parameter for the destination
register (properly fixes what I worked around in revision 1.106 of
ncgutil.pas)

View File

@ -269,7 +269,7 @@ implementation
cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
cg.a_call_name(list,'FPC_SETJMP');
@ -290,7 +290,7 @@ implementation
begin
cg.g_exception_reason_load(list, href);
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RESULT_REG;
cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,a,r,endexceptlabel);
end;
end;
@ -796,7 +796,8 @@ implementation
{$endif GDB}
{ this is the easiest case for inlined !! }
r.enum:=stack_pointer_reg;
r.enum:=R_INTREGISTER;
r.number:=NR_STACK_POINTER_REG;
if calloption=pocall_inline then
reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize)
else
@ -1229,7 +1230,7 @@ implementation
end;
procedure handle_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
procedure load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
var
href : treference;
hreg,r,r2 : tregister;
@ -1240,7 +1241,7 @@ implementation
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
cgsize:=def_cgsize(current_procdef.rettype.def);
{ Here, we return the function result. In most architectures, the value is
passed into the accumulator, but in a windowed architecure like sparc a
passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
function returns in a register and the caller receives it in an other one }
case current_procdef.rettype.def.deftype of
orddef,
@ -1248,14 +1249,14 @@ implementation
begin
uses_acc:=true;
r.enum:=R_INTREGISTER;
r.number:=NR_RETURN_RESULT_REG;
r.number:=NR_FUNCTION_RETURN_REG;
cg.a_reg_alloc(list,r);
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
begin
uses_acchi:=true;
r2.enum:=R_INTREGISTER;
r2.number:=NR_ACCUMULATORHIGH;
r2.number:=NR_FUNCTION_RETURNHIGH_REG;
cg.a_reg_alloc(list,r2);
cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
end
@ -1263,7 +1264,7 @@ implementation
{$endif cpu64bit}
begin
hreg.enum:=R_INTREGISTER;
hreg.number:=RS_RETURN_RESULT_REG shl 8 or cgsize2subreg(cgsize);
hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(cgsize);
cg.a_load_ref_reg(list,cgsize,href,hreg);
end;
end;
@ -1272,10 +1273,10 @@ implementation
uses_fpu := true;
{$ifdef cpufpemu}
if cs_fp_emulation in aktmoduleswitches then
r.enum := accumulator
r.enum := FUNCTION_RETURN_REG
else
{$endif cpufpemu}
r.enum:=fpu_result_reg;
r.enum:=FPU_RESULT_REG;
cg.a_loadfpu_ref_reg(list,cgsize,href,r);
end;
else
@ -1284,7 +1285,7 @@ implementation
begin
uses_acc:=true;
r.enum:=R_INTREGISTER;
r.number:=NR_RETURN_RESULT_REG;
r.number:=NR_FUNCTION_RETURN_REG;
cg.a_reg_alloc(list,r);
{$ifndef cpu64bit}
{ Win32 can return records in EAX:EDX }
@ -1292,7 +1293,7 @@ implementation
begin
uses_acchi:=true;
r2.enum:=R_INTREGISTER;
r2.number:=NR_ACCUMULATORHIGH;
r2.number:=NR_FUNCTION_RETURNHIGH_REG;
cg.a_reg_alloc(list,r2);
cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
end
@ -1300,7 +1301,7 @@ implementation
{$endif cpu64bit}
begin
hreg.enum:=R_INTREGISTER;
hreg.number:=RS_RETURN_RESULT_REG shl 8 or cgsize2subreg(cgsize);
hreg.number:=RS_FUNCTION_RETURN_REG shl 8 or cgsize2subreg(cgsize);
cg.a_load_ref_reg(list,cgsize,href,hreg);
end;
end
@ -1629,7 +1630,7 @@ implementation
{ Success exit }
cg.a_label(list,okexitlabel);
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
r.number:=NR_FUNCTION_RETURN_REG;
cg.a_reg_alloc(list,r);
{ return the self pointer }
srsym:=tvarsym(current_procdef.parast.search('self'));
@ -1641,7 +1642,7 @@ implementation
usesacc:=true;
end
else
handle_return_value(list,usesacc,usesacchi,usesfpu)
load_return_value(list,usesacc,usesacchi,usesfpu)
end;
{$ifdef GDB}
@ -1782,7 +1783,7 @@ implementation
Inlining
****************************************************************************}
procedure handle_inlined_return_value(list:TAAsmoutput);
procedure load_inlined_return_value(list:TAAsmoutput);
var
href : treference;
r,r2 : tregister;
@ -1793,7 +1794,7 @@ implementation
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
cgsize:=def_cgsize(current_procdef.rettype.def);
{ Here, we return the function result. In most architectures, the value is
passed into the accumulator, but in a windowed architecure like sparc a
passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
function returns in a register and the caller receives it in an other one }
case current_procdef.rettype.def.deftype of
orddef,
@ -1817,10 +1818,10 @@ implementation
begin
{$ifdef cpufpemu}
if cs_fp_emulation in aktmoduleswitches then
r.enum := accumulator
r.enum := FUNCTION_RETURN_REG
else
{$endif cpufpemu}
r.enum:=fpu_result_reg;
r.enum:=FPU_RESULT_REG;
cg.a_loadfpu_ref_reg(list,cgsize,href,r);
end;
else
@ -1898,8 +1899,8 @@ implementation
begin
if (current_procdef.proctypeoption=potype_constructor) then
internalerror(200305263);
// handle_inlined_return_value(list);
handle_return_value(list,usesacc,usesacchi,usesfpu)
// load_inlined_return_value(list);
load_return_value(list,usesacc,usesacchi,usesfpu)
end;
cleanup_regvars(list);
@ -1908,7 +1909,12 @@ implementation
end.
{
$Log$
Revision 1.111 2003-05-30 23:49:18 jonas
Revision 1.112 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.111 2003/05/30 23:49:18 jonas
* a_load_loc_reg now has an extra size parameter for the destination
register (properly fixes what I worked around in revision 1.106 of
ncgutil.pas)
@ -2116,7 +2122,7 @@ end.
* pass proccalloption to ret_in_xxx and push_xxx functions
Revision 1.61 2002/11/17 17:49:08 mazen
+ return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
+ return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
Revision 1.60 2002/11/17 16:31:56 carl
* memory optimization (3-4%) : cleanup of tai fields,

View File

@ -236,7 +236,8 @@ unit paramgr;
result.loc:=LOC_REFERENCE;
result.size:=OS_ADDR;
result.sp_fixup:=pointer_size;
result.reference.index.enum:=stack_pointer_reg;
result.reference.index.enum:=R_INTREGISTER;
result.reference.index.number:=NR_STACK_POINTER_REG;
result.reference.offset:=0;
end;
@ -246,7 +247,8 @@ unit paramgr;
result.loc:=LOC_REFERENCE;
result.size:=OS_ADDR;
result.sp_fixup:=pointer_size;
result.reference.index.enum:=stack_pointer_reg;
result.reference.index.enum:=R_INTREGISTER;
result.reference.index.number:=NR_STACK_POINTER_REG;
result.reference.offset:=0;
end;
@ -265,29 +267,38 @@ unit paramgr;
{$ifndef cpu64bit}
if result.size in [OS_64,OS_S64] then
begin
result.register64.reghi.enum:=accumulatorhigh;
result.register64.reglo.enum:=accumulator;
result.register64.reghi.enum:=R_INTREGISTER;
result.register64.reghi.number:=NR_FUNCTION_RETURNHIGH_REG;
result.register64.reglo.enum:=R_INTREGISTER;
result.register64.reglo.number:=NR_FUNCTION_RETURN_REG;
end
else
{$endif cpu64bit}
result.register.enum:=accumulator;
begin
result.register.enum:=R_INTREGISTER;
result.register.number:=NR_FUNCTION_RETURN_REG;
end;
end;
floatdef :
begin
result.loc := LOC_FPUREGISTER;
{$ifdef cpufpemu}
if cs_fp_emulation in aktmoduleswitches then
result.register.enum := accumulator
begin
result.register.enum:=R_INTREGISTER;
result.register.number:=FUNCTION_RETURN_REG;
end
else
{$endif cpufpemu}
result.register.enum := FPU_RESULT_REG;
result.register.enum := FPU_RESULT_REG;
end;
else
begin
if not ret_in_param(def,calloption) then
begin
result.loc := LOC_REGISTER;
result.register.enum := accumulator;
result.register.enum:=R_INTREGISTER;
result.register.number:=NR_FUNCTION_RETURN_REG;
end
else
begin
@ -388,7 +399,12 @@ end.
{
$Log$
Revision 1.38 2003-05-13 15:16:13 peter
Revision 1.39 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.38 2003/05/13 15:16:13 peter
* removed ret_in_acc, it's the reverse of ret_in_param
* fixed ret_in_param for win32 cdecl array

View File

@ -221,6 +221,7 @@ uses
NR_RTOC = NR_R2;
{Super registers:}
RS_NONE=$00;
RS_R0 = $01; RS_R1 = $02; RS_R2 = $03;
RS_R3 = $04; RS_R4 = $05; RS_R5 = $06;
RS_R6 = $07; RS_R7 = $08; RS_R8 = $09;
@ -380,7 +381,7 @@ uses
case typ : toptype of
top_none : ();
top_reg : (reg:tregister);
top_ref : (ref:^treference);
top_ref : (ref:preference);
top_const : (val:aword);
top_symbol : (sym:tasmsymbol;symofs:longint);
top_bool : (b: boolean);
@ -474,9 +475,6 @@ uses
const
max_operands = 5;
lvaluelocations = [LOC_REFERENCE, LOC_CREGISTER, LOC_CFPUREGISTER,
LOC_CMMREGISTER];
{# Constant defining possibly all registers which might require saving }
{$warning FIX ME !!!!!!!!! }
ALL_REGISTERS = [R_0..R_FPSCR];
@ -591,47 +589,47 @@ uses
}
stab_regindex : array[firstreg..lastreg] of shortint =
(
{ R_NO }
-1,
{ R0..R7 }
0,1,2,3,4,5,6,7,
{ R8..R15 }
8,9,10,11,12,13,14,15,
{ R16..R23 }
16,17,18,19,20,21,22,23,
{ R24..R32 }
24,25,26,27,28,29,30,31,
{ F0..F7 }
32,33,34,35,36,37,38,39,
{ F8..F15 }
40,41,42,43,44,45,46,47,
{ F16..F23 }
48,49,50,51,52,53,54,55,
{ F24..F31 }
56,57,58,59,60,61,62,63,
{ M0..M7 Multimedia registers are not supported by GCC }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M8..M15 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M16..M23 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M24..M31 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ CR }
-1,
{ CR0..CR7 }
68,69,70,71,72,73,74,75,
{ XER }
76,
{ LR }
65,
{ CTR }
66,
{ FPSCR }
-1
);
stab_regindex : array[firstreg..lastreg] of shortint =
(
{ R_NO }
-1,
{ R0..R7 }
0,1,2,3,4,5,6,7,
{ R8..R15 }
8,9,10,11,12,13,14,15,
{ R16..R23 }
16,17,18,19,20,21,22,23,
{ R24..R32 }
24,25,26,27,28,29,30,31,
{ F0..F7 }
32,33,34,35,36,37,38,39,
{ F8..F15 }
40,41,42,43,44,45,46,47,
{ F16..F23 }
48,49,50,51,52,53,54,55,
{ F24..F31 }
56,57,58,59,60,61,62,63,
{ M0..M7 Multimedia registers are not supported by GCC }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M8..M15 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M16..M23 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ M24..M31 }
-1,-1,-1,-1,-1,-1,-1,-1,
{ CR }
-1,
{ CR0..CR7 }
68,69,70,71,72,73,74,75,
{ XER }
76,
{ LR }
65,
{ CTR }
66,
{ FPSCR }
-1
);
{*****************************************************************************
@ -639,18 +637,11 @@ uses
*****************************************************************************}
{# Stack pointer register }
stack_pointer_reg = R_1;
NR_STACK_POINTER_REG = NR_R1;
RS_STACK_POINTER_REG = RS_R1;
{# Frame pointer register }
frame_pointer_reg = stack_pointer_reg;
NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
{# Self pointer register : contains the instance address of an
object or class. }
self_pointer_reg = R_9;
NR_SELF_POINTER_REG = NR_R9;
RS_SELF_POINTER_REG = RS_R9;
{# Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific. For
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
@ -658,28 +649,23 @@ uses
Taken from GCC rs6000.h
}
{$warning As indicated in rs6000.h, but can't find it anywhere else!}
pic_offset_reg = R_30;
{# Results are returned in this register (32-bit values) }
accumulator = R_3;
NR_ACCUMULATOR = NR_R3;
RS_ACCUMULATOR = RS_R3;
{the return_result_reg, is used inside the called function to store its return
value when that is a scalar value otherwise a pointer to the address of the
result is placed inside it}
return_result_reg = accumulator;
NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
NR_PIC_OFFSET_REG = NR_R30;
{ Results are returned in this register (32-bit values) }
NR_FUNCTION_RETURN_REG = NR_R3;
RS_FUNCTION_RETURN_REG = RS_R3;
{ High part of 64bit return value }
NR_FUNCTION_RETURNHIGH_REG = NR_R4;
RS_FUNCTION_RETURNHIGH_REG = RS_R4;
{ The value returned from a function is available in this register }
NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
{ The high part of 64bit value returned from a function is available in this register }
NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG;
RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG;
{the function_result_reg contains the function result after a call to a scalar
function othewise it contains a pointer to the returned result}
function_result_reg = accumulator;
{# Hi-Results are returned in this register (64-bit value high register) }
accumulatorhigh = R_4;
NR_ACCUMULATORHIGH = NR_R4;
RS_ACCUMULATORHIGH = RS_R4;
{ WARNING: don't change to R_ST0!! See comments above implementation of }
{ a_loadfpu* methods in rgcpu (JM) }
fpu_result_reg = R_F1;
FPU_RESULT_REG = R_F1;
mmresultreg = R_M0;
{*****************************************************************************
@ -731,6 +717,7 @@ uses
procedure convert_register_to_enum(var r:Tregister);
function cgsize2subreg(s:Tcgsize):Tsubregister;
implementation
uses
@ -792,7 +779,6 @@ implementation
procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
begin
r.simple := true;
r.cond := cond;
@ -803,64 +789,69 @@ implementation
end;
end;
procedure convert_register_to_enum(var r:Tregister);
begin
if r.enum = R_INTREGISTER then
if (r.number >= NR_NO) and
(r.number <= NR_R31) then
r.enum := toldregister(r.number shr 8)
else
begin
if r.enum = R_INTREGISTER then
if (r.number >= NR_NO) and
(r.number <= NR_R31) then
r.enum := toldregister(r.number shr 8)
else
{ case r.number of
NR_NO: r.enum:= R_NO;
NR_NO: r.enum:= R_NO;
NR_R0: r.enum:= R_0;
NR_R1: r.enum:= R_1;
NR_R2: r.enum:= R_2;
NR_R3: r.enum:= R_3;
NR_R4: r.enum:= R_4;
NR_R5: r.enum:= R_5;
NR_R6: r.enum:= R_6;
NR_R7: r.enum:= R_7;
NR_R8: r.enum:= R_8;
NR_R9: r.enum:= R_9;
NR_R10: r.enum:= R_10;
NR_R11: r.enum:= R_11;
NR_R12: r.enum:= R_12;
NR_R13: r.enum:= R_13;
NR_R14: r.enum:= R_14;
NR_R15: r.enum:= R_15;
NR_R16: r.enum:= R_16;
NR_R17: r.enum:= R_17;
NR_R18: r.enum:= R_18;
NR_R19: r.enum:= R_19;
NR_R20: r.enum:= R_20;
NR_R21: r.enum:= R_21;
NR_R22: r.enum:= R_22;
NR_R23: r.enum:= R_23;
NR_R24: r.enum:= R_24;
NR_R25: r.enum:= R_25;
NR_R26: r.enum:= R_26;
NR_R27: r.enum:= R_27;
NR_R28: r.enum:= R_28;
NR_R29: r.enum:= R_29;
NR_R30: r.enum:= R_30;
NR_R31: r.enum:= R_31;
NR_R0: r.enum:= R_0;
NR_R1: r.enum:= R_1;
NR_R2: r.enum:= R_2;
NR_R3: r.enum:= R_3;
NR_R4: r.enum:= R_4;
NR_R5: r.enum:= R_5;
NR_R6: r.enum:= R_6;
NR_R7: r.enum:= R_7;
NR_R8: r.enum:= R_8;
NR_R9: r.enum:= R_9;
NR_R10: r.enum:= R_10;
NR_R11: r.enum:= R_11;
NR_R12: r.enum:= R_12;
NR_R13: r.enum:= R_13;
NR_R14: r.enum:= R_14;
NR_R15: r.enum:= R_15;
NR_R16: r.enum:= R_16;
NR_R17: r.enum:= R_17;
NR_R18: r.enum:= R_18;
NR_R19: r.enum:= R_19;
NR_R20: r.enum:= R_20;
NR_R21: r.enum:= R_21;
NR_R22: r.enum:= R_22;
NR_R23: r.enum:= R_23;
NR_R24: r.enum:= R_24;
NR_R25: r.enum:= R_25;
NR_R26: r.enum:= R_26;
NR_R27: r.enum:= R_27;
NR_R28: r.enum:= R_28;
NR_R29: r.enum:= R_29;
NR_R30: r.enum:= R_30;
NR_R31: r.enum:= R_31;
else}
internalerror(200301082);
internalerror(200301082);
{ end;}
end;
end;
function cgsize2subreg(s:Tcgsize):Tsubregister;
begin
cgsize2subreg:=R_SUBWHOLE;
end;
begin
cgsize2subreg:=R_SUBWHOLE;
end;
end.
{
$Log$
Revision 1.53 2003-05-30 18:49:59 jonas
Revision 1.54 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.53 2003/05/30 18:49:59 jonas
* changed scratchregs from r28-r30 to r29-r31
* made sure the regvar registers don't overlap with the scratchregs
anymore
@ -924,10 +915,10 @@ end.
+ some comments describing the fields of treference
Revision 1.36 2002/11/17 18:26:16 mazen
* fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
* fixed a compilation bug accmulator-->FUNCTION_RETURN_REG, in definition of return_result_reg
Revision 1.35 2002/11/17 17:49:09 mazen
+ return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
+ return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
Revision 1.34 2002/09/17 18:54:06 jonas
* a_load_reg_reg() now has two size parameters: source and dest. This

View File

@ -83,6 +83,7 @@ interface
srsym,sym : tsym;
srsymtable : tsymtable;
code : TAAsmoutput;
framereg : tregister;
i,l : longint;
procedure writeasmline;
@ -104,6 +105,9 @@ interface
begin
ende:=false;
framereg.enum:=R_INTREGISTER;
framereg.number:=NR_STACK_POINTER_REG;
convert_register_to_enum(framereg);
s:='';
if assigned(current_procdef.funcretsym) and
is_fpu(current_procdef.rettype.def) then
@ -191,11 +195,11 @@ interface
if (tvarsym(sym).reg.enum<>R_NO) then
// until new regallocator stuff settles down
// hs:=gas_reg2str[procinfo.framepointer.enum]
hs:=gas_reg2str[STACK_POINTER_REG]
hs:=gas_reg2str[framereg.enum]
else
hs:=tostr(tvarsym(sym).address)+
// '('+gas_reg2str[procinfo.framepointer.enum]+')';
'('+gas_reg2str[STACK_POINTER_REG]+')';
'('+gas_reg2str[framereg.enum]+')';
end;
end
else
@ -217,7 +221,7 @@ interface
{ set offset }
inc(l,current_procdef.parast.address_fixup);
// hs:=tostr(l)+'('+gas_reg2str[procinfo.framepointer.enum]+')';
hs:=tostr(l)+'('+gas_reg2str[STACK_POINTER_REG]+')';
hs:=tostr(l)+'('+gas_reg2str[framereg.enum]+')';
if pos(',',s) > 0 then
tvarsym(sym).varstate:=vs_used;
end;
@ -347,7 +351,12 @@ initialization
end.
{
$Log$
Revision 1.13 2003-04-27 11:21:36 peter
Revision 1.14 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.13 2003/04/27 11:21:36 peter
* aktprocdef renamed to current_procdef
* procinfo renamed to current_procinfo
* procinfo will now be stored in current_module so it can be

View File

@ -1210,8 +1210,13 @@ begin
end.
{
$Log$
Revision 1.119 2003-05-28 23:58:18 jonas
* added missing initialization of rg.usedint{in,by}proc
Revision 1.120 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.119 2003/05/28 23:58:18 jonas
* added missing initialization of rg.usedintin,byproc
* ppc now also saves/restores used fpu registers
* ncgcal doesn't add used registers to usedby/inproc anymore, except for
i386

View File

@ -28,7 +28,7 @@ Interface
Uses
cutils,cclasses,
globtype,aasmbase,aasmtai,cpubase,cpuinfo,
globtype,aasmbase,aasmtai,cpubase,cpuinfo,cginfo,
symconst,symbase,symtype,symdef;
Const
@ -85,14 +85,14 @@ type
end;
TOperand = class
size : topsize;
hastype, { if the operand has typecasted variable }
hasvar : boolean; { if the operand is loaded with a variable }
size : TCGSize;
opr : TOprRec;
constructor create;
destructor destroy;override;
Procedure BuildOperand;virtual;
Procedure SetSize(_size:longint;force:boolean);
Procedure SetSize(_size:longint;force:boolean);virtual;
Procedure SetCorrectSize(opcode:tasmop);virtual;
Function SetupResult:boolean;virtual;
Function SetupSelf:boolean;
@ -104,7 +104,6 @@ type
TInstruction = class
opcode : tasmop;
opsize : topsize;
condition : tasmcond;
ops : byte;
labeled : boolean;
@ -690,7 +689,7 @@ end;
constructor TOperand.Create;
begin
size:=S_NO;
size:=OS_NO;
hastype:=false;
hasvar:=false;
FillChar(Opr,sizeof(Opr),0);
@ -702,32 +701,33 @@ begin
end;
Procedure TOperand.SetCorrectSize(opcode:tasmop);
begin
end;
Procedure TOperand.SetSize(_size:longint;force:boolean);
begin
if force or
((size = S_NO) and (_size<=extended_size)) then
((size = OS_NO) and (_size<=extended_size)) then
Begin
case _size of
1 : size:=S_B;
2 : size:=S_W{ could be S_IS};
4 : size:=S_L{ could be S_IL or S_FS};
8 : size:=S_IQ{ could be S_D or S_FL};
1 : size:=OS_8;
2 : size:=OS_16{ could be S_IS};
4 : size:=OS_32{ could be S_IL or S_FS};
8 : size:=OS_64{ could be S_D or S_FL};
else
begin
{ extended_size can also be 8, resulting in a
duplicate label }
if _size=extended_size then
size:=S_FX;
size:=OS_F80;
end;
end;
end;
end;
Procedure TOperand.SetCorrectSize(opcode:tasmop);
begin
end;
Function TOperand.SetupResult:boolean;
Begin
SetupResult:=false;
@ -1016,7 +1016,6 @@ end;
constructor TInstruction.create;
Begin
Opcode:=A_NONE;
Opsize:=S_NO;
Condition:=C_NONE;
Ops:=0;
InitOperands;
@ -1554,7 +1553,12 @@ end;
end.
{
$Log$
Revision 1.61 2003-05-25 08:55:49 peter
Revision 1.62 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.61 2003/05/25 08:55:49 peter
* load result using hidden parameter
Revision 1.60 2003/05/15 18:58:53 peter

View File

@ -1,10 +1,8 @@
{*****************************************************************************
{
$Id$
Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
Copyright (c) 1999-2002 by Mazen Neifer
* This code was inspired by the NASM sources
The Netwide Assembler is copyright (C) 1996 Simon Tatham and
Julian Hall. All rights reserved.
Contains the assembler object for the SPARC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,379 +17,254 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************}
****************************************************************************
}
unit aasmcpu;
{$INCLUDE fpcdefs.inc}
{$i fpcdefs.inc}
interface
uses
cclasses,globals,verbose,
cpuinfo,cpubase,
symppu,
aasmbase,aasmtai;
const
MaxPrefixes=4;
type
{ alignment for operator }
tai_align=class(tai_align_abstract)
reg:tregister;
constructor create(b:byte);
constructor create_op(b:byte; _op:byte);
end;
taicpu = class(taicpu_abstract)
opsize:topsize;
constructor op_none(op:tasmop);
constructor op_reg(op:tasmop;reg:tregister);
constructor op_const(op:tasmop;_op1:aword);
constructor op_ref(op:tasmop;const _op1:treference);
constructor op_reg_reg(op:tasmop;_op1,_op2:tregister);
constructor op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
constructor op_reg_const(op:tasmop;_op1:tregister;_op2:aword);
constructor op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
constructor op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
constructor op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
constructor op_reg_const_reg(Op:TAsmOp;SrcReg:TRegister;value:aWord;DstReg:TRegister);
constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
cclasses,aasmtai,
aasmbase,globals,verbose,
cpubase,cpuinfo;
{ this is for Jmp instructions }
constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
procedure changeopsize(siz:topsize);
private
procedure init(_size:topsize);{this need to be called by all constructor}
public
{ the next will reset all instructions that can change in pass 2 }
procedure SetCondition(const c:TAsmCond);
private
{ next fields are filled in pass1, so pass2 is faster }
procedure Swatoperands;
end;
PROCEDURE DoneAsm;
PROCEDURE InitAsm;
implementation
uses
cutils,
CpuGas;
const
_size=S_SW;{To be removed soon}
{****************************************************************************
TAI_ALIGN
****************************************************************************}
constructor tai_align.create(b:byte);
begin
inherited create(b);
reg.enum:= R_NONE;
end;
constructor tai_align.create_op(b:byte; _op:byte);
begin
inherited create_op(b,_op);
reg.enum:= R_NONE;
end;
{*****************************************************************************
Taicpu Constructors
*****************************************************************************}
procedure taicpu.changeopsize(siz:topsize);
begin
opsize:=siz;
end;
procedure taicpu.init(_size:topsize);
begin
opsize:=_size;
end;
constructor taicpu.op_none(op:tasmop);
begin
inherited create(op);
init(_size);
end;
constructor taicpu.op_reg(op:tasmop;reg:tregister);
begin
inherited create(op);
init(_size);
ops:=1;
loadreg(0,reg);
end;
constructor taicpu.op_const(op:tasmop;_op1:aword);
begin
inherited create(op);
init(_size);
ops:=1;
loadconst(0,aword(_op1));
end;
constructor taicpu.op_ref(op:tasmop;const _op1:treference);
begin
inherited create(op);
init(_size);
ops:=1;
loadref(0,_op1);
end;
constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister);
begin
inherited create(op);
init(_size);
ops:=2;
loadreg(0,_op1);
loadreg(1,_op2);
end;
constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword);
begin
inherited create(op);
init(_size);
ops:=2;
loadreg(0,_op1);
loadconst(1,aword(_op2));
end;
constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference);
begin
if not(Op in [A_STB..A_STDFQ])
then
fail;
inherited Create(Op);
init(_size);
ops:=2;
LoadReg(0,Reg);
LoadRef(1,Ref);
end;
constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister);
begin
inherited create(op);
init(_size);
ops:=2;
loadconst(0,aword(_op1));
loadreg(1,_op2);
end;
constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister);
begin
if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP])
then
InternalError(2003042900);
inherited Create(Op);
Init(S_SW);
Ops:=2;
LoadRef(0,Ref);
LoadReg(1,Reg);
end;
constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference);
begin
inherited create(op);
init(_size);
ops:=2;
loadref(0,_op1);
loadref(1,_op2);
end;
constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister);
begin
inherited create(op);
init(_size);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
begin
inherited create(op);
init(_size);
ops:=3;
loadreg(0,_op1);
loadref(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister);
begin
inherited Create(Op);
Init(S_W);
ops:=3;
LoadReg(0,SrcReg);
LoadConst(1,Value);
LoadReg(2,DstReg);
end;
constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister);
begin
inherited create(op);
init(_size);
ops:=3;
loadconst(0,aword(_op1));
loadref(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference);
begin
inherited create(op);
init(_size);
ops:=3;
loadconst(0,aword(_op1));
loadreg(1,_op2);
loadref(2,_op3);
end;
constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol);
begin
inherited create(op);
init(_size);
condition:=cond;
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol);
begin
inherited create(op);
init(_size);
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint);
begin
inherited create(op);
init(_size);
ops:=1;
loadsymbol(0,_op1,_op1ofs);
end;
constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister);
begin
inherited create(op);
init(_size);
ops:=2;
loadsymbol(0,_op1,_op1ofs);
loadreg(1,_op2);
end;
type
taicpu = class(taicpu_abstract)
constructor op_none(op : tasmop);
constructor op_reg(op : tasmop;_op1 : tregister);
constructor op_ref(op : tasmop;const _op1 : treference);
constructor op_const(op : tasmop;_op1 : aword);
constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference);
begin
inherited create(op);
init(_size);
ops:=2;
loadsymbol(0,_op1,_op1ofs);
loadref(1,_op2);
end;
constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aword);
constructor op_const_reg(op:tasmop; _op1: aword; _op2: tregister);
constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
procedure taicpu.Swatoperands;
var
p:TOper;
begin
{ Fix the operands which are in AT&T style and we need them in Intel style }
case ops of
2:begin
{ 0,1 -> 1,0 }
p:=oper[0];
oper[0]:=oper[1];
oper[1]:=p;
end;
3:begin
{ 0,1,2 -> 2,1,0 }
p:=oper[0];
oper[0]:=oper[2];
oper[2]:=p;
end;
end;
end;
{ This check must be done with the operand in ATT order
i.e.after swapping in the intel reader
but before swapping in the NASM and TASM writers PM }
{*****************************************************************************
Assembler
*****************************************************************************}
procedure TAiCpu.SetCondition(const c:TAsmCond);
const
AsmCond2OpCode:array[TAsmCond]of TAsmOp=
(A_BN,A_BNE,A_BE,A_BG,A_BLE,A_BGE,A_BL,A_BGU,A_BLEU,A_BCC,
A_BCS,A_BPOS,A_NEG,A_BVC,A_BVS,A_BA,A_BNE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE);
begin
inherited SetCondition(c);
if Opcode=A_BA
then
begin
is_jmp:=true;
Opcode:=AsmCond2OpCode[c];
{$IFDEF EXTDEBUG}
WriteLn('In TAiCpu.SetCondition TAsmCond=',cond2str[c],'==>',std_op2str[OpCode]);
{$ENDIF EXTDEBUG}
constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
constructor op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aword;_op3:tregister);
constructor op_const_ref_reg(op:tasmop;_op1:aword;const _op2:treference;_op3:tregister);
constructor op_const_reg_ref(op:tasmop;_op1:aword;_op2:tregister;const _op3:treference);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
constructor op_sym(op : tasmop;_op1 : tasmsymbol);
constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
end;
end;
procedure DoneAsm;
begin
end;
procedure InitAsm;
begin
end;
tai_align = class(tai_align_abstract)
{ nothing to add }
end;
procedure InitAsm;
procedure DoneAsm;
implementation
{*****************************************************************************
taicpu Constructors
*****************************************************************************}
constructor taicpu.op_none(op : tasmop);
begin
inherited create(op);
end;
constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031207);
ops:=1;
loadreg(0,_op1);
end;
constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
begin
inherited create(op);
ops:=1;
loadref(0,_op1);
end;
constructor taicpu.op_const(op : tasmop;_op1 : aword);
begin
inherited create(op);
ops:=1;
loadconst(0,_op1);
end;
constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031205);
if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
internalerror(2003031206);
ops:=2;
loadreg(0,_op1);
loadreg(1,_op2);
end;
constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aword);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031208);
ops:=2;
loadreg(0,_op1);
loadconst(1,_op2);
end;
constructor taicpu.op_const_reg(op:tasmop; _op1: aword; _op2: tregister);
begin
inherited create(op);
if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
internalerror(2003031209);
ops:=2;
loadconst(0,_op1);
loadreg(1,_op2);
end;
constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031210);
ops:=2;
loadreg(0,_op1);
loadref(1,_op2);
end;
constructor taicpu.op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
begin
inherited create(op);
if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
internalerror(2003031210);
ops:=2;
loadref(0,_op1);
loadreg(1,_op2);
end;
constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031211);
if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
internalerror(2003031212);
if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
internalerror(2003031213);
ops:=3;
loadreg(0,_op1);
loadreg(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031214);
if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
internalerror(2003031215);
ops:=3;
loadreg(0,_op1);
loadref(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aword;_op3:tregister);
begin
inherited create(op);
if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then
internalerror(2003031216);
if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
internalerror(2003031217);
ops:=3;
loadreg(0,_op1);
loadconst(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_const_ref_reg(op:tasmop;_op1:aword;const _op2:treference;_op3:tregister);
begin
inherited create(op);
if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then
internalerror(2003031218);
ops:=3;
loadconst(0,_op1);
loadref(1,_op2);
loadreg(2,_op3);
end;
constructor taicpu.op_const_reg_ref(op:tasmop;_op1:aword;_op2:tregister;const _op3:treference);
begin
inherited create(op);
if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then
internalerror(2003031219);
ops:=3;
loadconst(0,_op1);
loadreg(1,_op2);
loadref(2,_op3);
end;
constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_op1:tasmsymbol);
begin
inherited create(op);
condition:=cond;
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
begin
inherited create(op);
ops:=1;
loadsymbol(0,_op1,0);
end;
constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
begin
inherited create(op);
ops:=1;
loadsymbol(0,_op1,_op1ofs);
end;
procedure InitAsm;
begin
end;
procedure DoneAsm;
begin
end;
end.
{
$Log$
Revision 1.26 2003-05-28 23:18:31 florian
* started to fix and clean up the sparc port
$Log$
Revision 1.27 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.25 2003/05/07 11:45:02 mazen
- removed unused code
Revision 1.24 2003/05/07 11:28:26 mazen
- method CheckNonCommutativeOpcode removed as not used
Revision 1.23 2003/05/06 20:27:43 mazen
* A_BI changed to A_BL
Revision 1.22 2003/05/06 15:00:36 mazen
- non used code removed to bring up with powerpc changes
Revision 1.21 2003/04/29 11:06:15 mazen
* test of invalid opcode/operand combination gives internal error
Revision 1.20 2003/04/28 09:40:47 mazen
* Debug message in SetCondition more explicit.
Revision 1.19 2003/03/15 22:51:58 mazen
* remaking sparc rtl compile
Revision 1.18 2003/03/10 21:59:54 mazen
* fixing index overflow in handling new registers arrays.
Revision 1.17 2003/02/18 22:00:20 mazen
* asm condition generation modified by TAiCpu.SetCondition
Revision 1.16 2003/01/08 18:43:58 daniel
* Tregister changed into a record
Revision 1.15 2003/01/05 21:32:35 mazen
* fixing several bugs compiling the RTL
Revision 1.14 2002/12/14 15:02:03 carl
* maxoperands -> max_operands (for portability in rautils.pas)
* fix some range-check errors with loadconst
+ add ncgadd unit to m68k
* some bugfix of a_param_reg with LOC_CREFERENCE
Revision 1.13 2002/11/17 16:32:04 carl
* memory optimization (3-4%) : cleanup of tai fields,
cleanup of tdef and tsym fields.
* make it work for m68k
Revision 1.12 2002/11/10 19:07:46 mazen
* SPARC calling mechanism almost OK (as in GCC./mppcsparc )
Revision 1.11 2002/11/06 11:31:24 mazen
* op_reg_reg_reg don't need any more a TOpSize parameter
Revision 1.10 2002/11/05 16:15:00 mazen
*** empty log message ***
Revision 1.9 2002/10/28 20:59:17 mazen
* TOpSize values changed S_L --> S_SW
Revision 1.8 2002/10/22 13:43:01 mazen
- cga.pas redueced to an empty unit
Revision 1.7 2002/10/20 19:01:38 mazen
+ op_raddr_reg and op_caddr_reg added to fix functions prologue
Revision 1.6 2002/10/19 20:35:07 mazen
* carl's patch applied
Revision 1.5 2002/10/15 09:00:28 mazen
* sone coding style modified
Revision 1.4 2002/10/13 21:46:07 mazen
* assembler output format fixed
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -48,20 +48,17 @@ unit cpugas;
begin
inc(offset,offsetfixup);
offsetfixup:=0;
if base.enum>lastreg then
if (base.enum<>R_INTREGISTER) or (index.enum<>R_INTREGISTER) then
internalerror(200301081);
if index.enum>lastreg then
internalerror(200301081);
if assigned(symbol) then
begin
if (base.number<>NR_NO) or (index.number<>NR_NO) then
internalerror(2003052601);
GetReferenceString:=symbol.name;
if offset>0 then
GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
else if offset<0 then
GetReferenceString:=GetReferenceString+ToStr(offset);
if (base.enum<>R_NONE) or (index.enum<>R_NONE) then
internalerror(2003052601);
if symaddr=refs_hi then
GetReferenceString:='%hi('+GetReferenceString+')'
else if symaddr=refs_lo then
@ -71,9 +68,9 @@ unit cpugas;
end
else
begin
if base.enum<>R_NONE then
if base.number<>NR_NO then
GetReferenceString:=std_reg2str[base.enum]+'+';
if index.enum<>R_NONE then
if index.number<>NR_NO then
GetReferenceString:=GetReferenceString+std_reg2str[index.enum]+'+';
if Offset<>0 then
internalerror(2003052603);
@ -199,7 +196,12 @@ begin
end.
{
$Log$
Revision 1.15 2003-05-28 23:18:31 florian
Revision 1.16 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.15 2003/05/28 23:18:31 florian
* started to fix and clean up the sparc port
Revision 1.14 2003/05/07 11:55:34 mazen

View File

@ -1,8 +1,8 @@
{******************************************************************************
{
$Id$
Copyright (c) 2002 by Florian Klaempfl
Copyright (c) 1998-2002 by Florian Klaempfl
PowerPC specific calling conventions
Calling conventions for the SPARC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,269 +19,296 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************}
unit cpupara;
{SPARC specific calling conventions are handled by this unit}
{$INCLUDE fpcdefs.inc}
{$i fpcdefs.inc}
interface
uses
cpubase,
symconst,symbase,symtype,symdef,paramgr;
type
TSparcParaManager=class(TParaManager)
{Returns a structure giving the information on the storage of the parameter
(which must be an integer parameter)
@param(nr Parameter number of routine, starting from 1)}
function GetIntParaLoc(nr:longint):TParaLocation;override;
{Creates location information related to the parameter of the function}
procedure create_param_loc_info(p:TAbstractProcDef);override;
{Returns the location where the invisible parameter for structured function
results will be passed.}
function GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;override;
end;
uses
cpubase,
symconst,symbase,symtype,symdef,paramgr;
type
TSparcParaManager=class(TParaManager)
{Returns a structure giving the information on the storage of the parameter
(which must be an integer parameter)
@param(nr Parameter number of routine, starting from 1)}
function GetIntParaLoc(nr:longint):TParaLocation;override;
{Creates location information related to the parameter of the function}
procedure create_param_loc_info(p:TAbstractProcDef);override;
{Returns the location where the invisible parameter for structured function
results will be passed.}
function GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;override;
end;
implementation
uses
verbose,
cpuinfo,cginfo,cgbase,
defutil;
function TSparcParaManager.GetIntParaLoc(nr:longint):TParaLocation;
begin
if nr<1
then
InternalError(2002100806);
FillChar(GetIntParaLoc,SizeOf(TParaLocation),0);
Dec(nr);
with GetIntParaLoc do
if nr<6
then{The six first parameters are passed into registers}
begin
loc:=LOC_REGISTER;
register.enum:=ToldRegister(LongInt(R_i0)+nr);
end
else{The other parameters are passed into the frame}
begin
loc:=LOC_REFERENCE;
reference.index.enum:=frame_pointer_reg;
reference.offset:=-68-nr*4;
end;
end;
function GetParaLoc(p:TDef):TCGLoc;
begin
{Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER if
push_addr_param for the def is true}
case p.DefType of
OrdDef:
GetParaLoc:=LOC_REGISTER;
FloatDef:
GetParaLoc:=LOC_FPUREGISTER;
enumdef:
getparaloc:=LOC_REGISTER;
pointerdef:
getparaloc:=LOC_REGISTER;
formaldef:
getparaloc:=LOC_REGISTER;
classrefdef:
getparaloc:=LOC_REGISTER;
recorddef:
getparaloc:=LOC_REFERENCE;
objectdef:
if is_object(p)
then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
stringdef:
if is_shortstring(p) or is_longstring(p)
then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
procvardef:
if (po_methodpointer in tprocvardef(p).procoptions)
then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
filedef:
getparaloc:=LOC_REGISTER;
arraydef:
getparaloc:=LOC_REFERENCE;
setdef:
if is_smallset(p)
then
getparaloc:=LOC_REGISTER
else
getparaloc:=LOC_REFERENCE;
variantdef:
getparaloc:=LOC_REFERENCE;
{ avoid problems with errornous definitions }
errordef:
getparaloc:=LOC_REGISTER;
else
internalerror(2002071001);
end;
end;
procedure TSparcParaManager.create_param_loc_info(p:TAbstractProcDef);
var
nextintreg,nextfloatreg:tregister;
stack_offset:aword;
hp:tparaitem;
loc:tcgloc;
is_64bit:boolean;
begin
nextintreg.enum:=R_O0;
nextfloatreg.enum:=R_F0;
stack_offset:=92;
hp:=TParaItem(p.para.First);
while assigned(hp) do
uses
verbose,
cpuinfo,cginfo,cgbase,
defutil;
function TSparcParaManager.GetIntParaLoc(nr:longint):TParaLocation;
begin
loc:=GetParaLoc(hp.paratype.def);
case loc of
LOC_REGISTER:
if nr<1 then
InternalError(2002100806);
FillChar(GetIntParaLoc,SizeOf(TParaLocation),0);
Dec(nr);
with GetIntParaLoc do
begin
{ The six first parameters are passed into registers }
if nr<6 then
begin
hp.paraloc.size:=def_cgSize(hp.paratype.def);
if hp.paraloc.size=OS_NO
then
hp.paraloc.size:=OS_ADDR;
is_64bit:=hp.paraloc.size in [OS_64,OS_S64];
if NextIntReg.enum<=ToldRegister(ord(R_i5)-ord(is_64bit))
then
begin
hp.paraloc.loc:=LOC_REGISTER;
hp.paraloc.registerlow:=NextIntReg;
inc(NextIntReg.enum);
if is_64bit
then
begin
hp.paraloc.registerhigh:=nextintreg;
inc(nextintreg.enum);
end;
end
else
begin
nextintreg.enum:=R_i6;
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=stack_pointer_reg;
hp.paraloc.reference.offset:=stack_offset;
if not is_64bit
then
inc(stack_offset,4)
else
inc(stack_offset,8);
end;
loc:=LOC_REGISTER;
register.enum:=R_INTREGISTER;
register.number:=(RS_I0+nr) shl 8;
end
else
{ The other parameters are passed into the frame }
begin
loc:=LOC_REFERENCE;
reference.index.enum:=R_INTREGISTER;
reference.index.number:=NR_FRAME_POINTER_REG;
reference.offset:=-68-nr*4;
end;
LOC_FPUREGISTER:
begin
if hp.paratyp in [vs_var,vs_out]
then
end;
end;
function GetParaLoc(p:TDef):TCGLoc;
begin
{ Later, the LOC_REFERENCE is in most cases changed into
LOC_REGISTER if push_addr_param for the def is true}
case p.DefType of
OrdDef:
GetParaLoc:=LOC_REGISTER;
FloatDef:
GetParaLoc:=LOC_FPUREGISTER;
enumdef:
getparaloc:=LOC_REGISTER;
pointerdef:
getparaloc:=LOC_REGISTER;
formaldef:
getparaloc:=LOC_REGISTER;
classrefdef:
getparaloc:=LOC_REGISTER;
recorddef:
getparaloc:=LOC_REFERENCE;
objectdef:
if is_object(p) then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
stringdef:
if is_shortstring(p) or is_longstring(p) then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
procvardef:
if (po_methodpointer in tprocvardef(p).procoptions) then
getparaloc:=LOC_REFERENCE
else
getparaloc:=LOC_REGISTER;
filedef:
getparaloc:=LOC_REGISTER;
arraydef:
getparaloc:=LOC_REFERENCE;
setdef:
if is_smallset(p) then
getparaloc:=LOC_REGISTER
else
getparaloc:=LOC_REFERENCE;
variantdef:
getparaloc:=LOC_REFERENCE;
{ avoid problems with errornous definitions }
errordef:
getparaloc:=LOC_REGISTER;
else
internalerror(2002071001);
end;
end;
procedure TSparcParaManager.create_param_loc_info(p:TAbstractProcDef);
var
nextintreg : tsuperregister;
nextfloatreg : toldregister;
stack_offset : longint;
hp : tparaitem;
loc : tcgloc;
is_64bit : boolean;
begin
nextintreg:=RS_O0;
nextfloatreg:=R_F0;
stack_offset:=92;
hp:=TParaItem(p.para.First);
while assigned(hp) do
begin
loc:=GetParaLoc(hp.paratype.def);
case loc of
LOC_REGISTER:
begin
if NextIntReg.enum<=R_O5
then
hp.paraloc.size:=def_cgSize(hp.paratype.def);
if hp.paraloc.size=OS_NO then
hp.paraloc.size:=OS_ADDR;
is_64bit:=(hp.paraloc.size in [OS_64,OS_S64]);
if NextIntReg<=RS_I5-ord(is_64bit) then
begin
hp.paraloc.size:=OS_ADDR;
hp.paraloc.loc:=LOC_REGISTER;
hp.paraloc.register:=nextintreg;
inc(nextintreg.enum);
hp.paraloc.registerlow.enum:=R_INTREGISTER;
hp.paraloc.registerlow.number:=NextIntReg shl 8;
inc(NextIntReg);
if is_64bit then
begin
hp.paraloc.registerhigh.enum:=R_INTREGISTER;
hp.paraloc.registerhigh.number:=nextintreg shl 8;
inc(nextintreg);
end;
end
else
begin
nextintreg:=RS_I6;
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=R_INTREGISTER;
hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG;
hp.paraloc.reference.offset:=stack_offset;
if not is_64bit then
inc(stack_offset,4)
else
inc(stack_offset,8);
end;
end;
LOC_FPUREGISTER:
begin
if hp.paratyp in [vs_var,vs_out] then
begin
if NextIntReg<=RS_O5 then
begin
hp.paraloc.size:=OS_ADDR;
hp.paraloc.loc:=LOC_REGISTER;
hp.paraloc.register.enum:=R_INTREGISTER;
hp.paraloc.register.number:=nextintreg shl 8;
inc(nextintreg);
end
else
begin
{!!!!!!!}
hp.paraloc.size:=def_cgsize(hp.paratype.def);
internalerror(2002071006);
end;
end
else if nextfloatreg<=R_F10 then
begin
hp.paraloc.size:=def_cgsize(hp.paratype.def);
hp.paraloc.loc:=LOC_FPUREGISTER;
hp.paraloc.register.enum:=nextfloatreg;
inc(nextfloatreg);
end
else
begin
{!!!!!!!}
hp.paraloc.size:=def_cgsize(hp.paratype.def);
internalerror(2002071006);
internalerror(2002071004);
end;
end
else if nextfloatreg.enum<=R_F10 then
begin
hp.paraloc.size:=def_cgsize(hp.paratype.def);
hp.paraloc.loc:=LOC_FPUREGISTER;
hp.paraloc.register:=nextfloatreg;
inc(nextfloatreg.enum);
end
else
begin
{!!!!!!!}
hp.paraloc.size:=def_cgsize(hp.paratype.def);
internalerror(2002071004);
end;
LOC_REFERENCE:
begin
hp.paraloc.size:=OS_ADDR;
if push_addr_param(hp.paratype.def,p.proccalloption) or (hp.paratyp in [vs_var,vs_out]) then
begin
if nextintreg<=RS_O5 then
begin
hp.paraloc.loc:=LOC_REGISTER;
hp.paraloc.register.enum:=R_INTREGISTER;
hp.paraloc.register.number:=nextintreg shl 8;
inc(nextintreg);
end
else
begin
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=R_INTREGISTER;
hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG;
hp.paraloc.reference.offset:=stack_offset;
inc(stack_offset,4);
end;
end
else
begin
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=R_INTREGISTER;
hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG;
hp.paraloc.reference.offset:=stack_offset;
inc(stack_offset,hp.paratype.def.size);
end;
end;
else
internalerror(2002071002);
end;
LOC_REFERENCE:
begin
hp.paraloc.size:=OS_ADDR;
if push_addr_param(hp.paratype.def,p.proccalloption) or (hp.paratyp in [vs_var,vs_out]) then
begin
if nextintreg.enum<=R_O5 then
begin
hp.paraloc.loc:=LOC_REGISTER;
hp.paraloc.register:=nextintreg;
inc(nextintreg.enum);
end
else
begin
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=stack_pointer_reg;
hp.paraloc.reference.offset:=stack_offset;
inc(stack_offset,4);
end;
end
else
begin
hp.paraloc.loc:=LOC_REFERENCE;
hp.paraloc.reference.index.enum:=stack_pointer_reg;
hp.paraloc.reference.offset:=stack_offset;
inc(stack_offset,hp.paratype.def.size);
end;
end;
else
internalerror(2002071002);
end;
hp:=TParaItem(hp.Next);
end;
end;
function tSparcParaManager.GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;
begin
with GetFuncRetParaLoc do
case p.rettype.def.deftype of
orddef,enumdef:
begin
loc:=LOC_REGISTER;
register.enum:=return_result_reg;
size:=def_cgsize(p.rettype.def);
if size in [OS_S64,OS_64]
then
RegisterHigh.enum:=R_I1;
hp:=TParaItem(hp.Next);
end;
floatdef:
begin
loc:=LOC_FPUREGISTER;
register.enum:=R_F1;
size:=def_cgsize(p.rettype.def);
end;
setdef,
variantdef,
pointerdef,
formaldef,
classrefdef,
recorddef,
objectdef,
stringdef,
procvardef,
filedef,
arraydef,
errordef:
begin
loc:=LOC_REFERENCE;
reference.index.enum:=frame_pointer_reg;
reference.offset:=64;
size:=OS_ADDR;
end;
else
internalerror(2002090903);
end;
end;
function tSparcParaManager.GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;
begin
with GetFuncRetParaLoc do
begin
case p.rettype.def.deftype of
orddef,enumdef:
begin
loc:=LOC_REGISTER;
register.enum:=R_INTREGISTER;
register.number:=NR_FUNCTION_RETURN_REG;
size:=def_cgsize(p.rettype.def);
if size in [OS_S64,OS_64] then
internalerror(200305309);
end;
floatdef:
begin
loc:=LOC_FPUREGISTER;
register.enum:=R_F1;
size:=def_cgsize(p.rettype.def);
end;
setdef,
variantdef,
pointerdef,
formaldef,
classrefdef,
recorddef,
objectdef,
stringdef,
procvardef,
filedef,
arraydef,
errordef:
begin
loc:=LOC_REFERENCE;
reference.index.enum:=R_INTREGISTER;
reference.index.number:=NR_FRAME_POINTER_REG;
reference.offset:=64;
size:=OS_ADDR;
end;
else
internalerror(2002090903);
end;
end;
end;
begin
ParaManager:=TSparcParaManager.create;
end.
{
$Log$
Revision 1.16 2003-04-23 13:35:39 peter
Revision 1.17 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.16 2003/04/23 13:35:39 peter
* fix sparc compile
Revision 1.15 2003/04/23 12:35:35 florian

View File

@ -101,7 +101,12 @@ begin
end.
{
$Log$
Revision 1.15 2003-05-23 22:33:48 florian
Revision 1.16 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.15 2003/05/23 22:33:48 florian
* fix some small flaws which prevent sparc linux system unit from compiling
* some reformatting done
@ -133,7 +138,7 @@ end.
+ added debug output on screen with -an command line option
Revision 1.8 2002/11/17 17:49:09 mazen
+ return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
+ return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
Revision 1.7 2002/11/14 21:42:08 mazen
* fixing return value variable address

View File

@ -48,14 +48,17 @@ implementation
**************************************}
,CpuGas
,ogcoff
,ogelf
;
end.
{
$Log$
Revision 1.3 2003-05-23 21:10:50 florian
Revision 1.4 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.3 2003/05/23 21:10:50 florian
* fixed sparc compiler compilation
Revision 1.2 2002/09/07 15:25:14 peter

View File

@ -34,8 +34,8 @@ type
procedure second_addfloat;
function GetResFlags(unsigned:Boolean):TResFlags;
procedure emit_compare(unsigned:boolean);
procedure left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean);
procedure emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extra_not,mboverflow:Boolean);
procedure left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean);
procedure emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean);
procedure emit_op_right_left(op:TAsmOp);
procedure Load_left_right(cmpop,load_constants:Boolean);
procedure pass_left_and_right;
@ -47,12 +47,11 @@ uses
cutils,verbose,globals,
symconst,symdef,SymType,paramgr,
aasmbase,aasmtai,aasmcpu,defutil,htypechk,
cgbase,pass_2,regvars,
cpuinfo,cgbase,pass_2,regvars,
cpupara,
ncon,nset,
ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
const
opsize_2_cgSize:array[S_B..S_L]of TCgSize=(OS_8,OS_16,OS_32);
procedure TSparcAddNode.clear_left_right(cmpop:Boolean);
begin
if(right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER])and(cmpop or(location.register.enum <> right.location.register.enum))
@ -160,7 +159,7 @@ procedure TSparcAddNode.second_addboolean;
then
exprasmlist.concat(taicpu.op_reg_reg(A_JMPL,left.location.register,right.location.register))
else
exprasmlist.concat(taicpu.op_reg_const(A_JMPL,left.location.register,longint(right.location.value)));
exprasmlist.concat(taicpu.op_reg_const(A_JMPL,left.location.register,right.location.value));
location.resflags := GetResFlags(true);
end;
else
@ -280,7 +279,7 @@ function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags;
end;
end;
end;
procedure TSparcAddNode.left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean);
procedure TSparcAddNode.left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean);
begin
if(left.location.loc=LOC_REGISTER)
then
@ -296,10 +295,10 @@ procedure TSparcAddNode.left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean);
begin
{maybe we can reuse a constant register when the operation is a comparison that
doesn't change the value of the register}
location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
location_force_reg(exprasmlist,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
end;
end;
procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extra_not,mboverflow:Boolean);
procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean);
var
power:LongInt;
hl4:TAsmLabel;
@ -398,12 +397,12 @@ procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extr
IF cs_check_overflow IN aktlocalswitches
THEN
begin
// getlabel(hl4);
objectlibrary.getlabel(hl4);
IF unsigned
THEN
exprasmList.concat(Taicpu.Op_sym(A_JMPL,S_NO,hl4))
exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4))
ELSE
exprasmList.concat(Taicpu.Op_sym(A_JMPL,S_NO,hl4));
exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4));
cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
cg.a_label(exprasmlist,hl4);
end;
@ -425,7 +424,7 @@ procedure TSparcAddNode.emit_compare(unsigned:boolean);
then
begin
{$ifdef ExtDebug}
if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>$ffffffff) or unsigned)
if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>aword($ffffffff)) or unsigned)
then
internalerror(2002080301);
{$endif extdebug}
@ -463,7 +462,7 @@ procedure TSparcAddNode.emit_compare(unsigned:boolean);
if useconst
then
exprasmlist.concat(taicpu.op_reg_const(op,
left.location.register,longint(right.location.value)))
left.location.register,right.location.value))
else
begin
exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
@ -495,7 +494,6 @@ procedure TSparcAddNode.second_add64bit;
var
op : TOpCG;
op1,op2 : TAsmOp;
hl4 : tasmlabel;
cmpop,
unsigned : boolean;
r : Tregister;
@ -600,6 +598,7 @@ procedure TSparcAddNode.second_add64bit;
var
tempreg64: tregister64;
zeroreg : tregister;
begin
firstcomplex(self);
@ -681,7 +680,7 @@ procedure TSparcAddNode.second_add64bit;
tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist,OS_INT)
else
tempreg64.reglo := left.location.registerlow;
if ((right.location.valueqword shr 32) <> 0) then
if (hi(right.location.valueqword) <> 0) then
tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist,OS_INT)
else
tempreg64.reghi := left.location.registerhigh;
@ -690,25 +689,25 @@ procedure TSparcAddNode.second_add64bit;
if (right.location.valueqword <> 0) then
{ negative values can be handled using SUB, }
{ positive values < 65535 using XOR. }
if (longint(right.location.valueqword) >= -32767) and
(longint(right.location.valueqword) < 0) then
if (longint(lo(right.location.valueqword)) >= -32767) and
(longint(lo(right.location.valueqword)) < 0) then
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
right.location.valueqword,
lo(right.location.valueqword),
left.location.registerlow,tempreg64.reglo)
else
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
right.location.valueqword,
lo(right.location.valueqword),
left.location.registerlow,tempreg64.reglo);
if ((right.location.valueqword shr 32) <> 0) then
if (longint(right.location.valueqword shr 32) >= -32767) and
(longint(right.location.valueqword shr 32) < 0) then
if (hi(right.location.valueqword)<>0) then
if (longint(hi(right.location.valueqword))>= -32767) and
(longint(hi(right.location.valueqword)) < 0) then
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
right.location.valueqword shr 32,
hi(right.location.valueqword),
left.location.registerhigh,tempreg64.reghi)
else
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
right.location.valueqword shr 32,
hi(right.location.valueqword),
left.location.registerhigh,tempreg64.reghi);
end
else
@ -720,14 +719,14 @@ procedure TSparcAddNode.second_add64bit;
tempreg64);
end;
r.enum:=R_G0;
cg.a_reg_alloc(exprasmlist,r);
exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,r,
tempreg64.reglo,tempreg64.reghi));
cg.a_reg_dealloc(exprasmlist,r);
if (tempreg64.reglo.enum <> left.location.registerlow.enum) then
zeroreg.enum:=R_INTREGISTER;
zeroreg.number:=NR_G0;
cg.a_reg_alloc(exprasmlist,zeroreg);
exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,zeroreg,tempreg64.reglo,tempreg64.reghi));
cg.a_reg_dealloc(exprasmlist,zeroreg);
if (tempreg64.reglo.number <> left.location.registerlow.number) then
cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
if (tempreg64.reghi.enum <> left.location.registerhigh.enum) then
if (tempreg64.reghi.number <> left.location.registerhigh.number) then
cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
location_reset(location,LOC_FLAGS,OS_NO);
@ -735,7 +734,7 @@ procedure TSparcAddNode.second_add64bit;
end;
xorn,orn,andn,addn:
begin
if (location.registerlow.enum = R_NO) then
if (location.registerlow.number = NR_NO) then
begin
location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
@ -757,7 +756,7 @@ procedure TSparcAddNode.second_add64bit;
if left.location.loc <> LOC_CONSTANT then
begin
if (location.registerlow.enum = R_NO) then
if (location.registerlow.number = NR_NO) then
begin
location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
@ -775,7 +774,7 @@ procedure TSparcAddNode.second_add64bit;
end
else if ((left.location.valueqword shr 32) = 0) then
begin
if (location.registerlow.enum = R_NO) then
if (location.registerlow.number = NR_NO) then
begin
location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
@ -802,7 +801,7 @@ procedure TSparcAddNode.second_add64bit;
else if (left.location.valueqword = 0) then
begin
// (const32 shl 32) - reg64
if (location.registerlow.enum = R_NO) then
if (location.registerlow.number = NR_NO) then
begin
location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
@ -821,7 +820,7 @@ procedure TSparcAddNode.second_add64bit;
def_cgsize(left.resulttype.def),true);
if (left.location.loc = LOC_REGISTER) then
location.register64 := left.location.register64
else if (location.registerlow.enum = R_NO) then
else if (location.registerlow.number = NR_NO) then
begin
location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
@ -1009,30 +1008,21 @@ procedure TSparcAddNode.set_result_location(cmpOp,unsigned:Boolean);
ELSE
location_copy(location,left.location);
end;
function def_opsize(p1:tdef):topsize;
begin
case p1.size of
1:def_opsize:=S_B;
2:def_opsize:=S_W;
4:def_opsize:=S_L;
8:def_opsize:=S_L;
else
InternalError(130820001);
end;
end;
procedure TSparcAddNode.pass_2;
{is also being used for "xor", and "mul", "sub", or and comparative operators}
var
popeax,popedx,pushedfpu,mboverflow,cmpop:Boolean;
op:TAsmOp;
power:LongInt;
OpSize:TOpSize;
OpSize:TcgSize;
unsigned:Boolean;{true, if unsigned types are compared}
extra_not:Boolean;
cgop:TOpCg;
begin
{to make it more readable, string and set (not smallset!) have their own
procedures }
{ to make it more readable, string and set (not smallset!) have their own
procedures }
case left.resulttype.def.deftype of
orddef:
if is_boolean(left.resulttype.def)and is_boolean(right.resulttype.def)
@ -1070,7 +1060,7 @@ procedures }
cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
unsigned:=not(is_signed(left.resulttype.def))or
not(is_signed(right.resulttype.def));
opsize:=def_opsize(left.resulttype.def);
opsize:=def_cgsize(left.resulttype.def);
pass_left_and_right;
{ set result location }
if not cmpop
@ -1079,8 +1069,7 @@ procedures }
else
location_reset(location,LOC_FLAGS,OS_NO);
load_left_right(cmpop,(cs_check_overflow in aktlocalswitches)and(nodetype in [addn,subn,muln]));
if(location.register.enum = R_NO)and not(cmpop)
then
if (location.register.number = NR_NO) and not(cmpop) then
location.register := rg.getregisterint(exprasmlist,OS_INT);
if not(cs_check_overflow in aktlocalswitches)or cmpop or (nodetype in [orn,andn,xorn])
then
@ -1122,22 +1111,18 @@ procedures }
CGMessage(type_e_mismatch);
end;
{ Convert flags to register first }
if(left.location.loc=LOC_FLAGS)
then
location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false);
if (right.location.loc=LOC_FLAGS)
then
location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
if (left.location.loc=LOC_FLAGS) then
location_force_reg(exprasmlist,left.location,opsize,false);
if (right.location.loc=LOC_FLAGS) then
location_force_reg(exprasmlist,right.location,opsize,false);
left_must_be_reg(OpSize,false);
if not cmpOp
then
if not cmpOp then
emit_generic_code(op,opsize,unsigned,extra_not,mboverflow)
else
emit_compare(unsigned);
location_freetemp(exprasmlist,right.location);
location_release(exprasmlist,right.location);
if cmpop and(left.location.loc<>LOC_CREGISTER)
then
if cmpop and (left.location.loc<>LOC_CREGISTER) then
begin
location_freetemp(exprasmlist,left.location);
location_release(exprasmlist,left.location);
@ -1176,12 +1161,18 @@ procedure TSparcAddNode.pass_left_and_right;
left.location.register := tmpreg;
end;
end;
begin
cAddNode:=TSparcAddNode;
end.
{
$Log$
Revision 1.13 2003-05-07 15:05:37 mazen
Revision 1.14 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.13 2003/05/07 15:05:37 mazen
* fixed generated code for compare instructions
Revision 1.12 2003/05/06 21:37:58 mazen

View File

@ -150,7 +150,7 @@ implementation
rg.UnGetRegisterInt(exprasmlist,divider);
end;
{ free used registers }
if numerator.enum <> resultreg.enum then
if numerator.number <> resultreg.number then
rg.ungetregisterint(exprasmlist,numerator);
{ set result location }
location.loc:=LOC_REGISTER;
@ -479,7 +479,12 @@ begin
end.
{
$Log$
Revision 1.7 2003-03-15 22:51:58 mazen
Revision 1.8 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.7 2003/03/15 22:51:58 mazen
* remaking sparc rtl compile
Revision 1.6 2003/03/10 21:59:54 mazen

View File

@ -85,7 +85,7 @@ interface
OT_FPU0 = $01000800; { FPU stack register zero }
OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
{ a mask for the following }
OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX }
OT_REG_ACCUM = $00211000; { FUNCTION_RETURN_REG: AL, AX or EAX }
OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
OT_REG_AX = $00211002; { ditto }
OT_REG_EAX = $00211004; { and again }
@ -2024,7 +2024,12 @@ implementation
end.
{
$Log$
Revision 1.3 2003-05-22 21:33:31 peter
Revision 1.4 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.3 2003/05/22 21:33:31 peter
* removed some unit dependencies
Revision 1.2 2002/04/25 16:12:09 florian

View File

@ -309,9 +309,14 @@ unit cgx86;
class function tcgx86.reg_cgsize(const reg: tregister): tcgsize;
const
regsize_2_cgsize: array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
opsize_2_cgsize: array[topsize] of tcgsize = (OS_NO,
OS_8,OS_16,OS_32,OS_NO,OS_NO,OS_NO,
OS_32,OS_64,OS_64,
OS_F32,OS_F64,OS_F80,OS_F32,OS_F64,OS_NO,OS_NO,
OS_NO,OS_NO,OS_NO
);
begin
result := regsize_2_cgsize[reg2opsize(reg)];
result := opsize_2_cgsize[reg2opsize(reg)];
end;
@ -1941,7 +1946,12 @@ unit cgx86;
end.
{
$Log$
Revision 1.47 2003-05-22 21:33:31 peter
Revision 1.48 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.47 2003/05/22 21:33:31 peter
* removed some unit dependencies
Revision 1.46 2003/05/16 14:33:31 peter

View File

@ -487,9 +487,6 @@ uses
max_operands = 3;
lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
{# Constant defining possibly all registers which might require saving }
ALL_REGISTERS = [firstreg..lastreg];
ALL_INTREGISTERS = [1..255];
@ -715,7 +712,12 @@ implementation
end.
{
$Log$
Revision 1.4 2003-04-30 20:53:32 florian
Revision 1.5 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.4 2003/04/30 20:53:32 florian
* error when address of an abstract method is taken
* fixed some x86-64 problems
* merged some more x86-64 and i386 code
@ -798,10 +800,10 @@ end.
+ very basic support for float128 type (x86-64 only)
Revision 1.34 2002/11/17 18:26:16 mazen
* fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
* fixed a compilation bug accmulator-->FUNCTION_RETURN_REG, in definition of return_result_reg
Revision 1.33 2002/11/17 17:49:08 mazen
+ return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
+ return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
Revision 1.32 2002/10/05 12:43:29 carl
* fixes for Delphi 6 compilation

View File

@ -42,11 +42,15 @@ Procedure FWaitWarning;
type
T386Operand=class(TOperand)
opsize : topsize;
Procedure SetSize(_size:longint;force:boolean);override;
Procedure SetCorrectSize(opcode:tasmop);override;
end;
T386Instruction=class(TInstruction)
OpOrder : TOperandOrder;
opsize : topsize;
constructor Create;
{ Operand sizes }
procedure AddReferenceSizes;
procedure SetInstructionOpsize;
@ -85,7 +89,7 @@ implementation
uses
globtype,globals,systems,verbose,
cpuinfo,
itx86att;
itx86att,cgx86;
{$define ATTOP}
{$define INTELOP}
@ -196,20 +200,27 @@ end;
T386Operand
*****************************************************************************}
Procedure T386Operand.SetSize(_size:longint;force:boolean);
begin
inherited SetSize(_size,force);
opsize:=TCGSize2Opsize[size];
end;
Procedure T386Operand.SetCorrectSize(opcode:tasmop);
begin
if gas_needsuffix[opcode]=attsufFPU then
begin
case size of
S_L : size:=S_FS;
S_IQ : size:=S_FL;
case opsize of
S_L : opsize:=S_FS;
S_IQ : opsize:=S_FL;
end;
end
else if gas_needsuffix[opcode]=attsufFPUint then
begin
case size of
S_W : size:=S_IS;
S_L : size:=S_IL;
case opsize of
S_W : opsize:=S_IS;
S_L : opsize:=S_IL;
end;
end;
end;
@ -219,6 +230,13 @@ end;
T386Instruction
*****************************************************************************}
constructor T386Instruction.Create;
begin
inherited Create;
Opsize:=S_NO;
end;
procedure T386Instruction.SwapOperands;
begin
Inherited SwapOperands;
@ -242,7 +260,7 @@ begin
for i:=1to ops do
begin
operands[i].SetCorrectSize(opcode);
if (operands[i].size=S_NO) then
if t386operand(operands[i]).opsize=S_NO then
begin
case operands[i].Opr.Typ of
OPR_REFERENCE :
@ -265,19 +283,19 @@ begin
{ if no register then take the opsize (which is available with ATT),
if not availble then give an error }
if opsize<>S_NO then
operands[i].size:=opsize
t386operand(operands[i]).opsize:=opsize
else
begin
Message(asmr_e_unable_to_determine_reference_size);
{ recovery }
operands[i].size:=S_L;
t386operand(operands[i]).opsize:=S_L;
end;
end;
end
else
begin
if opsize<>S_NO then
operands[i].size:=opsize
t386operand(operands[i]).opsize:=opsize
end;
end;
OPR_SYMBOL :
@ -292,7 +310,7 @@ begin
operands[i].opr.ref.symbol:=s;
operands[i].opr.ref.offset:=so;
end;
operands[i].size:=S_L;
t386operand(operands[i]).opsize:=S_L;
end;
end;
end;
@ -319,20 +337,20 @@ begin
(operands[1].opr.reg.number<=nlastsreg))) then
opsize:=S_L
else
opsize:=operands[1].size;
opsize:=t386operand(operands[1]).opsize;
2 :
begin
case opcode of
A_MOVZX,A_MOVSX :
begin
case operands[1].size of
case t386operand(operands[1]).opsize of
S_W :
case operands[2].size of
case t386operand(operands[2]).opsize of
S_L :
opsize:=S_WL;
end;
S_B :
case operands[2].size of
case t386operand(operands[2]).opsize of
S_W :
opsize:=S_BW;
S_L :
@ -344,13 +362,13 @@ begin
32 bit register or memory, so no opsize is correct here PM }
exit;
A_OUT :
opsize:=operands[1].size;
opsize:=t386operand(operands[1]).opsize;
else
opsize:=operands[2].size;
opsize:=t386operand(operands[2]).opsize;
end;
end;
3 :
opsize:=operands[3].size;
opsize:=t386operand(operands[3]).opsize;
end;
end;
@ -391,11 +409,11 @@ begin
begin
case opsize of
S_BW :
sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_W);
sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_W);
S_BL :
sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_L);
sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_L);
S_WL :
sizeerr:=(operands[1].size<>S_W) or (operands[2].size<>S_L);
sizeerr:=(t386operand(operands[1]).opsize<>S_W) or (t386operand(operands[2]).opsize<>S_L);
end;
end;
end
@ -404,8 +422,8 @@ begin
for i:=1 to ops do
begin
if (operands[i].opr.typ<>OPR_CONSTANT) and
(operands[i].size in [S_B,S_W,S_L]) and
(operands[i].size<>opsize) then
(t386operand(operands[i]).opsize in [S_B,S_W,S_L]) and
(t386operand(operands[i]).opsize<>opsize) then
sizeerr:=true;
end;
end;
@ -483,19 +501,21 @@ begin
else
begin
if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
siz:=operands[1].size
siz:=t386operand(operands[1]).opsize
else
siz:=operands[Ops].size;
siz:=t386operand(operands[Ops]).opsize;
{ MOVD should be of size S_LQ or S_QL, but these do not exist PM }
if (ops=2) and (operands[1].size<>S_NO) and
(operands[2].size<>S_NO) and (operands[1].size<>operands[2].size) then
if (ops=2) and
(t386operand(operands[1]).opsize<>S_NO) and
(t386operand(operands[2]).opsize<>S_NO) and
(t386operand(operands[1]).opsize<>t386operand(operands[2]).opsize) then
siz:=S_NO;
end;
if ((opcode=A_MOVD)or
(opcode=A_CVTSI2SS)) and
((operands[1].size=S_NO) or
(operands[2].size=S_NO)) then
((t386operand(operands[1]).opsize=S_NO) or
(t386operand(operands[2]).opsize=S_NO)) then
siz:=S_NO;
{ NASM does not support FADD without args
as alias of FADDP
@ -636,10 +656,10 @@ begin
OPR_REFERENCE:
begin
ai.loadref(i-1,operands[i].opr.ref);
if operands[i].size<>S_NO then
if t386operand(operands[i]).opsize<>S_NO then
begin
asize:=0;
case operands[i].size of
case t386operand(operands[i]).opsize of
S_B :
asize:=OT_BITS8;
S_W, S_IS :
@ -684,7 +704,12 @@ end;
end.
{
$Log$
Revision 1.2 2003-05-22 21:33:31 peter
Revision 1.3 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.2 2003/05/22 21:33:31 peter
* removed some unit dependencies
Revision 1.1 2003/04/30 15:45:35 florian

View File

@ -163,29 +163,26 @@ const
*****************************************************************************}
{# Stack pointer register }
stack_pointer_reg = R_RSP;
NR_STACK_POINTER_REG = NR_RSP;
{# Frame pointer register }
frame_pointer_reg = R_RBP;
NR_FRAME_POINTER_REG = NR_RBP;
{ Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific. For
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
}
pic_offset_reg = R_EBX;
accumulator = R_RAX;
RS_ACCUMULATOR = RS_RAX;
NR_ACCUMULATOR = NR_RAX;
{ the return_result_reg, is used inside the called function to store its return
value when that is a scalar value otherwise a pointer to the address of the
result is placed inside it }
return_result_reg = accumulator;
RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
{ the function_result_reg contains the function result after a call to a scalar
function othewise it contains a pointer to the returned result}
function_result_reg = accumulator;
NR_PIC_OFFSET_REG = NR_EBX;
{ Results are returned in this register (32-bit values) }
NR_FUNCTION_RETURN_REG = NR_RAX;
RS_FUNCTION_RETURN_REG = RS_RAX;
{ High part of 64bit return value }
NR_FUNCTION_RETURNHIGH_REG = NR_NONE;
RS_FUNCTION_RETURNHIGH_REG = RS_NONE;
{ The value returned from a function is available in this register }
NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
{ The high part of 64bit value returned from a function is available in this register }
NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG;
RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG;
fpu_result_reg = R_ST;
mmresultreg = R_MM0;
@ -214,7 +211,12 @@ const
{
$Log$
Revision 1.3 2003-04-30 15:45:35 florian
Revision 1.4 2003-05-30 23:57:08 peter
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and
function_result_reg (caller)
Revision 1.3 2003/04/30 15:45:35 florian
* merged more x86-64/i386 code
Revision 1.2 2002/04/25 16:12:09 florian