mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-27 08:13:42 +02:00
338 lines
14 KiB
Plaintext
338 lines
14 KiB
Plaintext
$Id$
|
|
|
|
Module CPUBASE
|
|
--------------
|
|
|
|
CONSTANTS used throughout the code generator
|
|
--------------------------------------------
|
|
|
|
Must of this is subject to be moved to cpuinfo
|
|
|
|
frame_pointer equals the register used as frame pointer
|
|
stack_pointer equals the register used as stack pointer
|
|
self_pointer equals the register used as self pointer
|
|
accumulator equals the register which will be used
|
|
as function return values
|
|
|
|
|
|
unusedregsint set of Currently available integer registers
|
|
unusedregsfpu set of Currently available fpu registers
|
|
unusedregsmm set of Currently available mm registers
|
|
|
|
availabletempregsint set of maximally available integer registers
|
|
availabletempregsfpu set of maximally available fpu registers
|
|
availabletempregsmm set of maximally available mm registers
|
|
|
|
countusableregsint count of currently available integer registers
|
|
countusableregsfpu count of currently available fpu registers
|
|
countusableregsmm count of currently available mm registers
|
|
|
|
c_countusableregsint count of max. available int registers (in the current procedure)
|
|
c_countusableregsfpu count of max. available fpu registers (in the current procedure)
|
|
c_countusableregsmm count of max. available mm registers (in the current procedure)
|
|
|
|
intregs all!! available integer register
|
|
fpuregs all!! available fpu register
|
|
mmregs all!! available multimedia register
|
|
|
|
lvaluelocations a set of all locations which can be an l-value
|
|
|
|
Locations
|
|
---------
|
|
The first pass assigns these location types which are then
|
|
used by the code generator to write out the correct instructions:
|
|
|
|
LOC_INVALID = This is an error and should never occur
|
|
LOC_REGISTER = Location is in a register
|
|
LOC_MEM = Memory reference (symbolic or register address?)
|
|
LOC_REFERENCE = Memory reference (symbolic or register address?)
|
|
LOC_JUMP = ????
|
|
LOC_FLAGS = Value is in the flags (Florian, this will give problems!)
|
|
LOC_CREGISTER = Value is in a constant register (across calls -
|
|
used for optimizations) - Constant registers
|
|
should not be directly modified????
|
|
LOC_CONST = Value is a numeric constant
|
|
|
|
Operand Sizes
|
|
-------------
|
|
OS_NO = No operand size.
|
|
OS_8 = 8-bit signed or unsigned value
|
|
OS_16 = 16-bit signed or unsigned value
|
|
OS_32 = 32-bit signed or unsigned value
|
|
OS_64 = 64-bit signed or unsigned value
|
|
|
|
Intel specific
|
|
--------------
|
|
unusedregssse
|
|
availabletempregssse
|
|
countusableregssse
|
|
|
|
Jonas Maebe schrieb:
|
|
>
|
|
> Hello,
|
|
>
|
|
> Is there any difference between the localsize parameter of
|
|
> g_stackframe_entry and the parasize parameter of g_return_from_proc, or
|
|
> are they both the same value?
|
|
|
|
They are different, I think the value of g_return_from_proc doesn't matter
|
|
for the PowerPC. It's the size of parameters passed on the stack
|
|
and only important for the i386/m68k probably.
|
|
|
|
>
|
|
> And for the PowerPC, what will they contain? Just the size of the local
|
|
> variables and parameters, or also the maximum needed size for parameters
|
|
> of any procedure called by the current one (the caller must reserve space
|
|
> for the callee's parameters on it's own stack because you can't push
|
|
> values on the stack in the middle of a procedure (no frame pointer))
|
|
>
|
|
> Jonas
|
|
|
|
the parameter passed to g_stackframe_entry contains the size of the all local space which is
|
|
needed
|
|
except
|
|
that one for saving registers: the set procinfo.registerstosave (not yet implemented,
|
|
I'll commit it soon) will contain
|
|
all registers which must be saved by the entry and restored by the exit code of a procedure
|
|
and you have to add extra space to do that.
|
|
|
|
The code generation
|
|
-------------------
|
|
|
|
The code generation can be seperated into 3 layers:
|
|
1. the method secondpass of the tnode childs
|
|
2. the procedure variables p2_
|
|
3. the code generator object
|
|
|
|
1.: This procedure does very high level stuff, if the code generation
|
|
is processor independent, it calls the appropriate procedures of the
|
|
code generator object to generate the code, but in most cases, it
|
|
calls procedure variables of the second layer
|
|
|
|
2. This procedure variables must be initialized to match the
|
|
current processor, these variables are used to optimize
|
|
existing processor instructions(? CEC).
|
|
|
|
The following procedure variables are currently used
|
|
|
|
Name Purpose Alternatives
|
|
-----------------------------------------------------------------------------
|
|
p2_assignment
|
|
p2_assignment_int64_reg Do an assignment of a int64
|
|
|
|
|
|
3. The code generator object does very basic operations like generating
|
|
move code etc, which is called by the p2_ functions and by the
|
|
secondpass procedures.
|
|
|
|
Alignment
|
|
---------
|
|
|
|
The alignment is handled very easily: treference contains a field
|
|
alignment which describes the ensured alignment for the node, possible
|
|
values: 1,2,4,8,16 (1 means unligned). The code generator must update
|
|
that field at the appropriate places and take care of it when
|
|
generating the code
|
|
|
|
MODULE CGOBJ (The code generator object)
|
|
------------
|
|
This is the basis of the code generator, it includes several
|
|
template instructions which are used to create a processor
|
|
independant code generator.
|
|
|
|
Fields:
|
|
scratch_register_array_pointer : aword;
|
|
?????????????????????
|
|
Indicates the free scratch registers?
|
|
|
|
unusedscratchregisters : tregisterset;
|
|
This holds the currently unused registers which can
|
|
be used as temporary placeholders.
|
|
|
|
alignment : talignment; ?? Why is this in cg object, should not
|
|
this be a constant instead?
|
|
|
|
Template instructions
|
|
---------------------
|
|
procedure a_call_name
|
|
|
|
Call a routine by symbolic name with a possible
|
|
numeric offset value.
|
|
|
|
|
|
|
|
???? WE ASSUME UNSIGNED???
|
|
|
|
{ move instructions }
|
|
procedure a_load_const_reg
|
|
--------------------------
|
|
Move a constant value to a register
|
|
|
|
procedure a_load_reg_ref
|
|
------------------------
|
|
Move a register value to a memory reference
|
|
|
|
procedure a_load_ref_reg
|
|
------------------------
|
|
Move the value at a specified address into a register
|
|
|
|
procedure a_load_reg_reg
|
|
------------------------
|
|
Move from register to register
|
|
|
|
WE NEED !!!!MOVE WITH SIGN EXTENSION??????????????????????
|
|
|
|
|
|
{ comparison operations }
|
|
????????????? WHAT DOES THE LABELS MEAN????????
|
|
|
|
procedure a_cmp_reg_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
|
|
l : pasmlabel);virtual;
|
|
procedure a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : pasmlabel);
|
|
procedure a_cmp_reg_ref_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;l : pasmlabel);
|
|
procedure a_cmp_ref_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
|
|
l : pasmlabel);
|
|
|
|
procedure a_jmp_cond(list : paasmoutput;cond : TOpCmp;l: pasmlabel);
|
|
|
|
procedure a_loadaddress_ref_reg(list : paasmoutput;const ref : treference;r : tregister);virtual;
|
|
|
|
|
|
??????????????
|
|
{ allocates register r by inserting a pai_realloc record }
|
|
procedure a_reg_alloc(list : paasmoutput;r : tregister);
|
|
{ deallocates register r by inserting a pa_regdealloc record}
|
|
procedure a_reg_dealloc(list : paasmoutput;r : tregister);
|
|
|
|
|
|
{ returns a register for use as scratch register }
|
|
function get_scratch_reg(list : paasmoutput) : tregister;
|
|
{ releases a scratch register }
|
|
procedure free_scratch_reg(list : paasmoutput;r : tregister);
|
|
|
|
{************************************************}
|
|
{ code generation for subroutine entry/exit code }
|
|
|
|
{ initilizes data of type t }
|
|
{ if is_already_ref is true then the routines assumes }
|
|
{ that r points to the data to initialize ???? }
|
|
procedure g_initialize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
|
|
|
|
{ finalizes data of type t }
|
|
{ if is_already_ref is true then the routines assumes }
|
|
{ that r points to the data to finalizes ???? }
|
|
procedure g_finalize(list : paasmoutput;t : pdef;const ref : treference;is_already_ref : boolean);
|
|
|
|
{ helper routines }
|
|
procedure g_initialize_data(list : paasmoutput;p : psym);
|
|
procedure g_incr_data(list : paasmoutput;p : psym);
|
|
procedure g_finalize_data(list : paasmoutput;p : pnamedindexobject);
|
|
procedure g_copyvalueparas(list : paasmoutput;p : pnamedindexobject);
|
|
procedure g_finalizetempansistrings(list : paasmoutput);
|
|
|
|
procedure g_entrycode(list : paasmoutput;
|
|
const proc_names : tstringcontainer;make_global : boolean;
|
|
stackframe : longint;var parasize : longint;
|
|
var nostackframe : boolean;inlined : boolean);
|
|
|
|
procedure g_exitcode(list : paasmoutput;parasize : longint;
|
|
nostackframe,inlined : boolean);
|
|
|
|
{ string helper routines }
|
|
procedure g_decrstrref(list : paasmoutput;const ref : treference;t : pdef);
|
|
|
|
procedure g_removetemps(list : paasmoutput;p : plinkedlist);
|
|
|
|
{ passing parameters, per default the parameter is pushed }
|
|
{ nr gives the number of the parameter (enumerated from }
|
|
{ left to right), this allows to move the parameter to }
|
|
{ register, if the cpu supports register calling }
|
|
{ conventions }
|
|
procedure a_param_reg(list : paasmoutput;size : tcgsize;r : tregister;nr : longint);virtual;
|
|
procedure a_param_const(list : paasmoutput;size : tcgsize;a : aword;nr : longint);virtual;
|
|
procedure a_param_ref(list : paasmoutput;size : tcgsize;const r : treference;nr : longint);virtual;
|
|
procedure a_paramaddr_ref(list : paasmoutput;const r : treference;nr : longint);virtual;
|
|
|
|
{**********************************}
|
|
{ these methods must be overriden: }
|
|
|
|
{ Remarks:
|
|
* If a method specifies a size you have only to take care
|
|
of that number of bits, i.e. load_const_reg with OP_8 must
|
|
only load the lower 8 bit of the specified register
|
|
the rest of the register can be undefined
|
|
if necessary the compiler will call a method
|
|
to zero or sign extend the register
|
|
* The a_load_XX_XX with OP_64 needn't to be
|
|
implemented for 32 bit
|
|
processors, the code generator takes care of that
|
|
* the addr size is for work with the natural pointer
|
|
size
|
|
* the procedures without fpu/mm are only for integer usage
|
|
* normally the first location is the source and the
|
|
second the destination
|
|
}
|
|
Virtual instruction templates:
|
|
|
|
|
|
|
|
|
|
procedure g_stackframe_entry(list : paasmoutput;localsize : longint);virtual;
|
|
{ restores the frame pointer at procedure exit, for the }
|
|
{ i386 it generates a simple leave }
|
|
procedure g_restore_frame_pointer(list : paasmoutput);virtual;
|
|
|
|
{ some processors like the PPC doesn't allow to change the stack in }
|
|
{ a procedure, so we need to maintain an extra stack for the }
|
|
{ result values of setjmp in exception code }
|
|
{ this two procedures are for pushing an exception value, }
|
|
{ they can use the scratch registers }
|
|
procedure g_push_exception_value_reg(list : paasmoutput;reg : tregister);virtual;
|
|
procedure g_push_exception_value_const(list : paasmoutput;reg : tregister);virtual;
|
|
{ that procedure pops a exception value }
|
|
procedure g_pop_exception_value_reg(list : paasmoutput;reg : tregister);virtual;
|
|
procedure g_return_from_proc(list : paasmoutput;parasize : aword);virtual;
|
|
{********************************************************}
|
|
{ these methods can be overriden for extra functionality }
|
|
|
|
{ the following methods do nothing: }
|
|
procedure g_interrupt_stackframe_entry(list : paasmoutput);virtual;
|
|
procedure g_interrupt_stackframe_exit(list : paasmoutput);virtual;
|
|
|
|
procedure g_profilecode(list : paasmoutput);virtual;
|
|
procedure g_stackcheck(list : paasmoutput;stackframesize : longint);virtual;
|
|
|
|
procedure a_load_const_ref(list : paasmoutput;size : tcgsize;a : aword;const ref : treference);virtual;
|
|
procedure g_maybe_loadself(list : paasmoutput);virtual;
|
|
{ copies len bytes from the source to destination, if }
|
|
{ loadref is true, it assumes that it first must load }
|
|
{ the source address from the memory location where }
|
|
{ source points to }
|
|
procedure g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);virtual;
|
|
|
|
{ uses the addr of ref as param, was emitpushreferenceaddr }
|
|
procedure a_param_ref_addr(list : paasmoutput;r : treference;nr : longint);virtual;
|
|
|
|
|
|
|
|
|
|
CVS Log
|
|
-------
|
|
|
|
$Log$
|
|
Revision 1.2 2000-11-30 22:16:51 florian
|
|
* moved to i386
|
|
|
|
Revision 1.1 2000/07/13 06:30:07 michael
|
|
+ Initial import
|
|
|
|
Revision 1.6 2000/03/02 03:22:16 carl
|
|
+ More information and suggestions
|
|
|
|
Revision 1.5 2000/03/01 15:36:12 florian
|
|
* some new stuff for the new cg
|
|
|
|
Revision 1.4 1999/10/14 14:57:54 florian
|
|
- removed the hcodegen use in the new cg, use cgbase instead
|
|
|