mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 21:09:44 +02:00
* Several bugfixes for m68k target (register alloc., opcode emission)
+ VIS target + Generic add more complete (still not verified)
This commit is contained in:
parent
4841a83d44
commit
59d3edeec7
@ -49,6 +49,15 @@ unit compiler;
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$ifdef vis}
|
||||
{$ifndef CPUOK}
|
||||
{$DEFINE CPUOK}
|
||||
{$else}
|
||||
{$fatal cannot define two CPU switches}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
|
||||
{$ifdef powerpc}
|
||||
{$ifndef CPUOK}
|
||||
{$DEFINE CPUOK}
|
||||
@ -377,7 +386,12 @@ end;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.35 2002-09-05 19:28:31 peter
|
||||
Revision 1.36 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.35 2002/09/05 19:28:31 peter
|
||||
* removed repetitive pass counting
|
||||
* display heapsize also for extdebug
|
||||
|
||||
|
@ -519,6 +519,12 @@ uses
|
||||
mmregs = [R_MM0..R_MM7];
|
||||
usableregsmm = [R_MM0..R_MM7];
|
||||
c_countusableregsmm = 8;
|
||||
|
||||
maxaddrregs = 0;
|
||||
addrregs = [];
|
||||
usableregsaddr = [];
|
||||
c_countusableregsaddr = 0;
|
||||
|
||||
|
||||
firstsaveintreg = R_EAX;
|
||||
lastsaveintreg = R_EBX;
|
||||
@ -599,11 +605,11 @@ uses
|
||||
{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;
|
||||
return_result_reg = 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;
|
||||
function_result_reg = accumulator;
|
||||
{# Hi-Results are returned in this register (64-bit value high register) }
|
||||
accumulatorhigh = R_EDX;
|
||||
{ WARNING: don't change to R_ST0!! See comments above implementation of }
|
||||
@ -714,7 +720,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.40 2003-01-13 18:37:44 daniel
|
||||
Revision 1.41 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.40 2003/01/13 18:37:44 daniel
|
||||
* Work on register conversion
|
||||
|
||||
Revision 1.39 2003/01/09 20:41:00 daniel
|
||||
|
@ -69,6 +69,11 @@ unit cgcpu;
|
||||
procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
|
||||
procedure g_save_all_registers(list : taasmoutput);override;
|
||||
procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
|
||||
{ for address register allocation }
|
||||
function get_scratch_reg_address(list : taasmoutput) : tregister;override;
|
||||
function get_scratch_reg_int(list : taasmoutput) : tregister; override;
|
||||
|
||||
|
||||
protected
|
||||
function fixref(list: taasmoutput; var ref: treference): boolean;
|
||||
private
|
||||
@ -167,6 +172,59 @@ Implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
function tcg68k.get_scratch_reg_int(list : taasmoutput) : tregister;
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
i : longint;
|
||||
|
||||
begin
|
||||
if unusedscratchregisters=[] then
|
||||
internalerror(68996);
|
||||
|
||||
if R_D0 in unusedscratchregisters then
|
||||
begin
|
||||
r.enum := R_D0;
|
||||
end
|
||||
else if R_D1 in unusedscratchregisters then
|
||||
begin
|
||||
r.enum := R_D1;
|
||||
end
|
||||
else
|
||||
internalerror(10);
|
||||
|
||||
exclude(unusedscratchregisters,r.enum);
|
||||
a_reg_alloc(list,r);
|
||||
get_scratch_reg_int:=r;
|
||||
end;
|
||||
|
||||
|
||||
function tcg68k.get_scratch_reg_address(list : taasmoutput) : tregister;
|
||||
var
|
||||
r : tregister;
|
||||
i : longint;
|
||||
|
||||
begin
|
||||
if unusedscratchregisters=[] then
|
||||
internalerror(68996);
|
||||
|
||||
if R_A0 in unusedscratchregisters then
|
||||
begin
|
||||
r.enum := R_A0;
|
||||
end
|
||||
else if R_A1 in unusedscratchregisters then
|
||||
begin
|
||||
r.enum := R_A1;
|
||||
end
|
||||
else
|
||||
internalerror(10);
|
||||
|
||||
exclude(unusedscratchregisters,r.enum);
|
||||
a_reg_alloc(list,r);
|
||||
get_scratch_reg_address:=r;
|
||||
end;
|
||||
|
||||
|
||||
{****************************************************************************}
|
||||
{ TCG68K }
|
||||
{****************************************************************************}
|
||||
@ -242,7 +300,7 @@ Implementation
|
||||
begin
|
||||
if (rg.isaddressregister(register)) then
|
||||
begin
|
||||
list.concat(taicpu.op_const_reg(A_MOVE,S_L,a,register))
|
||||
list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
|
||||
end
|
||||
else
|
||||
if a = 0 then
|
||||
@ -250,9 +308,9 @@ Implementation
|
||||
else
|
||||
begin
|
||||
if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
|
||||
list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,a,register))
|
||||
list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,longint(a),register))
|
||||
else
|
||||
list.concat(taicpu.op_const_reg(A_MOVE,S_L,a,register))
|
||||
list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -318,6 +376,7 @@ Implementation
|
||||
{ extended is not supported, since it is not available on Coldfire }
|
||||
if opsize = S_FX then
|
||||
internalerror(20020729);
|
||||
href := ref;
|
||||
fixref(list,href);
|
||||
{ in emulation mode, only 32-bit single is supported }
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
@ -683,8 +742,12 @@ Implementation
|
||||
OP_NEG,
|
||||
OP_NOT :
|
||||
Begin
|
||||
{ if there are two operands, move the register,
|
||||
since the operation will only be done on the result
|
||||
register.
|
||||
}
|
||||
if reg1.enum <> R_NO then
|
||||
internalerror(200112291);
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,reg1,reg2);
|
||||
|
||||
if (rg.isaddressregister(reg2)) then
|
||||
begin
|
||||
@ -1124,14 +1187,10 @@ Implementation
|
||||
{ zero extend }
|
||||
OS_8:
|
||||
begin
|
||||
if (rg.isaddressregister(reg)) then
|
||||
internalerror(20020729);
|
||||
list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
|
||||
end;
|
||||
OS_16:
|
||||
begin
|
||||
if (rg.isaddressregister(reg)) then
|
||||
internalerror(20020729);
|
||||
list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
|
||||
end;
|
||||
end; { otherwise the size is already correct }
|
||||
@ -1276,7 +1335,12 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.15 2003-01-08 18:43:57 daniel
|
||||
Revision 1.16 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.15 2003/01/08 18:43:57 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.14 2003/01/05 13:36:53 florian
|
||||
|
@ -109,7 +109,8 @@ uses
|
||||
R_SPPUSH,R_SPPULL,
|
||||
{ misc. }
|
||||
R_CCR,R_FP0,R_FP1,R_FP2,R_FP3,R_FP4,R_FP5,R_FP6,
|
||||
R_FP7,R_FPCR,R_SR,R_SSP,R_DFC,R_SFC,R_VBR,R_FPSR);
|
||||
R_FP7,R_FPCR,R_SR,R_SSP,R_DFC,R_SFC,R_VBR,R_FPSR,
|
||||
R_INTREGISTER,R_FLOATREGISTER);
|
||||
|
||||
{# Set type definition for registers }
|
||||
tregisterset = set of Toldregister;
|
||||
@ -128,7 +129,22 @@ uses
|
||||
treg64 = tregister64;
|
||||
|
||||
|
||||
Const
|
||||
{New register coding:}
|
||||
|
||||
{Special registers:}
|
||||
const
|
||||
NR_NO = $0000; {Invalid register}
|
||||
|
||||
{Normal registers:}
|
||||
|
||||
{General purpose registers:}
|
||||
NR_D0 = $0100; NR_D1 = $0200; NR_D2 = $0300;
|
||||
NR_D3 = $0400; NR_D4 = $0500; NR_D5 = $0600;
|
||||
NR_D6 = $0700; NR_D7 = $0800; NR_A0 = $0900;
|
||||
NR_A1 = $0A00; NR_A2 = $0B00; NR_A3 = $0C00;
|
||||
NR_A4 = $0D00; NR_A5 = $0E00; NR_A6 = $0F00;
|
||||
NR_A7 = $1000;
|
||||
|
||||
{# First register in the tregister enumeration }
|
||||
firstreg = low(Toldregister);
|
||||
{# Last register in the tregister enumeration }
|
||||
@ -442,8 +458,8 @@ uses
|
||||
{# Registers which are defined as scratch integer and no need to save across
|
||||
routine calls or in assembler blocks.
|
||||
}
|
||||
max_scratch_regs = 2;
|
||||
scratch_regs: Array[1..max_scratch_regs] of Toldregister = (R_D0,R_D1);
|
||||
max_scratch_regs = 4;
|
||||
scratch_regs: Array[1..max_scratch_regs] of Toldregister = (R_D0,R_D1,R_A0,R_A1);
|
||||
|
||||
{*****************************************************************************
|
||||
Default generic sizes
|
||||
@ -600,14 +616,39 @@ implementation
|
||||
procedure convert_register_to_enum(var r:Tregister);
|
||||
|
||||
begin
|
||||
{$warning Convert_register_to_enum implementation is missing!}
|
||||
internalerror(200301082);
|
||||
if r.enum = R_INTREGISTER then
|
||||
case r.number of
|
||||
NR_NO: r.enum:= R_NO;
|
||||
NR_D0: r.enum:= R_D0;
|
||||
NR_D1: r.enum:= R_D1;
|
||||
NR_D2: r.enum:= R_D2;
|
||||
NR_D3: r.enum:= R_D3;
|
||||
NR_D4: r.enum:= R_D4;
|
||||
NR_D5: r.enum:= R_D5;
|
||||
NR_D6: r.enum:= R_D6;
|
||||
NR_D7: r.enum:= R_D7;
|
||||
NR_A0: r.enum:= R_A0;
|
||||
NR_A1: r.enum:= R_A1;
|
||||
NR_A2: r.enum:= R_A2;
|
||||
NR_A3: r.enum:= R_A3;
|
||||
NR_A4: r.enum:= R_A4;
|
||||
NR_A5: r.enum:= R_A5;
|
||||
NR_A6: r.enum:= R_A6;
|
||||
NR_A7: r.enum:= R_SP;
|
||||
else
|
||||
internalerror(200301082);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.16 2003-01-09 15:49:56 daniel
|
||||
Revision 1.17 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.16 2003/01/09 15:49:56 daniel
|
||||
* Added register conversion
|
||||
|
||||
Revision 1.15 2003/01/08 18:43:57 daniel
|
||||
|
@ -30,12 +30,12 @@ unit cpunode;
|
||||
|
||||
uses
|
||||
{ generic nodes }
|
||||
ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgmat,ncgadd
|
||||
ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgmat,ncgadd,
|
||||
{ to be able to only parts of the generic code,
|
||||
the processor specific nodes must be included
|
||||
after the generic one (FK)
|
||||
}
|
||||
// nm68kadd,
|
||||
ncpuadd,
|
||||
// nppccal,
|
||||
// nppccon,
|
||||
// nppcflw,
|
||||
@ -46,13 +46,19 @@ unit cpunode;
|
||||
{ this not really a node }
|
||||
// nppcobj,
|
||||
// nppcmat,
|
||||
,n68kcnv
|
||||
n68kmat,
|
||||
n68kcnv
|
||||
;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.3 2002-12-14 15:02:03 carl
|
||||
Revision 1.4 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.3 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
|
||||
|
@ -47,19 +47,51 @@ unit cpupara;
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose;
|
||||
verbose,
|
||||
globals,
|
||||
globtype,
|
||||
systems,
|
||||
cpuinfo,cginfo,cgbase,
|
||||
defutil;
|
||||
|
||||
function tm68kparamanager.getintparaloc(nr : longint) : tparalocation;
|
||||
begin
|
||||
fillchar(result,sizeof(tparalocation),0);
|
||||
if nr<1 then
|
||||
internalerror(2002070801)
|
||||
else
|
||||
begin
|
||||
{ warning : THIS ONLY WORKS WITH INTERNAL ROUTINES,
|
||||
WHICH MUST ALWAYS PASS 4-BYTE PARAMETERS!!
|
||||
}
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.reference.index.enum:=frame_pointer_reg;
|
||||
result.reference.offset:=target_info.first_parm_offset
|
||||
+nr*4;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tm68kparamanager.create_param_loc_info(p : tabstractprocdef);
|
||||
var
|
||||
param_offset : integer;
|
||||
hp : tparaitem;
|
||||
begin
|
||||
{ set default para_alignment to target_info.stackalignment }
|
||||
{ if para_alignment=0 then
|
||||
para_alignment:=aktalignment.paraalign;
|
||||
}
|
||||
{ frame pointer for nested procedures? }
|
||||
{ inc(nextintreg); }
|
||||
{ constructor? }
|
||||
{ destructor? }
|
||||
param_offset := target_info.first_parm_offset;
|
||||
hp:=tparaitem(p.para.last);
|
||||
while assigned(hp) do
|
||||
begin
|
||||
hp.paraloc.loc:=LOC_REFERENCE;
|
||||
hp.paraloc.sp_fixup:=0;
|
||||
hp.paraloc.reference.index.enum:=frame_pointer_reg;
|
||||
hp.paraloc.reference.offset:=param_offset;
|
||||
inc(param_offset,aktalignment.paraalign);
|
||||
hp.paraloc.size := def_cgsize(hp.paratype.def);
|
||||
hp:=tparaitem(hp.previous);
|
||||
end;
|
||||
end;
|
||||
|
||||
function tm68kparamanager.getselflocation(p : tabstractprocdef) : tparalocation;
|
||||
@ -75,7 +107,12 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.3 2003-01-08 18:43:57 daniel
|
||||
Revision 1.4 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.3 2003/01/08 18:43:57 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.2 2002/12/14 15:02:03 carl
|
||||
|
@ -37,7 +37,7 @@ implementation
|
||||
**************************************}
|
||||
|
||||
{$ifndef NOTARGETLINUX}
|
||||
,t_linux
|
||||
,t_linux,t_amiga
|
||||
{$endif}
|
||||
|
||||
{**************************************
|
||||
@ -50,7 +50,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2002-08-13 18:01:52 carl
|
||||
Revision 1.2 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.1 2002/08/13 18:01:52 carl
|
||||
* rename swatoperands to swapoperands
|
||||
+ m68k first compilable version (still needs a lot of testing):
|
||||
assembler generator, system information , inline
|
||||
|
@ -27,7 +27,7 @@ unit n68kmat;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nmat;
|
||||
node,nmat,ncgmat,cpubase,cginfo;
|
||||
|
||||
type
|
||||
|
||||
@ -36,16 +36,22 @@ interface
|
||||
procedure pass_2;override;
|
||||
end;
|
||||
|
||||
tm68kmoddivnode = class(tcgmoddivnode)
|
||||
procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);override;
|
||||
procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);override;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,systems,
|
||||
cutils,verbose,globals,
|
||||
symconst,symdef,aasmbase,aasmtai,aasmcpu,defbase,
|
||||
cginfo,cgbase,pass_1,pass_2,
|
||||
symconst,symdef,aasmbase,aasmtai,aasmcpu,
|
||||
cgbase,pass_1,pass_2,
|
||||
ncon,
|
||||
cpubase,cpuinfo,paramgr,
|
||||
cpuinfo,paramgr,defutil,
|
||||
tgobj,ncgutil,cgobj,rgobj,rgcpu,cgcpu,cg64f32;
|
||||
|
||||
|
||||
@ -114,21 +120,134 @@ implementation
|
||||
end
|
||||
else
|
||||
begin
|
||||
secondpass(left);
|
||||
location_copy(location,left.location);
|
||||
location_force_reg(exprasmlist,location,opsize,false);
|
||||
cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,location.register,location.register);
|
||||
secondpass(left);
|
||||
location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
|
||||
location_copy(location,left.location);
|
||||
if location.loc=LOC_CREGISTER then
|
||||
location.register := rg.getregisterint(exprasmlist);
|
||||
{ perform the NOT operation }
|
||||
cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,location.register,left.location.register);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TM68KMODDIVNODE
|
||||
*****************************************************************************}
|
||||
procedure tm68kmoddivnode.emit_div_reg_reg(signed: boolean;denum,num : tregister);
|
||||
var
|
||||
continuelabel : tasmlabel;
|
||||
reg_d0,reg_d1 : tregister;
|
||||
begin
|
||||
{ no RTL call, so inline a zero denominator verification }
|
||||
if aktoptprocessor <> MC68000 then
|
||||
begin
|
||||
{ verify if denominator is zero }
|
||||
objectlibrary.getlabel(continuelabel);
|
||||
{ compare against zero, if not zero continue }
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
|
||||
cg.a_param_const(exprasmlist, OS_S32,200,paramanager.getintparaloc(1));
|
||||
cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
|
||||
cg.a_label(exprasmlist, continuelabel);
|
||||
if signed then
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_DIVS,S_L,denum,num))
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_DIVU,S_L,denum,num));
|
||||
{ result should be in denuminator }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,denum);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ On MC68000/68010 mw must pass through RTL routines }
|
||||
reg_d0:=rg.getexplicitregisterint(exprasmlist,R_D0);
|
||||
reg_d1:=rg.getexplicitregisterint(exprasmlist,R_D1);
|
||||
{ put numerator in d0 }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,reg_d0);
|
||||
{ put denum in D1 }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,reg_d1);
|
||||
if signed then
|
||||
cg.a_call_name(exprasmlist,'FPC_DIV_LONGINT')
|
||||
else
|
||||
cg.a_call_name(exprasmlist,'FPC_DIV_CARDINAL');
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,reg_d0,denum);
|
||||
rg.ungetregisterint(exprasmlist,reg_d0);
|
||||
rg.ungetregisterint(exprasmlist,reg_d1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tm68kmoddivnode.emit_mod_reg_reg(signed: boolean;denum,num : tregister);
|
||||
var tmpreg : tregister;
|
||||
continuelabel : tasmlabel;
|
||||
signlabel : tasmlabel;
|
||||
reg_d0,reg_d1 : tregister;
|
||||
begin
|
||||
{ no RTL call, so inline a zero denominator verification }
|
||||
if aktoptprocessor <> MC68000 then
|
||||
begin
|
||||
{ verify if denominator is zero }
|
||||
objectlibrary.getlabel(continuelabel);
|
||||
{ compare against zero, if not zero continue }
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
|
||||
cg.a_param_const(exprasmlist, OS_S32,200,paramanager.getintparaloc(1));
|
||||
cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
|
||||
cg.a_label(exprasmlist, continuelabel);
|
||||
|
||||
tmpreg := cg.get_scratch_reg_int(exprasmlist);
|
||||
|
||||
{ we have to prepare the high register with the }
|
||||
{ correct sign. i.e we clear it, check if the low dword reg }
|
||||
{ which will participate in the division is signed, if so we}
|
||||
{ we extend the sign to the high doword register by inverting }
|
||||
{ all the bits. }
|
||||
exprasmlist.concat(taicpu.op_reg(A_CLR,S_L,tmpreg));
|
||||
objectlibrary.getlabel(signlabel);
|
||||
exprasmlist.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_A,0,tmpreg,signlabel);
|
||||
{ its a negative value, therefore change sign }
|
||||
cg.a_label(exprasmlist,signlabel);
|
||||
{ tmpreg:num / denum }
|
||||
|
||||
if signed then
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVSL,S_L,denum,tmpreg,num))
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVUL,S_L,denum,tmpreg,num));
|
||||
{ remainder in tmpreg }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,tmpreg,denum);
|
||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ On MC68000/68010 mw must pass through RTL routines }
|
||||
Reg_d0:=rg.getexplicitregisterint(exprasmlist,R_D0);
|
||||
Reg_d1:=rg.getexplicitregisterint(exprasmlist,R_D1);
|
||||
{ put numerator in d0 }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,Reg_D0);
|
||||
{ put denum in D1 }
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,Reg_D1);
|
||||
if signed then
|
||||
cg.a_call_name(exprasmlist,'FPC_MOD_LONGINT')
|
||||
else
|
||||
cg.a_call_name(exprasmlist,'FPC_MOD_CARDINAL');
|
||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,Reg_D0,denum);
|
||||
rg.ungetregisterint(exprasmlist,Reg_D0);
|
||||
rg.ungetregisterint(exprasmlist,Reg_D1);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
cnotnode:=tm68knotnode;
|
||||
cmoddivnode:=tm68kmoddivnode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.4 2002-09-07 15:25:13 peter
|
||||
Revision 1.5 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.4 2002/09/07 15:25:13 peter
|
||||
* old logs removed and tabs fixed
|
||||
|
||||
Revision 1.3 2002/08/15 15:15:55 carl
|
||||
|
440
compiler/m68k/ncpuadd.pas
Normal file
440
compiler/m68k/ncpuadd.pas
Normal file
@ -0,0 +1,440 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
|
||||
|
||||
Code generation for add nodes on the Motorola 680x0 family
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 ncpuadd;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nadd,ncgadd,cpubase,cginfo;
|
||||
|
||||
|
||||
type
|
||||
t68kaddnode = class(tcgaddnode)
|
||||
procedure second_cmpordinal;override;
|
||||
procedure second_cmpsmallset;override;
|
||||
procedure second_cmp64bit;override;
|
||||
procedure second_cmpboolean;override;
|
||||
private
|
||||
function getresflags(unsigned: boolean) : tresflags;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,systems,
|
||||
cutils,verbose,globals,
|
||||
symconst,symdef,paramgr,
|
||||
aasmbase,aasmtai,aasmcpu,defutil,htypechk,
|
||||
cgbase,cpuinfo,pass_1,pass_2,regvars,
|
||||
cpupara,
|
||||
ncon,nset,
|
||||
ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
|
||||
|
||||
{*****************************************************************************
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
function t68kaddnode.getresflags(unsigned : boolean) : tresflags;
|
||||
begin
|
||||
case nodetype of
|
||||
equaln : getresflags:=F_E;
|
||||
unequaln : getresflags:=F_NE;
|
||||
else
|
||||
if not(unsigned) then
|
||||
begin
|
||||
if nf_swaped in flags then
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_G;
|
||||
lten : getresflags:=F_GE;
|
||||
gtn : getresflags:=F_L;
|
||||
gten : getresflags:=F_LE;
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_L;
|
||||
lten : getresflags:=F_LE;
|
||||
gtn : getresflags:=F_G;
|
||||
gten : getresflags:=F_GE;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if nf_swaped in flags then
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_A;
|
||||
lten : getresflags:=F_AE;
|
||||
gtn : getresflags:=F_B;
|
||||
gten : getresflags:=F_BE;
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_B;
|
||||
lten : getresflags:=F_BE;
|
||||
gtn : getresflags:=F_A;
|
||||
gten : getresflags:=F_AE;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Smallsets
|
||||
*****************************************************************************}
|
||||
|
||||
procedure t68kaddnode.second_cmpsmallset;
|
||||
var
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
|
||||
case nodetype of
|
||||
equaln,
|
||||
unequaln :
|
||||
begin
|
||||
{emit_compare(true);}
|
||||
end;
|
||||
lten,gten:
|
||||
begin
|
||||
If (not(nf_swaped in flags) and
|
||||
(nodetype = lten)) or
|
||||
((nf_swaped in flags) and
|
||||
(nodetype = gten)) then
|
||||
swapleftright;
|
||||
// now we have to check whether left >= right
|
||||
tmpreg := cg.get_scratch_reg_int(exprasmlist);
|
||||
if left.location.loc = LOC_CONSTANT then
|
||||
begin
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
|
||||
not(left.location.value),right.location.register,tmpreg);
|
||||
exprasmlist.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
|
||||
// the two instructions above should be folded together by
|
||||
// the peepholeoptimizer
|
||||
end
|
||||
else
|
||||
begin
|
||||
if right.location.loc = LOC_CONSTANT then
|
||||
begin
|
||||
cg.a_load_const_reg(exprasmlist,OS_INT,
|
||||
aword(right.location.value),tmpreg);
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_AND,S_L,
|
||||
tmpreg,left.location.register));
|
||||
end
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_AND,S_L,
|
||||
right.location.register,left.location.register));
|
||||
end;
|
||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||
location.resflags := getresflags(true);
|
||||
end;
|
||||
else
|
||||
internalerror(2002072701);
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Ordinals
|
||||
*****************************************************************************}
|
||||
|
||||
procedure t68kaddnode.second_cmpordinal;
|
||||
var
|
||||
unsigned : boolean;
|
||||
useconst : boolean;
|
||||
tmpreg : tregister;
|
||||
op : tasmop;
|
||||
begin
|
||||
{ set result location }
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
|
||||
{ load values into registers (except constants) }
|
||||
load_left_right(true, false);
|
||||
|
||||
{ determine if the comparison will be unsigned }
|
||||
unsigned:=not(is_signed(left.resulttype.def)) or
|
||||
not(is_signed(right.resulttype.def));
|
||||
|
||||
// get the constant on the right if there is one
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
// can we use an immediate, or do we have to load the
|
||||
// constant in a register first?
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
begin
|
||||
{$ifdef extdebug}
|
||||
if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>-1) or unsigned) then
|
||||
internalerror(2002080301);
|
||||
{$endif extdebug}
|
||||
if (nodetype in [equaln,unequaln]) then
|
||||
if (unsigned and
|
||||
(right.location.value > high(word))) or
|
||||
(not unsigned and
|
||||
(longint(right.location.value) < low(smallint)) or
|
||||
(longint(right.location.value) > high(smallint))) then
|
||||
{ we can then maybe use a constant in the 'othersigned' case
|
||||
(the sign doesn't matter for // equal/unequal)}
|
||||
unsigned := not unsigned;
|
||||
|
||||
if (unsigned and
|
||||
((right.location.value) <= high(word))) or
|
||||
(not(unsigned) and
|
||||
(longint(right.location.value) >= low(smallint)) and
|
||||
(longint(right.location.value) <= high(smallint))) then
|
||||
useconst := true
|
||||
else
|
||||
begin
|
||||
useconst := false;
|
||||
tmpreg := cg.get_scratch_reg_int(exprasmlist);
|
||||
cg.a_load_const_reg(exprasmlist,OS_INT,
|
||||
aword(right.location.value),tmpreg);
|
||||
end
|
||||
end
|
||||
else
|
||||
useconst := false;
|
||||
location.loc := LOC_FLAGS;
|
||||
location.resflags := getresflags(unsigned);
|
||||
op := A_CMP;
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
if useconst then
|
||||
exprasmlist.concat(taicpu.op_reg_const(op,S_L,
|
||||
left.location.register,longint(right.location.value)))
|
||||
else
|
||||
begin
|
||||
exprasmlist.concat(taicpu.op_reg_reg(op,S_L,
|
||||
left.location.register,tmpreg));
|
||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||
end
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_reg(op,S_L,
|
||||
left.location.register,right.location.register));
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Boolean
|
||||
*****************************************************************************}
|
||||
|
||||
procedure t68kaddnode.second_cmpboolean;
|
||||
var
|
||||
cgop : TOpCg;
|
||||
cgsize : TCgSize;
|
||||
isjump : boolean;
|
||||
otl,ofl : tasmlabel;
|
||||
pushedregs : tmaybesave;
|
||||
begin
|
||||
if (torddef(left.resulttype.def).typ=bool8bit) or
|
||||
(torddef(right.resulttype.def).typ=bool8bit) then
|
||||
cgsize:=OS_8
|
||||
else
|
||||
if (torddef(left.resulttype.def).typ=bool16bit) or
|
||||
(torddef(right.resulttype.def).typ=bool16bit) then
|
||||
cgsize:=OS_16
|
||||
else
|
||||
cgsize:=OS_32;
|
||||
|
||||
if (cs_full_boolean_eval in aktlocalswitches) or
|
||||
(nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
|
||||
begin
|
||||
if left.nodetype in [ordconstn,realconstn] then
|
||||
swapleftright;
|
||||
|
||||
isjump:=(left.location.loc=LOC_JUMP);
|
||||
if isjump then
|
||||
begin
|
||||
otl:=truelabel;
|
||||
objectlibrary.getlabel(truelabel);
|
||||
ofl:=falselabel;
|
||||
objectlibrary.getlabel(falselabel);
|
||||
end;
|
||||
secondpass(left);
|
||||
if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
||||
location_force_reg(exprasmlist,left.location,cgsize,false);
|
||||
if isjump then
|
||||
begin
|
||||
truelabel:=otl;
|
||||
falselabel:=ofl;
|
||||
end;
|
||||
|
||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||
isjump:=(right.location.loc=LOC_JUMP);
|
||||
if isjump then
|
||||
begin
|
||||
otl:=truelabel;
|
||||
objectlibrary.getlabel(truelabel);
|
||||
ofl:=falselabel;
|
||||
objectlibrary.getlabel(falselabel);
|
||||
end;
|
||||
secondpass(right);
|
||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||
if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
||||
location_force_reg(exprasmlist,right.location,cgsize,false);
|
||||
if isjump then
|
||||
begin
|
||||
truelabel:=otl;
|
||||
falselabel:=ofl;
|
||||
end;
|
||||
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
|
||||
load_left_right(true,false);
|
||||
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
|
||||
if (right.location.loc <> LOC_CONSTANT) then
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,
|
||||
left.location.register,right.location.register))
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,
|
||||
longint(right.location.value),left.location.register));
|
||||
location.resflags := getresflags(true);
|
||||
|
||||
end;
|
||||
|
||||
clear_left_right(true);
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
64-bit
|
||||
*****************************************************************************}
|
||||
|
||||
procedure t68kaddnode.second_cmp64bit;
|
||||
begin
|
||||
(* load_left_right(true,false);
|
||||
|
||||
case nodetype of
|
||||
ltn,lten,
|
||||
gtn,gten:
|
||||
begin
|
||||
emit_cmp64_hi;
|
||||
firstjmp64bitcmp;
|
||||
emit_cmp64_lo;
|
||||
secondjmp64bitcmp;
|
||||
end;
|
||||
equaln,unequaln:
|
||||
begin
|
||||
// instead of doing a complicated compare, do
|
||||
// (left.hi xor right.hi) or (left.lo xor right.lo)
|
||||
// (somewhate optimized so that no superfluous 'mr's are
|
||||
// generated)
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
begin
|
||||
if left.location.loc = LOC_REGISTER then
|
||||
begin
|
||||
tempreg64.reglo := left.location.registerlow;
|
||||
tempreg64.reghi := left.location.registerhigh;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (aword(right.location.valueqword) <> 0) then
|
||||
tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist)
|
||||
else
|
||||
tempreg64.reglo := left.location.registerlow;
|
||||
if ((right.location.valueqword shr 32) <> 0) then
|
||||
tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist)
|
||||
else
|
||||
tempreg64.reghi := left.location.registerhigh;
|
||||
end;
|
||||
|
||||
if (aword(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
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword),
|
||||
left.location.registerlow,tempreg64.reglo)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
|
||||
aword(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
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.registerhigh,tempreg64.reghi)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.registerhigh,tempreg64.reghi);
|
||||
end
|
||||
else
|
||||
begin
|
||||
tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist);
|
||||
tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist);
|
||||
cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
|
||||
left.location.register64,right.location.register64,
|
||||
tempreg64);
|
||||
end;
|
||||
|
||||
cg.a_reg_alloc(exprasmlist,R_0);
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
|
||||
tempreg64.reglo,tempreg64.reghi));
|
||||
cg.a_reg_dealloc(exprasmlist,R_0);
|
||||
if (tempreg64.reglo <> left.location.registerlow) then
|
||||
cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
|
||||
if (tempreg64.reghi <> left.location.registerhigh) then
|
||||
cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
|
||||
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags := getresflags;
|
||||
end;
|
||||
else
|
||||
internalerror(2002072803);
|
||||
end;
|
||||
|
||||
|
||||
{ set result location }
|
||||
{ (emit_compare sets it to LOC_FLAGS for compares, so set the }
|
||||
{ real location only now) (JM) }
|
||||
if cmpop and
|
||||
not(nodetype in [equaln,unequaln]) then
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
*)
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
caddnode:=t68kaddnode;
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
}
|
@ -38,6 +38,10 @@ unit rgcpu;
|
||||
unusedregsaddr,usableregsaddr : tregisterset;
|
||||
countunusedregsaddr,
|
||||
countusableregsaddr : byte;
|
||||
procedure saveStateForInline(var state: pointer);override;
|
||||
procedure restoreStateAfterInline(var state: pointer);override;
|
||||
procedure saveUnusedState(var state: pointer);override;
|
||||
procedure restoreUnusedState(var state: pointer);override;
|
||||
function isaddressregister(reg: tregister): boolean; override;
|
||||
function getaddressregister(list: taasmoutput): tregister; override;
|
||||
procedure ungetaddressregister(list: taasmoutput; r: tregister); override;
|
||||
@ -46,6 +50,7 @@ unit rgcpu;
|
||||
const saved : tpushedsaved);override;
|
||||
procedure saveusedregisters(list: taasmoutput;
|
||||
var saved : tpushedsaved; const s: tregisterset);override;
|
||||
procedure cleartempgen;override;
|
||||
|
||||
end;
|
||||
|
||||
@ -107,8 +112,8 @@ unit rgcpu;
|
||||
may not be real (JM) }
|
||||
else
|
||||
begin
|
||||
dec(countunusedregsint);
|
||||
exclude(unusedregsint,r.enum);
|
||||
dec(countunusedregsaddr);
|
||||
exclude(unusedregsaddr,r.enum);
|
||||
end;
|
||||
tg.ungettemp(list,hr);
|
||||
end;
|
||||
@ -138,21 +143,69 @@ unit rgcpu;
|
||||
saved[r.enum].ofs:=hr.offset;
|
||||
cg.a_load_reg_ref(list,OS_ADDR,r,hr);
|
||||
cg.a_reg_dealloc(list,r);
|
||||
include(unusedregsint,r.enum);
|
||||
inc(countunusedregsint);
|
||||
include(unusedregsaddr,r.enum);
|
||||
inc(countunusedregsaddr);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure trgcpu.saveStateForInline(var state: pointer);
|
||||
begin
|
||||
inherited savestateforinline(state);
|
||||
psavedstate(state)^.unusedregsaddr := unusedregsaddr;
|
||||
psavedstate(state)^.usableregsaddr := usableregsaddr;
|
||||
psavedstate(state)^.countunusedregsaddr := countunusedregsaddr;
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.restoreStateAfterInline(var state: pointer);
|
||||
begin
|
||||
unusedregsaddr := psavedstate(state)^.unusedregsaddr;
|
||||
usableregsaddr := psavedstate(state)^.usableregsaddr;
|
||||
countunusedregsaddr := psavedstate(state)^.countunusedregsaddr;
|
||||
inherited restoreStateAfterInline(state);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.saveUnusedState(var state: pointer);
|
||||
begin
|
||||
inherited saveUnusedState(state);
|
||||
punusedstate(state)^.unusedregsaddr := unusedregsaddr;
|
||||
punusedstate(state)^.countunusedregsaddr := countunusedregsaddr;
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.restoreUnusedState(var state: pointer);
|
||||
begin
|
||||
unusedregsaddr := punusedstate(state)^.unusedregsaddr;
|
||||
countunusedregsaddr := punusedstate(state)^.countunusedregsaddr;
|
||||
inherited restoreUnusedState(state);
|
||||
end;
|
||||
|
||||
procedure trgcpu.cleartempgen;
|
||||
|
||||
begin
|
||||
inherited cleartempgen;
|
||||
countunusedregsaddr:=countusableregsaddr;
|
||||
unusedregsaddr:=usableregsaddr;
|
||||
end;
|
||||
|
||||
|
||||
initialization
|
||||
rg := trgcpu.create;
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.5 2003-01-08 18:43:57 daniel
|
||||
Revision 1.6 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.5 2003/01/08 18:43:57 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.4 2002/09/07 15:25:14 peter
|
||||
|
@ -33,7 +33,7 @@ interface
|
||||
tcgaddnode = class(taddnode)
|
||||
{ function pass_1: tnode; override;}
|
||||
procedure pass_2;override;
|
||||
private
|
||||
protected
|
||||
procedure pass_left_and_right;
|
||||
{ load left and right nodes into registers }
|
||||
procedure load_left_right(cmpop, load_constants: boolean);
|
||||
@ -51,12 +51,10 @@ interface
|
||||
procedure second_add64bit;virtual;
|
||||
procedure second_addordinal;virtual;
|
||||
{ procedure second_cmpfloat;virtual;}
|
||||
procedure second_cmpboolean;virtual;
|
||||
procedure second_cmpsmallset;virtual;
|
||||
procedure second_cmp64bit;virtual;
|
||||
procedure second_cmpordinal;virtual;
|
||||
|
||||
|
||||
procedure second_cmpboolean;virtual;abstract;
|
||||
procedure second_cmpsmallset;virtual;abstract;
|
||||
procedure second_cmp64bit;virtual;abstract;
|
||||
procedure second_cmpordinal;virtual;abstract;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -75,50 +73,6 @@ interface
|
||||
{*****************************************************************************
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
(*
|
||||
function tcgaddnode.getresflags(unsigned : boolean) : tresflags;
|
||||
begin
|
||||
case nodetype of
|
||||
equaln : getresflags:=F_E;
|
||||
unequaln : getresflags:=F_NE;
|
||||
else
|
||||
if not(unsigned) then
|
||||
begin
|
||||
if nf_swaped in flags then
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_G;
|
||||
lten : getresflags:=F_GE;
|
||||
gtn : getresflags:=F_L;
|
||||
gten : getresflags:=F_LE;
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_L;
|
||||
lten : getresflags:=F_LE;
|
||||
gtn : getresflags:=F_G;
|
||||
gten : getresflags:=F_GE;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if nf_swaped in flags then
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_A;
|
||||
lten : getresflags:=F_AE;
|
||||
gtn : getresflags:=F_B;
|
||||
gten : getresflags:=F_BE;
|
||||
end
|
||||
else
|
||||
case nodetype of
|
||||
ltn : getresflags:=F_B;
|
||||
lten : getresflags:=F_BE;
|
||||
gtn : getresflags:=F_A;
|
||||
gten : getresflags:=F_AE;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
procedure tcgaddnode.pass_left_and_right;
|
||||
var
|
||||
@ -249,58 +203,6 @@ interface
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgaddnode.second_cmpsmallset;
|
||||
begin
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
|
||||
case nodetype of
|
||||
equaln,
|
||||
unequaln :
|
||||
begin
|
||||
{emit_compare(true);}
|
||||
end;
|
||||
lten,gten:
|
||||
begin
|
||||
(*
|
||||
If (not(nf_swaped in flags) and
|
||||
(nodetype = lten)) or
|
||||
((nf_swaped in flags) and
|
||||
(nodetype = gten)) then
|
||||
swapleftright;
|
||||
// now we have to check whether left >= right
|
||||
tmpreg := cg.get_scratch_reg_int(exprasmlist);
|
||||
if left.location.loc = LOC_CONSTANT then
|
||||
begin
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
|
||||
not(left.location.value),right.location.register,tmpreg);
|
||||
exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
|
||||
// the two instructions above should be folded together by
|
||||
// the peepholeoptimizer
|
||||
end
|
||||
else
|
||||
begin
|
||||
if right.location.loc = LOC_CONSTANT then
|
||||
begin
|
||||
cg.a_load_const_reg(exprasmlist,OS_INT,
|
||||
aword(right.location.value),tmpreg);
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
|
||||
tmpreg,left.location.register));
|
||||
end
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
|
||||
right.location.register,left.location.register));
|
||||
end;
|
||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||
location.resflags.cr := R_CR0;
|
||||
location.resflags.flag := F_EQ;
|
||||
opdone := true;*)
|
||||
end;
|
||||
else
|
||||
internalerror(2002072701);
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgaddnode.second_addsmallset;
|
||||
@ -425,6 +327,8 @@ interface
|
||||
{ calculate the operator which is more difficult }
|
||||
firstcomplex(self);
|
||||
|
||||
cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
|
||||
|
||||
if cmpop then
|
||||
second_cmpboolean
|
||||
else
|
||||
@ -433,21 +337,15 @@ interface
|
||||
|
||||
end;
|
||||
|
||||
procedure tcgaddnode.second_cmpboolean;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure tcgaddnode.second_addboolean;
|
||||
var
|
||||
cgop : TOpCg;
|
||||
cgsize : TCgSize;
|
||||
cmpop,
|
||||
isjump : boolean;
|
||||
otl,ofl : tasmlabel;
|
||||
pushedregs : tmaybesave;
|
||||
begin
|
||||
|
||||
cmpop:=false;
|
||||
if (torddef(left.resulttype.def).typ=bool8bit) or
|
||||
(torddef(right.resulttype.def).typ=bool8bit) then
|
||||
cgsize:=OS_8
|
||||
@ -457,7 +355,7 @@ interface
|
||||
cgsize:=OS_16
|
||||
else
|
||||
cgsize:=OS_32;
|
||||
(*
|
||||
|
||||
if (cs_full_boolean_eval in aktlocalswitches) or
|
||||
(nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
|
||||
begin
|
||||
@ -500,60 +398,37 @@ interface
|
||||
falselabel:=ofl;
|
||||
end;
|
||||
|
||||
cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
|
||||
|
||||
{ set result location }
|
||||
if not cmpop then
|
||||
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
|
||||
else
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
|
||||
|
||||
load_left_right(cmpop,false);
|
||||
load_left_right(false,false);
|
||||
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
|
||||
{ compare the }
|
||||
case nodetype of
|
||||
ltn,lten,gtn,gten,
|
||||
equaln,unequaln :
|
||||
begin
|
||||
if (right.location.loc <> LOC_CONSTANT) then
|
||||
exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
|
||||
left.location.register,right.location.register))
|
||||
else
|
||||
exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
|
||||
left.location.register,longint(right.location.value)));
|
||||
location.resflags := getresflags;
|
||||
end;
|
||||
xorn :
|
||||
cgop:=OP_XOR;
|
||||
orn :
|
||||
cgop:=OP_OR;
|
||||
andn :
|
||||
cgop:=OP_AND;
|
||||
else
|
||||
begin
|
||||
case nodetype of
|
||||
xorn :
|
||||
cgop:=OP_XOR;
|
||||
orn :
|
||||
cgop:=OP_OR;
|
||||
andn :
|
||||
cgop:=OP_AND;
|
||||
else
|
||||
internalerror(200203247);
|
||||
end;
|
||||
internalerror(200203247);
|
||||
end;
|
||||
|
||||
if right.location.loc <> LOC_CONSTANT then
|
||||
cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
|
||||
left.location.register,right.location.register,
|
||||
location.register)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
|
||||
aword(right.location.value),left.location.register,
|
||||
location.register);
|
||||
end;
|
||||
end;
|
||||
if right.location.loc <> LOC_CONSTANT then
|
||||
cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
|
||||
left.location.register,right.location.register,
|
||||
location.register)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
|
||||
aword(right.location.value),left.location.register,
|
||||
location.register);
|
||||
end
|
||||
else
|
||||
begin
|
||||
// just to make sure we free the right registers
|
||||
cmpop := true;
|
||||
case nodetype of
|
||||
andn,
|
||||
orn :
|
||||
@ -585,9 +460,9 @@ interface
|
||||
maketojumpbool(exprasmlist,right,lr_load_regvars);
|
||||
end;
|
||||
end;
|
||||
end;*)
|
||||
end;
|
||||
{ free used register (except the result register) }
|
||||
clear_left_right(cmpop);
|
||||
clear_left_right(true);
|
||||
end;
|
||||
|
||||
|
||||
@ -616,104 +491,6 @@ interface
|
||||
clear_left_right(cmpop);
|
||||
end;
|
||||
|
||||
procedure tcgaddnode.second_cmp64bit;
|
||||
begin
|
||||
(* load_left_right(true,false);
|
||||
|
||||
case nodetype of
|
||||
ltn,lten,
|
||||
gtn,gten:
|
||||
begin
|
||||
emit_cmp64_hi;
|
||||
firstjmp64bitcmp;
|
||||
emit_cmp64_lo;
|
||||
secondjmp64bitcmp;
|
||||
end;
|
||||
equaln,unequaln:
|
||||
begin
|
||||
// instead of doing a complicated compare, do
|
||||
// (left.hi xor right.hi) or (left.lo xor right.lo)
|
||||
// (somewhate optimized so that no superfluous 'mr's are
|
||||
// generated)
|
||||
if (left.location.loc = LOC_CONSTANT) then
|
||||
swapleftright;
|
||||
if (right.location.loc = LOC_CONSTANT) then
|
||||
begin
|
||||
if left.location.loc = LOC_REGISTER then
|
||||
begin
|
||||
tempreg64.reglo := left.location.registerlow;
|
||||
tempreg64.reghi := left.location.registerhigh;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (aword(right.location.valueqword) <> 0) then
|
||||
tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist)
|
||||
else
|
||||
tempreg64.reglo := left.location.registerlow;
|
||||
if ((right.location.valueqword shr 32) <> 0) then
|
||||
tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist)
|
||||
else
|
||||
tempreg64.reghi := left.location.registerhigh;
|
||||
end;
|
||||
|
||||
if (aword(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
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword),
|
||||
left.location.registerlow,tempreg64.reglo)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
|
||||
aword(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
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.registerhigh,tempreg64.reghi)
|
||||
else
|
||||
cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
|
||||
aword(right.location.valueqword shr 32),
|
||||
left.location.registerhigh,tempreg64.reghi);
|
||||
end
|
||||
else
|
||||
begin
|
||||
tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist);
|
||||
tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist);
|
||||
cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
|
||||
left.location.register64,right.location.register64,
|
||||
tempreg64);
|
||||
end;
|
||||
|
||||
cg.a_reg_alloc(exprasmlist,R_0);
|
||||
exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
|
||||
tempreg64.reglo,tempreg64.reghi));
|
||||
cg.a_reg_dealloc(exprasmlist,R_0);
|
||||
if (tempreg64.reglo <> left.location.registerlow) then
|
||||
cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
|
||||
if (tempreg64.reghi <> left.location.registerhigh) then
|
||||
cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
|
||||
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags := getresflags;
|
||||
end;
|
||||
else
|
||||
internalerror(2002072803);
|
||||
end;
|
||||
|
||||
|
||||
{ set result location }
|
||||
{ (emit_compare sets it to LOC_FLAGS for compares, so set the }
|
||||
{ real location only now) (JM) }
|
||||
if cmpop and
|
||||
not(nodetype in [equaln,unequaln]) then
|
||||
location_reset(location,LOC_JUMP,OS_NO);
|
||||
*)
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgaddnode.second_add64bit;
|
||||
@ -841,22 +618,6 @@ interface
|
||||
{*****************************************************************************
|
||||
Ordinals
|
||||
*****************************************************************************}
|
||||
procedure tcgaddnode.second_cmpordinal;
|
||||
var
|
||||
unsigned : boolean;
|
||||
begin
|
||||
{ set result location }
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
|
||||
{ load values into registers (except constants) }
|
||||
load_left_right(true, false);
|
||||
|
||||
{ determine if the comparison will be unsigned }
|
||||
unsigned:=not(is_signed(left.resulttype.def)) or
|
||||
not(is_signed(right.resulttype.def));
|
||||
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgaddnode.second_addordinal;
|
||||
var
|
||||
@ -1049,10 +810,17 @@ interface
|
||||
clear_left_right(cmpop);
|
||||
end;
|
||||
|
||||
begin
|
||||
caddnode:=tcgaddnode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.4 2003-01-08 18:43:56 daniel
|
||||
Revision 1.5 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.4 2003/01/08 18:43:56 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.3 2002/12/14 15:02:03 carl
|
||||
|
@ -64,13 +64,18 @@ unit paramgr;
|
||||
is required for cdecl procedures
|
||||
}
|
||||
function copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
|
||||
{ Returns a structure giving the information on
|
||||
{# Returns a structure giving the information on
|
||||
the storage of the parameter (which must be
|
||||
an integer parameter)
|
||||
an integer parameter). This is only used when calling
|
||||
internal routines directly, where all parameters must
|
||||
be 4-byte values.
|
||||
|
||||
@param(nr Parameter number of routine, starting from 1)
|
||||
}
|
||||
function getintparaloc(nr : longint) : tparalocation;virtual;abstract;
|
||||
{# This is used to populate the location information on all parameters
|
||||
for the routine. This is used for normal call resolution.
|
||||
}
|
||||
procedure create_param_loc_info(p : tabstractprocdef);virtual;abstract;
|
||||
|
||||
{
|
||||
@ -400,7 +405,12 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.30 2003-01-08 18:43:56 daniel
|
||||
Revision 1.31 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.30 2003/01/08 18:43:56 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.29 2002/12/23 20:58:03 peter
|
||||
|
@ -512,6 +512,13 @@ uses
|
||||
usableregsmm = [R_M14..R_M31];
|
||||
c_countusableregsmm = 31-14+1;
|
||||
|
||||
{ no distinction on this platform }
|
||||
maxaddrregs = 0;
|
||||
addrregs = [];
|
||||
usableregsaddr = [];
|
||||
c_countusableregsaddr = 0;
|
||||
|
||||
|
||||
firstsaveintreg = R_13;
|
||||
lastsaveintreg = R_27;
|
||||
firstsavefpureg = R_F14;
|
||||
@ -821,7 +828,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.42 2003-01-16 11:31:28 olle
|
||||
Revision 1.43 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.42 2003/01/16 11:31:28 olle
|
||||
+ added new register constants
|
||||
+ implemented register convertion proc
|
||||
|
||||
|
@ -31,6 +31,7 @@ program pp;
|
||||
M68K generate a compiler for the M68000
|
||||
SPARC generate a compiler for SPARC
|
||||
POWERPC generate a compiler for the PowerPC
|
||||
VIS generate a compile for the VIS
|
||||
USEOVERLAY compiles a TP version which uses overlays
|
||||
DEBUG version with debug code is generated
|
||||
EXTDEBUG some extra debug code is executed
|
||||
@ -77,6 +78,12 @@ program pp;
|
||||
{$endif CPUDEFINED}
|
||||
{$define CPUDEFINED}
|
||||
{$endif M68K}
|
||||
{$ifdef vis}
|
||||
{$ifdef CPUDEFINED}
|
||||
{$fatal ONLY one of the switches for the CPU type must be defined}
|
||||
{$endif CPUDEFINED}
|
||||
{$define CPUDEFINED}
|
||||
{$endif}
|
||||
{$ifdef iA64}
|
||||
{$ifdef CPUDEFINED}
|
||||
{$fatal ONLY one of the switches for the CPU type must be defined}
|
||||
@ -179,7 +186,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.19 2002-11-15 01:58:53 peter
|
||||
Revision 1.20 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.19 2002/11/15 01:58:53 peter
|
||||
* merged changes from 1.0.7 up to 04-11
|
||||
- -V option for generating bug report tracing
|
||||
- more tracing for option parsing
|
||||
|
@ -43,6 +43,8 @@ unit rgobj;
|
||||
;
|
||||
|
||||
type
|
||||
|
||||
|
||||
regvar_longintarray = array[firstreg..lastreg] of longint;
|
||||
regvar_booleanarray = array[firstreg..lastreg] of boolean;
|
||||
regvar_ptreearray = array[firstreg..lastreg] of tnode;
|
||||
@ -55,6 +57,48 @@ unit rgobj;
|
||||
|
||||
tpushedsaved = array[firstreg..lastreg] of tpushedsavedloc;
|
||||
|
||||
(******************************* private struct **********************)
|
||||
psavedstate = ^tsavedstate;
|
||||
tsavedstate = record
|
||||
unusedregsint,usableregsint : tregisterset;
|
||||
unusedregsfpu,usableregsfpu : tregisterset;
|
||||
unusedregsmm,usableregsmm : tregisterset;
|
||||
unusedregsaddr,usableregsaddr : tregisterset;
|
||||
countunusedregsaddr,
|
||||
countunusedregsint,
|
||||
countunusedregsfpu,
|
||||
countunusedregsmm : byte;
|
||||
countusableregsaddr,
|
||||
countusableregsint,
|
||||
countusableregsfpu,
|
||||
countusableregsmm : byte;
|
||||
{ contains the registers which are really used by the proc itself }
|
||||
usedbyproc,
|
||||
usedinproc : tregisterset;
|
||||
reg_pushes : regvar_longintarray;
|
||||
is_reg_var : regvar_booleanarray;
|
||||
regvar_loaded: regvar_booleanarray;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user : regvar_ptreearray;
|
||||
reg_releaser : regvar_ptreearray;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
(******************************* private struct **********************)
|
||||
punusedstate = ^tunusedstate;
|
||||
tunusedstate = record
|
||||
unusedregsint : tregisterset;
|
||||
unusedregsfpu : tregisterset;
|
||||
unusedregsmm : tregisterset;
|
||||
unusedregsaddr : tregisterset;
|
||||
countunusedregsaddr,
|
||||
countunusedregsint,
|
||||
countunusedregsfpu,
|
||||
countunusedregsmm : byte;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{#
|
||||
This class implements the abstract register allocator
|
||||
It is used by the code generator to allocate and free
|
||||
@ -213,11 +257,11 @@ unit rgobj;
|
||||
|
||||
procedure makeregvar(reg: tregister);
|
||||
|
||||
procedure saveStateForInline(var state: pointer);
|
||||
procedure restoreStateAfterInline(var state: pointer);
|
||||
procedure saveStateForInline(var state: pointer);virtual;
|
||||
procedure restoreStateAfterInline(var state: pointer);virtual;
|
||||
|
||||
procedure saveUnusedState(var state: pointer);
|
||||
procedure restoreUnusedState(var state: pointer);
|
||||
procedure saveUnusedState(var state: pointer);virtual;
|
||||
procedure restoreUnusedState(var state: pointer);virtual;
|
||||
protected
|
||||
{ the following two contain the common (generic) code for all }
|
||||
{ get- and ungetregisterxxx functions/procedures }
|
||||
@ -275,40 +319,8 @@ unit rgobj;
|
||||
globals,verbose,
|
||||
cgobj,tgobj,regvars;
|
||||
|
||||
type
|
||||
psavedstate = ^tsavedstate;
|
||||
tsavedstate = record
|
||||
unusedregsint,usableregsint : tregisterset;
|
||||
unusedregsfpu,usableregsfpu : tregisterset;
|
||||
unusedregsmm,usableregsmm : tregisterset;
|
||||
countunusedregsint,
|
||||
countunusedregsfpu,
|
||||
countunusedregsmm : byte;
|
||||
countusableregsint,
|
||||
countusableregsfpu,
|
||||
countusableregsmm : byte;
|
||||
{ contains the registers which are really used by the proc itself }
|
||||
usedbyproc,
|
||||
usedinproc : tregisterset;
|
||||
reg_pushes : regvar_longintarray;
|
||||
is_reg_var : regvar_booleanarray;
|
||||
regvar_loaded: regvar_booleanarray;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user : regvar_ptreearray;
|
||||
reg_releaser : regvar_ptreearray;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
|
||||
punusedstate = ^tunusedstate;
|
||||
tunusedstate = record
|
||||
unusedregsint : tregisterset;
|
||||
unusedregsfpu : tregisterset;
|
||||
unusedregsmm : tregisterset;
|
||||
countunusedregsint,
|
||||
countunusedregsfpu,
|
||||
countunusedregsmm : byte;
|
||||
end;
|
||||
|
||||
|
||||
constructor trgobj.create;
|
||||
@ -532,6 +544,8 @@ unit rgobj;
|
||||
ungetregisterfpu(list,r)
|
||||
else if r.enum in mmregs then
|
||||
ungetregistermm(list,r)
|
||||
else if r.enum in addrregs then
|
||||
ungetaddressregister(list,r)
|
||||
else internalerror(2002070602);
|
||||
end;
|
||||
|
||||
@ -1016,7 +1030,12 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.21 2003-01-08 18:43:57 daniel
|
||||
Revision 1.22 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.21 2003/01/08 18:43:57 daniel
|
||||
* Tregister changed into a record
|
||||
|
||||
Revision 1.20 2002/10/05 12:43:28 carl
|
||||
|
@ -121,12 +121,12 @@ const
|
||||
IF_SSE = $00010000; { it's a SSE (KNI, MMX2) instruction }
|
||||
IF_PMASK = LongInt($FF000000); { the mask for processor types }
|
||||
IF_PFMASK = LongInt($F001FF00); { the mask for disassembly "prefer" }
|
||||
IF_V7 = $00000000; { SPARC V7 instruction only (not supported)}
|
||||
IF_V8 = $01000000; { SPARC V8 instruction (the default)}
|
||||
IF_V9 = $02000000; { SPARC V9 instruction (not yet supported)}
|
||||
IF_V7 = $00000000; { SPARC V7 instruction only (not supported)}
|
||||
IF_V8 = $01000000; { SPARC V8 instruction (the default)}
|
||||
IF_V9 = $02000000; { SPARC V9 instruction (not yet supported)}
|
||||
{ added flags }
|
||||
IF_PRE = $40000000; { it's a prefix instruction }
|
||||
IF_PASS2 = LongInt($80000000);{instruction can change in a second pass?}
|
||||
IF_PASS2 = LongInt($80000000);{instruction can change in a second pass?}
|
||||
TYPE
|
||||
{$WARNING CPU32 opcodes do not fully include the Ultra SPRAC instruction set.}
|
||||
{ don't change the order of these opcodes! }
|
||||
@ -378,6 +378,12 @@ const
|
||||
mmregs=[];
|
||||
usableregsmm=[];
|
||||
c_countusableregsmm=0;
|
||||
{ no distinction on this platform }
|
||||
maxaddrregs = 0;
|
||||
addrregs = [];
|
||||
usableregsaddr = [];
|
||||
c_countusableregsaddr = 0;
|
||||
|
||||
|
||||
firstsaveintreg = R_O0;
|
||||
lastsaveintreg = R_I7;
|
||||
@ -400,15 +406,15 @@ const
|
||||
Taken from rs6000.h (DBX_REGISTER_NUMBER) from GCC 3.x source code.}
|
||||
stab_regindex:ARRAY[firstreg..lastreg]OF ShortInt=({$INCLUDE stabregi.inc});
|
||||
{*************************** generic register names **************************}
|
||||
stack_pointer_reg = R_O6;
|
||||
frame_pointer_reg = R_I6;
|
||||
stack_pointer_reg = R_O6;
|
||||
frame_pointer_reg = R_I6;
|
||||
{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 = R_I0;
|
||||
return_result_reg = R_I0;
|
||||
{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 = R_O0;
|
||||
function_result_reg = R_O0;
|
||||
self_pointer_reg =R_G5;
|
||||
{There is no accumulator in the SPARC architecture. There are just families
|
||||
of registers. All registers belonging to the same family are identical except
|
||||
@ -493,6 +499,8 @@ const
|
||||
max_operands = 3;
|
||||
maxintregs = maxvarregs;
|
||||
maxfpuregs = maxfpuvarregs;
|
||||
|
||||
|
||||
|
||||
FUNCTION is_calljmp(o:tasmop):boolean;
|
||||
FUNCTION flags_to_cond(CONST f:TResFlags):TAsmCond;
|
||||
@ -603,7 +611,12 @@ END.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.21 2003-01-20 22:21:36 mazen
|
||||
Revision 1.22 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.21 2003/01/20 22:21:36 mazen
|
||||
* many stuff related to RTL fixed
|
||||
|
||||
Revision 1.20 2003/01/09 20:41:00 daniel
|
||||
|
@ -715,6 +715,9 @@ interface
|
||||
{$ifdef SPARC}
|
||||
pbestrealtype : ^ttype = @s64floattype;
|
||||
{$endif SPARC}
|
||||
{$ifdef vis}
|
||||
pbestrealtype : ^ttype = @s64floattype;
|
||||
{$endif vis}
|
||||
|
||||
function mangledname_prefix(typeprefix:string;st:tsymtable):string;
|
||||
|
||||
@ -5648,7 +5651,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.127 2003-01-21 14:36:44 pierre
|
||||
Revision 1.128 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.127 2003/01/21 14:36:44 pierre
|
||||
* set sizes needs to be passes in bits not bytes to stabs info
|
||||
|
||||
Revision 1.126 2003/01/16 22:11:33 peter
|
||||
|
@ -30,31 +30,34 @@ unit i_amiga;
|
||||
const
|
||||
system_m68k_amiga_info : tsysteminfo =
|
||||
(
|
||||
system : target_m68k_Amiga;
|
||||
system : system_m68k_Amiga;
|
||||
name : 'Commodore Amiga';
|
||||
shortname : 'amiga';
|
||||
flags : [];
|
||||
cpu : cpu_m68k;
|
||||
short_name : 'AMIGA';
|
||||
unit_env : '';
|
||||
extradefines : '';
|
||||
sharedlibext : '.library';
|
||||
staticlibext : '.a';
|
||||
sourceext : '.pp';
|
||||
pasext : '.pas';
|
||||
exeext : '';
|
||||
defext : '';
|
||||
scriptext : '';
|
||||
defext : '.def';
|
||||
scriptext : '.sh';
|
||||
smartext : '.sl';
|
||||
unitext : '.ppa';
|
||||
unitext : '.ppu';
|
||||
unitlibext : '.ppl';
|
||||
asmext : '.asm';
|
||||
objext : '.o';
|
||||
resext : '.res';
|
||||
resobjext : '.or';
|
||||
staticlibprefix : '';
|
||||
sharedlibext : '.library';
|
||||
staticlibext : '.a';
|
||||
staticlibprefix : 'lib';
|
||||
sharedlibprefix : '';
|
||||
Cprefix : '_';
|
||||
sharedClibext : '.library';
|
||||
staticClibext : '.a';
|
||||
staticClibprefix : 'lib';
|
||||
sharedClibprefix : '';
|
||||
Cprefix : '';
|
||||
newline : #10;
|
||||
dirsep : '/';
|
||||
files_case_relevent : true;
|
||||
@ -62,16 +65,31 @@ unit i_amiga;
|
||||
assemextern : as_gas;
|
||||
link : nil;
|
||||
linkextern : nil;
|
||||
ar : ar_m68k_ar;
|
||||
ar : ar_gnu_ar;
|
||||
res : res_none;
|
||||
script : script_amiga;
|
||||
endian : endian_big;
|
||||
stackalignment : 2;
|
||||
maxCrecordalignment : 4;
|
||||
heapsize : 128*1024;
|
||||
stacksize : 8192;
|
||||
alignment :
|
||||
(
|
||||
procalign : 4;
|
||||
loopalign : 4;
|
||||
jumpalign : 0;
|
||||
constalignmin : 0;
|
||||
constalignmax : 4;
|
||||
varalignmin : 0;
|
||||
varalignmax : 4;
|
||||
localalignmin : 0;
|
||||
localalignmax : 4;
|
||||
paraalign : 4;
|
||||
recordalignmin : 0;
|
||||
recordalignmax : 2;
|
||||
maxCrecordalign : 4
|
||||
);
|
||||
first_parm_offset : 8;
|
||||
heapsize : 256*1024;
|
||||
stacksize : 262144;
|
||||
DllScanSupported:false;
|
||||
use_function_relative_addresses : false
|
||||
use_function_relative_addresses : true
|
||||
);
|
||||
|
||||
implementation
|
||||
@ -79,13 +97,18 @@ unit i_amiga;
|
||||
initialization
|
||||
{$ifdef cpu68}
|
||||
{$ifdef AMIGA}
|
||||
set_source_info(system_m68k_Amiga);
|
||||
set_source_info(system_m68k_Amiga_info);
|
||||
{$endif amiga}
|
||||
{$endif cpu68}
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2002-09-06 15:03:51 carl
|
||||
Revision 1.2 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.1 2002/09/06 15:03:51 carl
|
||||
* moved files to systems directory
|
||||
|
||||
Revision 1.3 2002/08/13 18:01:51 carl
|
||||
|
259
compiler/vis/aasmcpu.pas
Normal file
259
compiler/vis/aasmcpu.pas
Normal file
@ -0,0 +1,259 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2001 by Florian Klaempfl and Pierre Muller
|
||||
|
||||
virtual instruction set family assembler instructions
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cclasses,aasmtai,
|
||||
aasmbase,globals,verbose,
|
||||
cpubase,cpuinfo;
|
||||
|
||||
|
||||
type
|
||||
|
||||
taicpu = class(taicpu_abstract)
|
||||
opsize : topsize;
|
||||
constructor op_none(op : tasmop;_size : topsize);
|
||||
|
||||
constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
|
||||
constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
|
||||
constructor op_ref(op : tasmop;_size : topsize;_op1 : treference);
|
||||
|
||||
constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
|
||||
constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
|
||||
constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
|
||||
|
||||
constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
|
||||
constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
|
||||
|
||||
|
||||
{ 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);
|
||||
{ for DBxx opcodes }
|
||||
constructor op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
|
||||
constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
|
||||
|
||||
constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
|
||||
constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
|
||||
|
||||
private
|
||||
procedure init(_size : topsize); { this need to be called by all constructor }
|
||||
end;
|
||||
|
||||
|
||||
tai_align = class(tai_align_abstract)
|
||||
{ nothing to add }
|
||||
end;
|
||||
|
||||
procedure InitAsm;
|
||||
procedure DoneAsm;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Taicpu Constructors
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
|
||||
|
||||
procedure taicpu.init(_size : topsize);
|
||||
begin
|
||||
typ:=ait_instruction;
|
||||
is_jmp:=false;
|
||||
opsize:=_size;
|
||||
ops:=0;
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_none(op : tasmop;_size : topsize);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=1;
|
||||
loadreg(0,_op1);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=1;
|
||||
loadconst(0,aword(_op1));
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : treference);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=1;
|
||||
loadref(0,_op1);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadreg(0,_op1);
|
||||
loadreg(1,_op2);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadreg(0,_op1);
|
||||
loadref(1,_op2);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadconst(0,aword(_op1));
|
||||
loadreg(1,_op2);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadconst(0,aword(_op1));
|
||||
loadref(1,_op2);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
|
||||
begin
|
||||
inherited create(op);;
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadref(0,_op1);
|
||||
loadreg(1,_op2);
|
||||
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_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
|
||||
begin
|
||||
inherited create(op);
|
||||
init(_size);
|
||||
ops:=2;
|
||||
loadreg(0,_op1);
|
||||
loadsymbol(1,_op2,0);
|
||||
end;
|
||||
|
||||
|
||||
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 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;
|
||||
loadreg(0,_op2);
|
||||
loadsymbol(1,_op1,_op1ofs);
|
||||
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;
|
||||
|
||||
|
||||
|
||||
procedure InitAsm;
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
procedure DoneAsm;
|
||||
begin
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
|
||||
|
||||
}
|
@ -66,18 +66,24 @@ uses
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
tregister = (R_NO,R_R0,R_R1,R_R2,R_R3,
|
||||
toldregister = (R_NO,R_R0,R_R1,R_R2,R_R3,
|
||||
R_R4,R_R5,R_R6,R_R7,
|
||||
R_R8,R_R9,R_R10,R_R11,
|
||||
R_CCR,R_SP,R_FP,R_PC,
|
||||
R_FP0,R_FP1,R_FP2,R_FP3,
|
||||
R_FP4,R_FP5,R_FP6,R_FP7,
|
||||
R_FP8,R_FP9,R_FP10,R_FP11,
|
||||
R_FP12,R_FP13,R_FP14,R_FP15
|
||||
R_FP12,R_FP13,R_FP14,R_FP15,
|
||||
R_INTREGISTER,R_FPUREGISTER
|
||||
);
|
||||
|
||||
{# Set type definition for registers }
|
||||
tregisterset = set of tregister;
|
||||
tregisterset = set of Toldregister;
|
||||
|
||||
tregister=record
|
||||
enum:toldregister;
|
||||
number:word;
|
||||
end;
|
||||
|
||||
{ A type to store register locations for 64 Bit values. }
|
||||
tregister64 = packed record
|
||||
@ -88,19 +94,31 @@ uses
|
||||
treg64 = tregister64;
|
||||
|
||||
{# Type definition for the array of string of register nnames }
|
||||
treg2strtable = array[tregister] of string[5];
|
||||
treg2strtable = array[toldregister] of string[5];
|
||||
|
||||
Const
|
||||
|
||||
{Special registers:}
|
||||
NR_NO = $0000; {Invalid register}
|
||||
|
||||
{Normal registers:}
|
||||
|
||||
{General purpose registers:}
|
||||
NR_R0 = $0100; NR_R1 = $0200; NR_R2 = $0300;
|
||||
NR_R3 = $0400; NR_R4 = $0500; NR_R5 = $0600;
|
||||
NR_R6 = $0700; NR_R7 = $0800; NR_R8 = $0900;
|
||||
NR_R9 = $0A00; NR_R10 = $0B00; NR_R11 = $0C00;
|
||||
|
||||
{# First register in the tregister enumeration }
|
||||
firstreg = low(tregister);
|
||||
firstreg = low(toldregister);
|
||||
{# Last register in the tregister enumeration }
|
||||
lastreg = high(tregister);
|
||||
lastreg = high(toldregister);
|
||||
|
||||
|
||||
std_reg2str : treg2strtable = ('',
|
||||
'r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','ccr',
|
||||
'sp','fp','pc','fp0','fp1','fp2','fp3','fp4','fp5','fp6','fp7',
|
||||
'fp8','fp9','fp10','fp11','fp12','fp13','fp14','fp15'
|
||||
'fp8','fp9','fp10','fp11','fp12','fp13','fp14','fp15','',''
|
||||
);
|
||||
|
||||
|
||||
@ -199,6 +217,16 @@ uses
|
||||
{*****************************************************************************
|
||||
Operand Sizes
|
||||
*****************************************************************************}
|
||||
{ S_NO = No Size of operand }
|
||||
{ S_B = 8-bit size operand }
|
||||
{ S_W = 16-bit size operand }
|
||||
{ S_L = 32-bit size operand }
|
||||
{ Floating point types }
|
||||
{ S_FS = single type (32 bit) }
|
||||
{ S_FD = double/64bit integer }
|
||||
{ S_FX = Extended type }
|
||||
topsize = (S_NO,S_B,S_W,S_L,S_FS,S_FD,S_FX,S_IQ);
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Generic Location
|
||||
@ -350,6 +378,12 @@ uses
|
||||
mmregs = [];
|
||||
usableregsmm = [];
|
||||
c_countusableregsmm = 0;
|
||||
|
||||
{ no distinction on this platform }
|
||||
maxaddrregs = 0;
|
||||
addrregs = [];
|
||||
usableregsaddr = [];
|
||||
c_countusableregsaddr = 0;
|
||||
|
||||
firstsaveintreg = R_R2;
|
||||
lastsaveintreg = R_R11;
|
||||
@ -359,11 +393,11 @@ uses
|
||||
lastsavemmreg = R_NO;
|
||||
|
||||
maxvarregs = 10;
|
||||
varregs : Array [1..maxvarregs] of Tregister =
|
||||
varregs : Array [1..maxvarregs] of toldregister =
|
||||
(R_R2,R_R3,R_R4,R_R5,R_R6,R_R7,R_R8,R_R9,R_R10,R_R11);
|
||||
|
||||
maxfpuvarregs = 15;
|
||||
fpuvarregs : Array [1..maxfpuvarregs] of Tregister =
|
||||
fpuvarregs : Array [1..maxfpuvarregs] of toldregister =
|
||||
(R_FP1,R_FP2,R_FP3,
|
||||
R_FP4,R_FP5,R_FP6,
|
||||
R_FP7,R_FP8,R_FP9,
|
||||
@ -381,7 +415,7 @@ uses
|
||||
routine calls or in assembler blocks.
|
||||
}
|
||||
max_scratch_regs = 2;
|
||||
scratch_regs: Array[1..max_scratch_regs] of TRegister = (R_R0,R_R1);
|
||||
scratch_regs: Array[1..max_scratch_regs] of toldregister = (R_R0,R_R1);
|
||||
|
||||
{*****************************************************************************
|
||||
Default generic sizes
|
||||
@ -406,7 +440,7 @@ uses
|
||||
Currently unsupported by abstract machine
|
||||
}
|
||||
|
||||
stab_regindex : array[tregister] of shortint =
|
||||
stab_regindex : array[toldregister] of shortint =
|
||||
(-1,
|
||||
{ r0..r11 }
|
||||
-1,-1,-1,-1,-1,-1,
|
||||
@ -416,7 +450,9 @@ uses
|
||||
{ FP0..FP7 }
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
{ FP8..FP15 }
|
||||
-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
{ invalid }
|
||||
-1,-1
|
||||
);
|
||||
|
||||
|
||||
@ -440,11 +476,11 @@ uses
|
||||
{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;
|
||||
return_result_reg = 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;
|
||||
function_result_reg = accumulator;
|
||||
{# Hi-Results are returned in this register (64-bit value high register) }
|
||||
accumulatorhigh = R_R1;
|
||||
fpu_result_reg = R_FP0;
|
||||
@ -480,6 +516,7 @@ uses
|
||||
|
||||
procedure inverse_flags(var r : TResFlags);
|
||||
function flags_to_cond(const f: TResFlags) : TAsmCond;
|
||||
procedure convert_register_to_enum(var r:Tregister);
|
||||
|
||||
|
||||
implementation
|
||||
@ -531,10 +568,40 @@ implementation
|
||||
flags_to_cond := flags2cond[f];
|
||||
end;
|
||||
|
||||
|
||||
procedure convert_register_to_enum(var r:Tregister);
|
||||
|
||||
begin
|
||||
if r.enum = R_INTREGISTER then
|
||||
case r.number of
|
||||
NR_NO: r.enum:= R_NO;
|
||||
NR_R0: r.enum:= R_R0;
|
||||
NR_R1: r.enum:= R_R1;
|
||||
NR_R2: r.enum:= R_R2;
|
||||
NR_R3: r.enum:= R_R3;
|
||||
NR_R4: r.enum:= R_R4;
|
||||
NR_R5: r.enum:= R_R5;
|
||||
NR_R6: r.enum:= R_R6;
|
||||
NR_R7: r.enum:= R_R7;
|
||||
NR_R8: r.enum:= R_R8;
|
||||
NR_R9: r.enum:= R_R9;
|
||||
NR_R10: r.enum:= R_R10;
|
||||
NR_R11: r.enum:= R_R11;
|
||||
else
|
||||
internalerror(200301082);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.3 2002-11-17 18:26:16 mazen
|
||||
Revision 1.4 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.3 2002/11/17 18:26:16 mazen
|
||||
* fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
|
||||
|
||||
Revision 1.2 2002/11/17 17:49:09 mazen
|
||||
|
84
compiler/vis/cpupara.pas
Normal file
84
compiler/vis/cpupara.pas
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 2002 by Florian Klaempfl
|
||||
|
||||
Generates the argument location information for the
|
||||
virtual instruction set machine
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published bymethodpointer
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
{ Generates the argument location information for 680x0.
|
||||
}
|
||||
unit cpupara;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cpubase,
|
||||
symdef,paramgr;
|
||||
|
||||
type
|
||||
{ Returns the location for the nr-st 32 Bit int parameter
|
||||
if every parameter before is an 32 Bit int parameter as well
|
||||
and if the calling conventions for the helper routines of the
|
||||
rtl are used.
|
||||
}
|
||||
tcpuparamanager = class(tparamanager)
|
||||
function getintparaloc(nr : longint) : tparalocation;override;
|
||||
procedure create_param_loc_info(p : tabstractprocdef);override;
|
||||
function getselflocation(p : tabstractprocdef) : tparalocation;override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose,
|
||||
globals,
|
||||
globtype,
|
||||
systems,
|
||||
cpuinfo,cginfo,cgbase,
|
||||
defutil;
|
||||
|
||||
function tcpuparamanager.getintparaloc(nr : longint) : tparalocation;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure tcpuparamanager.create_param_loc_info(p : tabstractprocdef);
|
||||
var
|
||||
param_offset : integer;
|
||||
hp : tparaitem;
|
||||
begin
|
||||
end;
|
||||
|
||||
function tcpuparamanager.getselflocation(p : tabstractprocdef) : tparalocation;
|
||||
begin
|
||||
end;
|
||||
|
||||
begin
|
||||
paramanager:=tcpuparamanager.create;
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
}
|
@ -371,6 +371,13 @@ const
|
||||
mmregs = [R_MM0..R_MM7];
|
||||
usableregsmm = [R_XMM0..R_XMM15];
|
||||
c_countusableregsmm = 8;
|
||||
|
||||
{ no distinction on this platform }
|
||||
maxaddrregs = 0;
|
||||
addrregs = [];
|
||||
usableregsaddr = [];
|
||||
c_countusableregsaddr = 0;
|
||||
|
||||
|
||||
firstsaveintreg = R_EAX;
|
||||
lastsaveintreg = R_R15;
|
||||
@ -417,11 +424,11 @@ const
|
||||
{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;
|
||||
return_result_reg = 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;
|
||||
function_result_reg = accumulator;
|
||||
accumulatorhigh = R_RDX;
|
||||
{ the register where the vmt offset is passed to the destructor }
|
||||
{ helper routine }
|
||||
@ -500,7 +507,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.5 2003-01-05 13:36:54 florian
|
||||
Revision 1.6 2003-02-02 19:25:54 carl
|
||||
* Several bugfixes for m68k target (register alloc., opcode emission)
|
||||
+ VIS target
|
||||
+ Generic add more complete (still not verified)
|
||||
|
||||
Revision 1.5 2003/01/05 13:36:54 florian
|
||||
* x86-64 compiles
|
||||
+ very basic support for float128 type (x86-64 only)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user