mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-25 04:29:10 +02:00
* merged i386/cpubase and x86_64/cpubase to x86/cpubase;
different stuff went to cpubase.inc
This commit is contained in:
parent
6aa01a99a9
commit
98d09473e4
@ -63,10 +63,6 @@
|
||||
'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
|
||||
);
|
||||
|
||||
{*****************************************************************************
|
||||
Constants
|
||||
*****************************************************************************}
|
||||
|
||||
firstsaveintreg = RS_EAX;
|
||||
lastsaveintreg = RS_EDX;
|
||||
firstsavefpureg = R_NO;
|
||||
@ -74,34 +70,6 @@
|
||||
firstsavemmreg = R_MM0;
|
||||
lastsavemmreg = R_MM7;
|
||||
|
||||
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
|
||||
|
||||
{$ifdef newra}
|
||||
usableregsint = [first_imreg..last_imreg];
|
||||
{$else}
|
||||
usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
|
||||
{$endif}
|
||||
c_countusableregsint = 4;
|
||||
|
||||
maxaddrregs = 1;
|
||||
addrregs = [R_ESI];
|
||||
usableregsaddr = [RS_ESI];
|
||||
c_countusableregsaddr = 1;
|
||||
|
||||
maxvarregs = 4;
|
||||
varregs : array[1..maxvarregs] of Toldregister =
|
||||
(R_EBX,R_EDX,R_ECX,R_EAX);
|
||||
|
||||
maxfpuvarregs = 8;
|
||||
|
||||
{# Registers which are defined as scratch and no need to save across
|
||||
routine calls or in assembler blocks.
|
||||
}
|
||||
{$ifndef newra}
|
||||
max_scratch_regs = 1;
|
||||
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
|
||||
{$endif}
|
||||
{*****************************************************************************
|
||||
GDB Information
|
||||
*****************************************************************************}
|
||||
@ -202,10 +170,7 @@
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.2 2002-04-25 16:12:09 florian
|
||||
* fixed more problems with cpubase and x86-64
|
||||
|
||||
Revision 1.1 2003/04/25 11:12:09 florian
|
||||
Revision 1.1 2003-04-25 11:12:09 florian
|
||||
* merged i386/cpubase and x86_64/cpubase to x86/cpubase;
|
||||
different stuff went to cpubase.inc
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -128,34 +128,6 @@ uses
|
||||
|
||||
{Super register numbers:}
|
||||
const
|
||||
{$ifdef x86_64}
|
||||
RS_SPECIAL = $00; {Special register}
|
||||
RS_RAX = $01; {EAX}
|
||||
RS_RBX = $02; {EBX}
|
||||
RS_RCX = $03; {ECX}
|
||||
RS_RDX = $04; {EDX}
|
||||
RS_RSI = $05; {ESI}
|
||||
RS_RDI = $06; {EDI}
|
||||
RS_RBP = $07; {EBP}
|
||||
RS_RSP = $08; {ESP}
|
||||
RS_R8 = $09; {R8}
|
||||
RS_R9 = $0a; {R9}
|
||||
RS_R10 = $0b; {R10}
|
||||
RS_R11 = $0c; {R11}
|
||||
RS_R12 = $0d; {R12}
|
||||
RS_R13 = $0e; {R13}
|
||||
RS_R14 = $0f; {R14}
|
||||
RS_R15 = $10; {R15}
|
||||
{ create aliases to allow code sharing between x86-64 and i386 }
|
||||
RS_EAX = RS_RAX;
|
||||
RS_EBX = RS_RBX;
|
||||
RS_ECX = RS_RCX;
|
||||
RS_EDX = RS_RDX;
|
||||
RS_ESI = RS_RSI;
|
||||
RS_EDI = RS_RDI;
|
||||
RS_EBP = RS_RBP;
|
||||
RS_ESP = RS_RSP;
|
||||
{$else x86_64}
|
||||
RS_SPECIAL = $00; {Special register}
|
||||
RS_EAX = $01; {EAX}
|
||||
RS_EBX = $02; {EBX}
|
||||
@ -165,7 +137,14 @@ uses
|
||||
RS_EDI = $06; {EDI}
|
||||
RS_EBP = $07; {EBP}
|
||||
RS_ESP = $08; {ESP}
|
||||
{$endif x86_64}
|
||||
RS_R8 = $09; {R8}
|
||||
RS_R9 = $0a; {R9}
|
||||
RS_R10 = $0b; {R10}
|
||||
RS_R11 = $0c; {R11}
|
||||
RS_R12 = $0d; {R12}
|
||||
RS_R13 = $0e; {R13}
|
||||
RS_R14 = $0f; {R14}
|
||||
RS_R15 = $10; {R15}
|
||||
|
||||
|
||||
{Number of first and last superregister.}
|
||||
@ -486,6 +465,9 @@ uses
|
||||
ALL_REGISTERS = [firstreg..lastreg];
|
||||
ALL_INTREGISTERS = [1..255];
|
||||
|
||||
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
|
||||
|
||||
{# low and high of the available maximum width integer general purpose }
|
||||
{ registers }
|
||||
LoGPReg = R_EAX;
|
||||
@ -510,6 +492,12 @@ uses
|
||||
|
||||
maxintregs = 4;
|
||||
intregs = [R_EAX..R_BL]-[R_ESI,R_SI];
|
||||
{$ifdef newra}
|
||||
usableregsint = [first_imreg..last_imreg];
|
||||
{$else}
|
||||
usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
|
||||
{$endif}
|
||||
c_countusableregsint = 4;
|
||||
|
||||
maxfpuregs = 8;
|
||||
fpuregs = [R_ST0..R_ST7];
|
||||
@ -520,6 +508,25 @@ uses
|
||||
usableregsmm = [R_MM0..R_MM7];
|
||||
c_countusableregsmm = 8;
|
||||
|
||||
maxaddrregs = 1;
|
||||
addrregs = [R_ESI];
|
||||
usableregsaddr = [RS_ESI];
|
||||
c_countusableregsaddr = 1;
|
||||
|
||||
maxvarregs = 4;
|
||||
varregs : array[1..maxvarregs] of Toldregister =
|
||||
(R_EBX,R_EDX,R_ECX,R_EAX);
|
||||
|
||||
maxfpuvarregs = 8;
|
||||
|
||||
{# Registers which are defined as scratch and no need to save across
|
||||
routine calls or in assembler blocks.
|
||||
}
|
||||
{$ifndef newra}
|
||||
max_scratch_regs = 1;
|
||||
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
|
||||
{$endif}
|
||||
|
||||
{*****************************************************************************
|
||||
CPU Dependent Constants
|
||||
*****************************************************************************}
|
||||
@ -707,14 +714,7 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.3 2002-04-25 20:15:40 florian
|
||||
* block nodes within expressions shouldn't release the used registers,
|
||||
fixed using a flag till the new rg is ready
|
||||
|
||||
Revision 1.2 2002/04/25 16:12:09 florian
|
||||
* fixed more problems with cpubase and x86-64
|
||||
|
||||
Revision 1.1 2003/04/25 11:12:09 florian
|
||||
Revision 1.1 2003-04-25 11:12:09 florian
|
||||
* merged i386/cpubase and x86_64/cpubase to x86/cpubase;
|
||||
different stuff went to cpubase.inc
|
||||
|
||||
|
@ -81,34 +81,7 @@ const
|
||||
firstsavemmreg = R_XMM0;
|
||||
lastsavemmreg = R_XMM15;
|
||||
|
||||
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
general_superregisters = [RS_RAX,RS_RBX,RS_RCX,RS_RDX];
|
||||
|
||||
{$ifdef newra}
|
||||
usableregsint = [first_imreg..last_imreg];
|
||||
{$else}
|
||||
usableregsint = [RS_RAX,RS_RBX,RS_RCX,RS_RDX];
|
||||
{$endif}
|
||||
c_countusableregsint = 4;
|
||||
|
||||
maxaddrregs = 1;
|
||||
addrregs = [R_ESI];
|
||||
usableregsaddr = [RS_RSI];
|
||||
c_countusableregsaddr = 1;
|
||||
|
||||
maxvarregs = 4;
|
||||
varregs : array[1..maxvarregs] of Toldregister =
|
||||
(R_EBX,R_EDX,R_ECX,R_EAX);
|
||||
|
||||
maxfpuvarregs = 8;
|
||||
|
||||
{# Registers which are defined as scratch and no need to save across
|
||||
routine calls or in assembler blocks.
|
||||
}
|
||||
{$ifndef newra}
|
||||
max_scratch_regs = 1;
|
||||
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_RDI);
|
||||
{$endif}
|
||||
{*****************************************************************************
|
||||
Default generic sizes
|
||||
*****************************************************************************}
|
||||
@ -126,33 +99,28 @@ const
|
||||
Generic Register names
|
||||
*****************************************************************************}
|
||||
|
||||
{# 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;
|
||||
{ location of function results }
|
||||
|
||||
{ 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;
|
||||
stack_pointer_reg = R_RSP;
|
||||
frame_pointer_reg = R_RBP;
|
||||
self_pointer_reg = R_RSI;
|
||||
accumulator = R_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;
|
||||
|
||||
fpu_result_reg = R_ST;
|
||||
mmresultreg = R_MM0;
|
||||
{ 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;
|
||||
accumulatorhigh = R_RDX;
|
||||
{ the register where the vmt offset is passed to the destructor }
|
||||
{ helper routine }
|
||||
vmt_offset_reg = R_RDI;
|
||||
|
||||
resultreg = R_RAX;
|
||||
resultreg64 = R_RAX;
|
||||
fpu_result_reg = R_ST;
|
||||
|
||||
{*****************************************************************************
|
||||
GCC /ABI linking information
|
||||
@ -178,10 +146,7 @@ const
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.2 2002-04-25 16:12:09 florian
|
||||
* fixed more problems with cpubase and x86-64
|
||||
|
||||
Revision 1.1 2003/04/25 11:12:09 florian
|
||||
Revision 1.1 2003-04-25 11:12:09 florian
|
||||
* merged i386/cpubase and x86_64/cpubase to x86/cpubase;
|
||||
different stuff went to cpubase.inc
|
||||
}
|
||||
|
@ -1,531 +0,0 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
|
||||
|
||||
Contains the basic declarations for the x86-64 architecture
|
||||
|
||||
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.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
{ This unit contains the basic declarations for the x86-64 architecture.
|
||||
}
|
||||
unit cpubase;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
globals,cutils,cclasses,
|
||||
aasmbase,
|
||||
cpuinfo,
|
||||
cginfo;
|
||||
|
||||
{*****************************************************************************
|
||||
Assembler Opcodes
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TAsmOp={$i x86_64op.inc}
|
||||
|
||||
{ This should define the array of instructions as string }
|
||||
op2strtable=array[tasmop] of string[11];
|
||||
|
||||
Const
|
||||
{ First value of opcode enumeration }
|
||||
firstop = low(tasmop);
|
||||
{ Last value of opcode enumeration }
|
||||
lastop = high(tasmop);
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Operand Sizes
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
topsize = (S_NO,
|
||||
S_B,S_W,S_L,S_BW,S_BL,S_WL,S_BQ,S_WQ,S_LQ,
|
||||
S_IS,S_IL,S_IQ,
|
||||
S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX,
|
||||
S_NEAR,S_FAR,S_SHORT
|
||||
);
|
||||
|
||||
{*****************************************************************************
|
||||
Registers
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
{ don't change the order }
|
||||
{ it's used by the register size conversions }
|
||||
{ Enumeration of all registers of the CPU }
|
||||
tregister = (R_NO,
|
||||
R_RAX,R_RCX,R_RDX,R_RBX,R_RSP,R_RBP,R_RSI,R_RDI,
|
||||
R_R8,R_R9,R_R10,R_R11,R_R12,R_R13,R_R14,R_R15,R_RIP,
|
||||
R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
|
||||
R_R8D,R_R9D,R_R10D,R_R11D,R_R12D,R_R13D,R_R14D,R_R15D,
|
||||
R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
|
||||
R_R8W,R_R9W,R_R10W,R_R11W,R_R12W,R_R13W,R_R14W,R_R15W,
|
||||
R_AL,R_CL,R_DL,R_BL,R_SPL,R_BPL,R_SIL,R_DIL,
|
||||
R_R8B,R_R9B,R_R10B,R_R11B,R_R12B,R_R13B,R_R14B,R_R15B,
|
||||
R_AH,R_CH,R_BH,R_DH,
|
||||
R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
|
||||
R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
|
||||
R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
|
||||
R_CR0,R_CR2,R_CR3,R_CR4,
|
||||
R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
|
||||
R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
|
||||
R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7,
|
||||
R_XMM8,R_XMM9,R_XMM10,R_XMM11,R_XMM12,R_XMM13,R_XMM14,R_XMM15
|
||||
);
|
||||
|
||||
{ A type to store register locations for 64 Bit values. }
|
||||
tregister64 = tregister;
|
||||
|
||||
{ alias for compact code }
|
||||
treg64 = tregister64;
|
||||
|
||||
{ Set type definition for registers }
|
||||
tregisterset = set of tregister;
|
||||
|
||||
{ Type definition for the array of string of register names }
|
||||
reg2strtable = array[tregister] of string[6];
|
||||
|
||||
const
|
||||
firstreg = low(tregister);
|
||||
lastreg = high(tregister);
|
||||
|
||||
firstsreg = R_CS;
|
||||
lastsreg = R_GS;
|
||||
|
||||
regset8bit : tregisterset = [R_AL..R_DH];
|
||||
regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
|
||||
regset32bit : tregisterset = [R_EAX..R_EDI];
|
||||
|
||||
{ Convert reg to opsize }
|
||||
reg2opsize:array[firstreg..lastreg] of topsize = (S_NO,
|
||||
S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,
|
||||
S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,
|
||||
S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
|
||||
S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
|
||||
S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
|
||||
S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
|
||||
S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
|
||||
S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
|
||||
S_B,S_B,S_B,S_B,
|
||||
S_W,S_W,S_W,S_W,S_W,S_W,
|
||||
S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
|
||||
S_L,S_L,S_L,S_L,S_L,S_L,
|
||||
S_L,S_L,S_L,S_L,
|
||||
S_L,S_L,S_L,S_L,S_L,
|
||||
S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
|
||||
S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
|
||||
S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
|
||||
);
|
||||
|
||||
{ Standard opcode string table (for each tasmop enumeration). The
|
||||
opcode strings should conform to the names as defined by the
|
||||
processor manufacturer.
|
||||
}
|
||||
std_op2str:op2strtable={$i x86_64in.inc}
|
||||
|
||||
{ Standard register table (for each tregister enumeration). The
|
||||
register strings should conform to the the names as defined
|
||||
by the processor manufacturer
|
||||
}
|
||||
std_reg2str : reg2strtable = ('',
|
||||
'rax','rcx','rdx','rbx','rsp','rbp','rsi','rdi',
|
||||
'r8','r9','r10','r11','r12','r13','r14','r15','rip',
|
||||
'eax','ecx','edx','ebx','esp','ebp','esi','edi',
|
||||
'r8d','r9d','r10d','r11d','r12d','r13d','r14d','r15d',
|
||||
'ax','cx','dx','bx','sp','bp','si','di',
|
||||
'r8w','r9w','r10w','r11w','r12w','r13w','r14w','r15w',
|
||||
'al','cl','dl','bl','spl','bpl','sil','dil',
|
||||
'r8b','r9b','r10b','r11b','r12b','r13b','r14b','r15b',
|
||||
'ah','ch','bh','dh',
|
||||
'cs','ds','es','ss','fs','gs',
|
||||
'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
|
||||
'dr0','dr1','dr2','dr3','dr6','dr7',
|
||||
'cr0','cr2','cr3','cr4',
|
||||
'tr3','tr4','tr5','tr6','tr7',
|
||||
'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
|
||||
'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7',
|
||||
'xmm8','xmm9','xmm10','xmm11','xmm12','xmm13','xmm14','xmm15');
|
||||
|
||||
{*****************************************************************************
|
||||
Conditions
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TAsmCond=(C_None,
|
||||
C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
|
||||
C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
|
||||
C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
|
||||
);
|
||||
|
||||
const
|
||||
cond2str:array[TAsmCond] of string[3]=('',
|
||||
'a','ae','b','be','c','e','g','ge','l','le','na','nae',
|
||||
'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
|
||||
'ns','nz','o','p','pe','po','s','z'
|
||||
);
|
||||
inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
|
||||
C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
|
||||
C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
|
||||
C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
|
||||
);
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Flags
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TResFlags = (F_E,F_NE,F_G,F_L,F_GE,F_LE,F_C,F_NC,F_A,F_AE,F_B,F_BE);
|
||||
|
||||
{*****************************************************************************
|
||||
Reference
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
|
||||
|
||||
{ immediate/reference record }
|
||||
preference = ^treference;
|
||||
treference = packed record
|
||||
offset : longint;
|
||||
symbol : tasmsymbol;
|
||||
offsetfixup : longint;
|
||||
segment,
|
||||
base,
|
||||
index : tregister;
|
||||
scalefactor : byte;
|
||||
options : trefoptions;
|
||||
alignment : byte;
|
||||
end;
|
||||
|
||||
{ reference record }
|
||||
pparareference = ^tparareference;
|
||||
tparareference = packed record
|
||||
index : tregister;
|
||||
offset : longint;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Operands
|
||||
*****************************************************************************}
|
||||
|
||||
{ Types of operand }
|
||||
toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
|
||||
|
||||
toper=record
|
||||
ot : longint;
|
||||
case typ : toptype of
|
||||
top_none : ();
|
||||
top_reg : (reg:tregister);
|
||||
top_ref : (ref:preference);
|
||||
top_const : (val:longint);
|
||||
top_symbol : (sym:tasmsymbol;symofs:longint);
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Generic Location
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
TLoc=(
|
||||
{ added for tracking problems}
|
||||
LOC_INVALID,
|
||||
{ contant }
|
||||
LOC_CONSTANT,
|
||||
{ in a processor register }
|
||||
LOC_REGISTER,
|
||||
{ in memory }
|
||||
LOC_CREFERENCE,
|
||||
{ like LOC_MEM, but lvalue }
|
||||
LOC_REFERENCE,
|
||||
{ boolean results only, jump to false or true label }
|
||||
LOC_JUMP,
|
||||
{ boolean results only, flags are set }
|
||||
LOC_FLAGS,
|
||||
{ Constant register which shouldn't be modified }
|
||||
LOC_CREGISTER,
|
||||
{ MMX register }
|
||||
LOC_MMXREGISTER,
|
||||
{ Constant MMX register }
|
||||
LOC_CMMXREGISTER,
|
||||
{ FPU stack }
|
||||
LOC_FPUREGISTER,
|
||||
{ if it is a FPU register variable on the fpu stack }
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_MMREGISTER,
|
||||
LOC_CMMREGISTER
|
||||
);
|
||||
|
||||
{ tparamlocation describes where a parameter for a procedure is stored.
|
||||
References are given from the caller's point of view. The usual
|
||||
TLocation isn't used, because contains a lot of unnessary fields.
|
||||
}
|
||||
tparalocation = packed record
|
||||
loc : TLoc;
|
||||
sp_fixup : longint;
|
||||
size : TCGSize;
|
||||
case TLoc of
|
||||
LOC_REFERENCE : (reference : tparareference);
|
||||
{ segment in reference at the same place as in loc_register }
|
||||
LOC_REGISTER,LOC_CREGISTER : (
|
||||
case longint of
|
||||
1 : (register,registerhigh : tregister);
|
||||
{ overlay a registerlow }
|
||||
2 : (registerlow : tregister);
|
||||
{ overlay a 64 Bit register type }
|
||||
3 : (reg64 : tregister64);
|
||||
4 : (register64 : tregister64);
|
||||
);
|
||||
{ it's only for better handling }
|
||||
LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
|
||||
end;
|
||||
|
||||
plocation = ^tlocation;
|
||||
tlocation = packed record
|
||||
loc : tloc;
|
||||
size : TCGSize;
|
||||
case TLoc of
|
||||
LOC_FLAGS : (resflags : tresflags);
|
||||
LOC_CONSTANT : (
|
||||
case longint of
|
||||
1 : (value : AWord);
|
||||
2 : (valuelow, valuehigh:AWord);
|
||||
{ overlay a complete 64 Bit value }
|
||||
3 : (valueqword : qword);
|
||||
);
|
||||
LOC_CREFERENCE,LOC_REFERENCE : (reference : treference);
|
||||
{ segment in reference at the same place as in loc_register }
|
||||
LOC_REGISTER,LOC_CREGISTER : (
|
||||
case longint of
|
||||
1 : (register,segment,registerhigh : tregister);
|
||||
{ overlay a registerlow }
|
||||
2 : (registerlow : tregister);
|
||||
{ overlay a 64 Bit register type }
|
||||
3 : (reg64 : tregister64);
|
||||
4 : (register64 : tregister64);
|
||||
);
|
||||
{ it's only for better handling }
|
||||
LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
Constants
|
||||
*****************************************************************************}
|
||||
|
||||
const
|
||||
max_operands = 3;
|
||||
|
||||
lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
|
||||
LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
|
||||
|
||||
ALL_REGISTERS = [R_EAX..R_XMM15];
|
||||
|
||||
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
|
||||
{ low and high of the available maximum width integer general purpose }
|
||||
{ registers }
|
||||
LoGPReg = R_EAX;
|
||||
HiGPReg = R_EDI;
|
||||
|
||||
{ low and high of every possible width general purpose register (same as }
|
||||
{ above on most architctures apart from the 80x86) }
|
||||
LoReg = R_EAX;
|
||||
HiReg = R_BL;
|
||||
|
||||
intregs = general_registers;
|
||||
|
||||
maxvarregs = 4;
|
||||
varregs : array[1..maxvarregs] of tregister =
|
||||
(R_EBX,R_EDX,R_ECX,R_EAX);
|
||||
|
||||
usableregsint = [R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
c_countusableregsint = 4;
|
||||
|
||||
maxfpuvarregs = 16;
|
||||
|
||||
maxintregs = maxvarregs;
|
||||
maxfpuregs = maxfpuvarregs;
|
||||
|
||||
fpuregs = [R_ST0..R_ST7];
|
||||
usableregsfpu = [];
|
||||
c_countusableregsfpu = 0;
|
||||
|
||||
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;
|
||||
firstsavefpureg = R_NO;
|
||||
lastsavefpureg = R_NO;
|
||||
firstsavemmreg = R_XMM0;
|
||||
lastsavemmreg = R_XMM15;
|
||||
|
||||
registers_saved_on_cdecl = [R_ESI,R_EDI,R_EBX];
|
||||
|
||||
scratch_regs : array[1..1] of tregister = (R_EDI);
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Default generic sizes
|
||||
*****************************************************************************}
|
||||
{ Defines the default address size for a processor, }
|
||||
OS_ADDR = OS_32;
|
||||
{ the natural int size for a processor, }
|
||||
OS_INT = OS_32;
|
||||
{ the maximum float size for a processor, }
|
||||
OS_FLOAT = OS_F80;
|
||||
{ the size of a vector register for a processor }
|
||||
OS_VECTOR = OS_M64;
|
||||
|
||||
cpuflags = [];
|
||||
|
||||
{ sizes }
|
||||
pointersize = 8;
|
||||
extended_size = 10;
|
||||
sizepostfix_pointer = S_L;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Generic Register names
|
||||
*****************************************************************************}
|
||||
|
||||
{ location of function results }
|
||||
|
||||
stack_pointer_reg = R_RSP;
|
||||
frame_pointer_reg = R_RBP;
|
||||
self_pointer_reg = R_RSI;
|
||||
accumulator = R_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;
|
||||
|
||||
{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;
|
||||
accumulatorhigh = R_RDX;
|
||||
{ the register where the vmt offset is passed to the destructor }
|
||||
{ helper routine }
|
||||
vmt_offset_reg = R_RDI;
|
||||
|
||||
resultreg = R_RAX;
|
||||
resultreg64 = R_RAX;
|
||||
fpu_result_reg = R_ST;
|
||||
|
||||
{*****************************************************************************
|
||||
GCC /ABI linking information
|
||||
*****************************************************************************}
|
||||
|
||||
const
|
||||
{ Registers which must be saved when calling a routine declared as
|
||||
cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
|
||||
saved should be the ones as defined in the target ABI and / or GCC.
|
||||
|
||||
This value can be deduced from the CALLED_USED_REGISTERS array in the
|
||||
GCC source.
|
||||
}
|
||||
std_saved_registers = [R_ESI,R_EDI,R_EBX];
|
||||
{ Required parameter alignment when calling a routine declared as
|
||||
stdcall and cdecl. The alignment value should be the one defined
|
||||
by GCC or the target ABI.
|
||||
|
||||
The value of this constant is equal to the constant
|
||||
PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
|
||||
}
|
||||
std_param_align = 8;
|
||||
|
||||
{*****************************************************************************
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
function is_calljmp(o:tasmop):boolean;
|
||||
|
||||
function flags_to_cond(const f: TResFlags) : TAsmCond;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{*****************************************************************************
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
function is_calljmp(o:tasmop):boolean;
|
||||
begin
|
||||
case o of
|
||||
A_CALL,
|
||||
A_JCXZ,
|
||||
A_JECXZ,
|
||||
A_JMP,
|
||||
A_LOOP,
|
||||
A_LOOPE,
|
||||
A_LOOPNE,
|
||||
A_LOOPNZ,
|
||||
A_LOOPZ,
|
||||
A_Jcc :
|
||||
is_calljmp:=true;
|
||||
else
|
||||
is_calljmp:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function flags_to_cond(const f: TResFlags) : TAsmCond;
|
||||
const
|
||||
flags_2_cond : array[TResFlags] of TAsmCond =
|
||||
(C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
|
||||
begin
|
||||
result := flags_2_cond[f];
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
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)
|
||||
|
||||
Revision 1.4 2002/11/17 18:26:16 mazen
|
||||
* fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
|
||||
|
||||
Revision 1.3 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
|
||||
|
||||
Revision 1.2 2002/07/25 22:55:33 florian
|
||||
* several fixes, small test units can be compiled
|
||||
|
||||
Revision 1.1 2002/07/24 22:38:15 florian
|
||||
+ initial release of x86-64 target code
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user