mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 23:21:57 +02:00
* more sparc cleanup
* accumulator removed, splitted in function_return_reg (called) and function_result_reg (caller)
This commit is contained in:
parent
d992e13e08
commit
414bd5fa22
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user