* synchronized cpubase between powerpc and i386

* moved more tables from cpubase to cpuasm
  * tai_align_abstract moved to tainst, cpuasm must define
    the tai_align class now, which may be empty
This commit is contained in:
peter 2002-05-14 17:28:08 +00:00
parent 4a176c81bc
commit f6b3e2e37f
12 changed files with 1200 additions and 1421 deletions

View File

@ -24,8 +24,8 @@
This unit implements an abstract assembler output class for all processors, these
are then overriden for each assembler writer to actually write the data in these
classes to an assembler file.
}
}
unit aasm;
{$i defines.inc}
@ -68,10 +68,11 @@ interface
ait_regalloc, { for register,temp allocation debugging }
ait_tempalloc,
ait_marker,
{$ifdef alpha}
{ the follow is for the DEC Alpha }
ait_frame,
ait_ent,
{$endif alpha}
{$ifdef m68k}
ait_labeled_instruction,
{$endif m68k}
@ -205,22 +206,6 @@ interface
end;
{ alignment for operator }
{$ifdef i386}
tai_align_abstract = class(tai)
{$else i386}
tai_align = class(tai)
{$endif i386}
buf : array[0..63] of char; { buf used for fill }
aligntype : byte; { 1 = no align, 2 = word align, 4 = dword align }
fillsize : byte; { real size to fill }
fillop : byte; { value to fill with - optional }
use_op : boolean;
constructor Create(b:byte);
constructor Create_op(b: byte; _op: byte);
function getfillbuf:pchar;
end;
{ Insert a section/segment directive }
tai_section = class(tai)
sec : tsection;
@ -742,56 +727,6 @@ uses
inherited Destroy;
end;
{****************************************************************************
TAI_ALIGN
****************************************************************************}
{$ifdef i386}
constructor tai_align_abstract.Create(b: byte);
{$else i386}
constructor tai_align.Create(b: byte);
{$endif i386}
begin
inherited Create;
typ:=ait_align;
if b in [1,2,4,8,16,32] then
aligntype := b
else
aligntype := 1;
fillsize:=0;
fillop:=0;
use_op:=false;
end;
{$ifdef i386}
constructor tai_align_abstract.Create_op(b: byte; _op: byte);
{$else i386}
constructor tai_align.Create_op(b: byte; _op: byte);
{$endif i386}
begin
inherited Create;
typ:=ait_align;
if b in [1,2,4,8,16,32] then
aligntype := b
else
aligntype := 1;
fillsize:=0;
fillop:=_op;
use_op:=true;
fillchar(buf,sizeof(buf),_op)
end;
{$ifdef i386}
function tai_align_abstract.getfillbuf:pchar;
{$else i386}
function tai_align.getfillbuf:pchar;
{$endif i386}
begin
getfillbuf:=@buf;
end;
{****************************************************************************
TAI_CUT
****************************************************************************}
@ -1135,7 +1070,13 @@ uses
end.
{
$Log$
Revision 1.23 2002-04-15 18:54:34 carl
Revision 1.24 2002-05-14 17:28:08 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.23 2002/04/15 18:54:34 carl
- removed tcpuflags
Revision 1.22 2002/04/07 13:18:19 carl

View File

@ -91,21 +91,19 @@ uses globals, aoptcpub, cpuinfo;
Function RefsEqual(Const R1, R2: TReference): Boolean;
Begin
If R1.is_immediate Then
RefsEqual := R2.is_immediate and (R1.Offset = R2.Offset)
Else
RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup)
And (R1.Base = R2.Base)
RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup)
And (R1.Base = R2.Base)
{$ifdef RefsHaveindex}
And (R1.Index = R2.Index)
And (R1.Index = R2.Index)
{$endif RefsHaveindex}
{$ifdef RefsHaveScale}
And (R1.ScaleFactor = R2.ScaleFactor)
And (R1.ScaleFactor = R2.ScaleFactor)
{$endif RefsHaveScale}
And (R1.Symbol = R2.Symbol)
And (R1.Symbol = R2.Symbol)
{$ifdef RefsHaveSegment}
And (R1.Segment = R2.Segment)
And (R1.Segment = R2.Segment)
{$endif RefsHaveSegment}
;
End;
@ -263,7 +261,13 @@ End.
{
$Log$
Revision 1.1 2001-08-26 13:36:35 florian
Revision 1.2 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.1 2001/08/26 13:36:35 florian
* some cg reorganisation
* some PPC updates

View File

@ -28,15 +28,6 @@ unit cpuasm;
{$i defines.inc}
{ Optimize addressing and skip already passed nodes }
{$ifndef NASMDEBUG}
{$define OPTEA}
{$define PASS2FLAG}
{$endif ndef NASMDEBUG}
{ Give warnings when an immediate is found in the reference struct }
{.$define REF_IMMEDIATE_WARN}
interface
uses
@ -51,6 +42,121 @@ const
Instruction table
*****************************************************************************}
const
{ Operand types }
OT_NONE = $00000000;
OT_BITS8 = $00000001; { size, and other attributes, of the operand }
OT_BITS16 = $00000002;
OT_BITS32 = $00000004;
OT_BITS64 = $00000008; { FPU only }
OT_BITS80 = $00000010;
OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
OT_NEAR = $00000040;
OT_SHORT = $00000080;
OT_SIZE_MASK = $000000FF; { all the size attributes }
OT_NON_SIZE = longint(not OT_SIZE_MASK);
OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
OT_TO = $00000200; { operand is followed by a colon }
{ reverse effect in FADD, FSUB &c }
OT_COLON = $00000400;
OT_REGISTER = $00001000;
OT_IMMEDIATE = $00002000;
OT_IMM8 = $00002001;
OT_IMM16 = $00002002;
OT_IMM32 = $00002004;
OT_IMM64 = $00002008;
OT_IMM80 = $00002010;
OT_REGMEM = $00200000; { for r/m, ie EA, operands }
OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
OT_REG8 = $00201001;
OT_REG16 = $00201002;
OT_REG32 = $00201004;
OT_MMXREG = $00201008; { MMX registers }
OT_XMMREG = $00201010; { Katmai registers }
OT_MEMORY = $00204000; { register number in 'basereg' }
OT_MEM8 = $00204001;
OT_MEM16 = $00204002;
OT_MEM32 = $00204004;
OT_MEM64 = $00204008;
OT_MEM80 = $00204010;
OT_FPUREG = $01000000; { floating point stack registers }
OT_FPU0 = $01000800; { FPU stack register zero }
OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
{ a mask for the following }
OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX }
OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
OT_REG_AX = $00211002; { ditto }
OT_REG_EAX = $00211004; { and again }
OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
OT_REG_CX = $00221002; { ditto }
OT_REG_ECX = $00221004; { another one }
OT_REG_DX = $00241002;
OT_REG_SREG = $00081002; { any segment register }
OT_REG_CS = $01081002; { CS }
OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
OT_REG_CDT = $00101004; { CRn, DRn and TRn }
OT_REG_CREG = $08101004; { CRn }
OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
OT_REG_DREG = $10101004; { DRn }
OT_REG_TREG = $20101004; { TRn }
OT_MEM_OFFS = $00604000; { special type of EA }
{ simple [address] offset }
OT_ONENESS = $00800000; { special type of immediate operand }
{ so UNITY == IMMEDIATE | ONENESS }
OT_UNITY = $00802000; { for shift/rotate instructions }
{Instruction flags }
IF_NONE = $00000000;
IF_SM = $00000001; { size match first two operands }
IF_SM2 = $00000002;
IF_SB = $00000004; { unsized operands can't be non-byte }
IF_SW = $00000008; { unsized operands can't be non-word }
IF_SD = $00000010; { unsized operands can't be nondword }
IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
IF_ARMASK = $00000060; { mask for unsized argument spec }
IF_PRIV = $00000100; { it's a privileged instruction }
IF_SMM = $00000200; { it's only valid in SMM }
IF_PROT = $00000400; { it's protected mode only }
IF_UNDOC = $00001000; { it's an undocumented instruction }
IF_FPU = $00002000; { it's an FPU instruction }
IF_MMX = $00004000; { it's an MMX instruction }
IF_3DNOW = $00008000; { it's a 3DNow! instruction }
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_8086 = $00000000; { 8086 instruction }
IF_186 = $01000000; { 186+ instruction }
IF_286 = $02000000; { 286+ instruction }
IF_386 = $03000000; { 386+ instruction }
IF_486 = $04000000; { 486+ instruction }
IF_PENT = $05000000; { Pentium instruction }
IF_P6 = $06000000; { P6 instruction }
IF_KATMAI = $07000000; { Katmai instructions }
IF_CYRIX = $10000000; { Cyrix-specific instruction }
IF_AMD = $20000000; { AMD-specific instruction }
{ added flags }
IF_PRE = $40000000; { it's a prefix instruction }
IF_PASS2 =
longint($80000000); { if the instruction can change in a second pass }
{ Size of the instruction table converted by nasmconv.pas }
instabentries = {$i i386nop.inc}
maxinfolen = 8;
type
tinsentry=packed record
opcode : tasmop;
@ -79,10 +185,10 @@ type
reg : tregister;
constructor create(b:byte);
constructor create_op(b: byte; _op: byte);
function getfillbuf:pchar;
function getfillbuf:pchar;override;
end;
taicpu = class(tainstruction)
taicpu = class(taicpu_abstract)
opsize : topsize;
constructor op_none(op : tasmop;_size : topsize);
@ -159,6 +265,44 @@ uses
ogbase,
ag386att;
const
{ Intel style operands ! }
opsize_2_type:array[0..2,topsize] of longint=(
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
),
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
),
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
)
);
{ Convert reg to operand type }
reg2type : array[firstreg..lastreg] of longint = (OT_NONE,
OT_REG_EAX,OT_REG_ECX,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,
OT_REG_AX,OT_REG_CX,OT_REG_DX,OT_REG16,OT_REG16,OT_REG16,OT_REG16,OT_REG16,
OT_REG_AL,OT_REG_CL,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,
OT_REG_CS,OT_REG_DESS,OT_REG_DESS,OT_REG_DESS,OT_REG_FSGS,OT_REG_FSGS,
OT_FPU0,OT_FPU0,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,
OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,
OT_REG_CREG,OT_REG_CREG,OT_REG_CREG,OT_REG_CR4,
OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,
OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,
OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG
);
{****************************************************************************
TAI_ALIGN
****************************************************************************}
@ -1663,7 +1807,13 @@ end;
end.
{
$Log$
Revision 1.21 2002-05-12 16:53:16 peter
Revision 1.22 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.21 2002/05/12 16:53:16 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function

View File

@ -4,10 +4,6 @@
Contains the base types for the i386
* This code was inspired by the NASM sources
The Netwide Assembler is copyright (C) 1996 Simon Tatham and
Julian Hall. All rights reserved.
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
@ -37,555 +33,365 @@ interface
uses
globals,cutils,cclasses,aasm,cpuinfo,cginfo;
const
{ Size of the instruction table converted by nasmconv.pas }
instabentries = {$i i386nop.inc}
maxinfolen = 8;
{ By default we want everything }
{$define ATTOP}
{$define INTELOP}
{$define ITTABLE}
{*****************************************************************************
Assembler Opcodes
*****************************************************************************}
{ We Don't need the intel style opcodes if we don't have a intel
reader or generator }
{$ifdef NORA386INT}
{$ifdef NOAG386NSM}
{$ifdef NOAG386INT}
{$undef INTELOP}
{$endif}
{$endif}
{$endif}
type
TAsmOp={$i i386op.inc}
{ We Don't need the AT&T style opcodes if we don't have a AT&T
reader or generator }
{$ifdef NORA386ATT}
{$ifdef NOAG386ATT}
{$undef ATTOP}
{$ifdef NOAG386DIR}
{$undef ATTREG}
{$endif}
{$endif}
{$endif}
{ We need the AT&T suffix table for both asm readers and AT&T writer }
{$define ATTSUF}
{$ifdef NORA386INT}
{$ifdef NORA386ATT}
{$ifdef NOAG386ATT}
{$undef ATTSUF}
{$endif}
{$endif}
{$endif}
const
{ Operand types }
OT_NONE = $00000000;
OT_BITS8 = $00000001; { size, and other attributes, of the operand }
OT_BITS16 = $00000002;
OT_BITS32 = $00000004;
OT_BITS64 = $00000008; { FPU only }
OT_BITS80 = $00000010;
OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
OT_NEAR = $00000040;
OT_SHORT = $00000080;
OT_SIZE_MASK = $000000FF; { all the size attributes }
OT_NON_SIZE = longint(not OT_SIZE_MASK);
OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
OT_TO = $00000200; { operand is followed by a colon }
{ reverse effect in FADD, FSUB &c }
OT_COLON = $00000400;
OT_REGISTER = $00001000;
OT_IMMEDIATE = $00002000;
OT_IMM8 = $00002001;
OT_IMM16 = $00002002;
OT_IMM32 = $00002004;
OT_IMM64 = $00002008;
OT_IMM80 = $00002010;
OT_REGMEM = $00200000; { for r/m, ie EA, operands }
OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
OT_REG8 = $00201001;
OT_REG16 = $00201002;
OT_REG32 = $00201004;
OT_MMXREG = $00201008; { MMX registers }
OT_XMMREG = $00201010; { Katmai registers }
OT_MEMORY = $00204000; { register number in 'basereg' }
OT_MEM8 = $00204001;
OT_MEM16 = $00204002;
OT_MEM32 = $00204004;
OT_MEM64 = $00204008;
OT_MEM80 = $00204010;
OT_FPUREG = $01000000; { floating point stack registers }
OT_FPU0 = $01000800; { FPU stack register zero }
OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
{ a mask for the following }
OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX }
OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
OT_REG_AX = $00211002; { ditto }
OT_REG_EAX = $00211004; { and again }
OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
OT_REG_CX = $00221002; { ditto }
OT_REG_ECX = $00221004; { another one }
OT_REG_DX = $00241002;
OT_REG_SREG = $00081002; { any segment register }
OT_REG_CS = $01081002; { CS }
OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
OT_REG_CDT = $00101004; { CRn, DRn and TRn }
OT_REG_CREG = $08101004; { CRn }
OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
OT_REG_DREG = $10101004; { DRn }
OT_REG_TREG = $20101004; { TRn }
OT_MEM_OFFS = $00604000; { special type of EA }
{ simple [address] offset }
OT_ONENESS = $00800000; { special type of immediate operand }
{ so UNITY == IMMEDIATE | ONENESS }
OT_UNITY = $00802000; { for shift/rotate instructions }
{Instruction flags }
IF_NONE = $00000000;
IF_SM = $00000001; { size match first two operands }
IF_SM2 = $00000002;
IF_SB = $00000004; { unsized operands can't be non-byte }
IF_SW = $00000008; { unsized operands can't be non-word }
IF_SD = $00000010; { unsized operands can't be nondword }
IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
IF_ARMASK = $00000060; { mask for unsized argument spec }
IF_PRIV = $00000100; { it's a privileged instruction }
IF_SMM = $00000200; { it's only valid in SMM }
IF_PROT = $00000400; { it's protected mode only }
IF_UNDOC = $00001000; { it's an undocumented instruction }
IF_FPU = $00002000; { it's an FPU instruction }
IF_MMX = $00004000; { it's an MMX instruction }
IF_3DNOW = $00008000; { it's a 3DNow! instruction }
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_8086 = $00000000; { 8086 instruction }
IF_186 = $01000000; { 186+ instruction }
IF_286 = $02000000; { 286+ instruction }
IF_386 = $03000000; { 386+ instruction }
IF_486 = $04000000; { 486+ instruction }
IF_PENT = $05000000; { Pentium instruction }
IF_P6 = $06000000; { P6 instruction }
IF_KATMAI = $07000000; { Katmai instructions }
IF_CYRIX = $10000000; { Cyrix-specific instruction }
IF_AMD = $20000000; { AMD-specific instruction }
{ added flags }
IF_PRE = $40000000; { it's a prefix instruction }
IF_PASS2 =
longint($80000000); { if the instruction can change in a second pass }
type
TAsmOp={$i i386op.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);
{# 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_IS,S_IL,S_IQ,
S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
S_NEAR,S_FAR,S_SHORT
);
const
{ Intel style operands ! }
opsize_2_type:array[0..2,topsize] of longint=(
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
),
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
),
(OT_NONE,
OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,
OT_BITS16,OT_BITS32,OT_BITS64,
OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
OT_NEAR,OT_FAR,OT_SHORT
)
);
{*****************************************************************************
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
);
type
topsize = (S_NO,
S_B,S_W,S_L,S_BW,S_BL,S_WL,
S_IS,S_IL,S_IQ,
S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
S_NEAR,S_FAR,S_SHORT
);
{*****************************************************************************
Registers
*****************************************************************************}
type
{# Enumeration for all possible registers for cpu. It
is to note that all registers of the same type
(for example all FPU registers), should be grouped
together.
}
{ don't change the order }
{ it's used by the register size conversions }
tregister = (R_NO,
R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
R_AL,R_CL,R_DL,R_BL,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
);
type
{# Enumeration for all possible registers for cpu. It
is to note that all registers of the same type
(for example all FPU registers), should be grouped
together.
}
{ don't change the order }
{ it's used by the register size conversions }
tregister = (R_NO,
R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
R_AL,R_CL,R_DL,R_BL,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
);
{# Set type definition for registers }
tregisterset = set of tregister;
{# Set type definition for registers }
tregisterset = set of tregister;
{# Type definition for the array of string of register nnames }
reg2strtable = array[tregister] of string[6];
{# Type definition for the array of string of register nnames }
reg2strtable = array[tregister] of string[6];
const
{# First register in the tregister enumeration }
firstreg = low(tregister);
{# Last register in the tregister enumeration }
lastreg = high(tregister);
const
{# First register in the tregister enumeration }
firstreg = low(tregister);
{# Last register in the tregister enumeration }
lastreg = high(tregister);
firstsreg = R_CS;
lastsreg = R_GS;
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];
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_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_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
);
{ Convert reg to opsize }
reg2opsize : array[firstreg..lastreg] of topsize = (S_NO,
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_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
);
{ Convert reg to operand type }
reg2type : array[firstreg..lastreg] of longint = (OT_NONE,
OT_REG_EAX,OT_REG_ECX,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,
OT_REG_AX,OT_REG_CX,OT_REG_DX,OT_REG16,OT_REG16,OT_REG16,OT_REG16,OT_REG16,
OT_REG_AL,OT_REG_CL,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,
OT_REG_CS,OT_REG_DESS,OT_REG_DESS,OT_REG_DESS,OT_REG_FSGS,OT_REG_FSGS,
OT_FPU0,OT_FPU0,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,
OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,
OT_REG_CREG,OT_REG_CREG,OT_REG_CREG,OT_REG_CR4,
OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,
OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,
OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG
);
{# 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 i386int.inc}
{# 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 i386int.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 = ('',
'eax','ecx','edx','ebx','esp','ebp','esi','edi',
'ax','cx','dx','bx','sp','bp','si','di',
'al','cl','dl','bl','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'
);
{# 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 = ('',
'eax','ecx','edx','ebx','esp','ebp','esi','edi',
'ax','cx','dx','bx','sp','bp','si','di',
'al','cl','dl','bl','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'
);
{*****************************************************************************
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);
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);
type
trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
type
{ immediate/reference record }
poperreference = ^treference;
treference = packed record
segment,
base,
index : tregister;
scalefactor : byte;
offset : longint;
symbol : tasmsymbol;
offsetfixup : longint;
options : trefoptions;
end;
{ reference record }
preference = ^treference;
treference = packed record
segment,
base,
index : tregister;
scalefactor : byte;
offset : longint;
symbol : tasmsymbol;
offsetfixup : longint;
options : trefoptions;
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:poperreference);
top_const : (val:aword);
top_symbol : (sym:tasmsymbol;symofs:longint);
end;
{*****************************************************************************
Argument Classification
*****************************************************************************}
{ 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:aword);
top_symbol : (sym:tasmsymbol;symofs:longint);
end;
{*****************************************************************************
Generic Location
*****************************************************************************}
type
TLoc=(
LOC_INVALID, { added for tracking problems}
LOC_CONSTANT, { constant value }
LOC_JUMP, { boolean results only, jump to false or true label }
LOC_FLAGS, { boolean results only, flags are set }
LOC_CREFERENCE, { in memory constant value reference (cannot change) }
LOC_REFERENCE, { in memory value }
LOC_REGISTER, { in a processor register }
LOC_CREGISTER, { Constant register which shouldn't be modified }
LOC_FPUREGISTER, { FPU stack }
LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
LOC_MMXREGISTER, { MMX register }
LOC_CMMXREGISTER, { MMX register variable }
LOC_SSEREGISTER,
LOC_CSSEREGISTER
);
type
TLoc=(
LOC_INVALID, { added for tracking problems}
LOC_CONSTANT, { constant value }
LOC_JUMP, { boolean results only, jump to false or true label }
LOC_FLAGS, { boolean results only, flags are set }
LOC_CREFERENCE, { in memory constant value reference (cannot change) }
LOC_REFERENCE, { in memory value }
LOC_REGISTER, { in a processor register }
LOC_CREGISTER, { Constant register which shouldn't be modified }
LOC_FPUREGISTER, { FPU stack }
LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
LOC_MMXREGISTER, { MMX register }
LOC_CMMXREGISTER, { MMX register variable }
LOC_SSEREGISTER,
LOC_CSSEREGISTER
);
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);
);
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);
);
{ it's only for better handling }
LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
end;
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);
);
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);
);
{ it's only for better handling }
LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
end;
{*****************************************************************************
Constants
*****************************************************************************}
const
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
const
max_operands = 3;
{# Table of registers which can be allocated by the code generator
internally, when generating the code.
}
{ legend: }
{ xxxregs = set of all possibly used registers of that type in the code }
{ generator }
{ usableregsxxx = set of all 32bit components of registers that can be }
{ possible allocated to a regvar or using getregisterxxx (this }
{ excludes registers which can be only used for parameter }
{ passing on ABI's that define this) }
{ c_countusableregsxxx = amount of registers in the usableregsxxx set }
lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
intregs = [R_EAX..R_BL];
usableregsint = general_registers;
c_countusableregsint = 4;
{# Constant defining possibly all registers which might require saving }
ALL_REGISTERS = [firstreg..lastreg];
fpuregs = [R_ST0..R_ST7];
usableregsfpu = [];
c_countusableregsfpu = 0;
general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
mmregs = [R_MM0..R_MM7];
usableregsmm = [R_MM0..R_MM7];
c_countusableregsmm = 8;
{# low and high of the available maximum width integer general purpose }
{ registers }
LoGPReg = R_EAX;
HiGPReg = R_EDX;
firstsaveintreg = R_EAX;
lastsaveintreg = R_EBX;
firstsavefpureg = R_NO;
lastsavefpureg = R_NO;
firstsavemmreg = R_MM0;
lastsavemmreg = R_MM7;
{# 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_DH;
{# Constant defining possibly all registers which might require saving }
ALL_REGISTERS = [firstreg..lastreg];
{# Table of registers which can be allocated by the code generator
internally, when generating the code.
}
{ legend: }
{ xxxregs = set of all possibly used registers of that type in the code }
{ generator }
{ usableregsxxx = set of all 32bit components of registers that can be }
{ possible allocated to a regvar or using getregisterxxx (this }
{ excludes registers which can be only used for parameter }
{ passing on ABI's that define this) }
{ c_countusableregsxxx = amount of registers in the usableregsxxx set }
lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
maxintregs = 4;
intregs = [R_EAX..R_BL];
usableregsint = [R_EAX,R_EBX,R_ECX,R_EDX];
c_countusableregsint = 4;
maxfpuregs = 8;
fpuregs = [R_ST0..R_ST7];
usableregsfpu = [];
c_countusableregsfpu = 0;
mmregs = [R_MM0..R_MM7];
usableregsmm = [R_MM0..R_MM7];
c_countusableregsmm = 8;
firstsaveintreg = R_EAX;
lastsaveintreg = R_EBX;
firstsavefpureg = R_NO;
lastsavefpureg = R_NO;
firstsavemmreg = R_MM0;
lastsavemmreg = R_MM7;
maxvarregs = 4;
varregs : array[1..maxvarregs] of tregister =
(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.
}
max_scratch_regs = 1;
scratch_regs : array[1..max_scratch_regs] 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;
{# 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;
{*****************************************************************************
Generic Register names
*****************************************************************************}
{# Stack pointer register }
stack_pointer_reg = R_ESP;
{# Frame pointer register }
frame_pointer_reg = R_EBP;
{# Self pointer register : contains the instance address of an
object or class. }
self_pointer_reg = R_ESI;
{# Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific }
pic_offset_reg = R_EBX;
{# Results are returned in this register (32-bit values) }
accumulator = R_EAX;
{# 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 }
{ a_loadfpu* methods in rgcpu (JM) }
fpuresultreg = R_ST;
mmresultreg = R_MM0;
{# Registers which are defined as scratch and no need to save across
routine calls or in assembler blocks.
}
scratch_regs : array[1..1] of tregister = (R_EDI);
{# Stack pointer register }
stack_pointer_reg = R_ESP;
{# Frame pointer register }
frame_pointer_reg = R_EBP;
{# Self pointer register : contains the instance address of an
object or class. }
self_pointer_reg = R_ESI;
{# Register for addressing absolute data in a position independant way,
such as in PIC code. The exact meaning is ABI specific }
pic_offset_reg = R_EBX;
{# Results are returned in this register (32-bit values) }
accumulator = R_EAX;
{# 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 }
{ a_loadfpu* methods in rgcpu (JM) }
fpuresultreg = R_ST;
mmresultreg = R_MM0;
{*****************************************************************************
GCC /ABI linking information
*****************************************************************************}
{# 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 = 4;
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 = 4;
{*****************************************************************************
CPU Dependent Constants
*****************************************************************************}
{*****************************************************************************
Helpers
*****************************************************************************}
const
maxvarregs = 4;
varregs : array[1..maxvarregs] of tregister =
(R_EBX,R_EDX,R_ECX,R_EAX);
maxfpuvarregs = 8;
max_operands = 3;
maxintregs = maxvarregs;
maxfpuregs = maxfpuvarregs;
function is_calljmp(o:tasmop):boolean;
function flags_to_cond(const f: TResFlags) : TAsmCond;
@ -593,17 +399,10 @@ const
implementation
{$ifdef heaptrc}
uses
ppheap;
{$endif heaptrc}
{*****************************************************************************
Helpers
*****************************************************************************}
function is_calljmp(o:tasmop):boolean;
begin
case o of
@ -624,9 +423,6 @@ implementation
end;
function flags_to_cond(const f: TResFlags) : TAsmCond;
const
flags_2_cond : array[TResFlags] of TAsmCond =
@ -635,11 +431,16 @@ implementation
result := flags_2_cond[f];
end;
end.
{
$Log$
Revision 1.19 2002-05-12 16:53:16 peter
Revision 1.20 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.19 2002/05/12 16:53:16 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function

View File

@ -1616,7 +1616,7 @@ Begin
End;
Procedure ReadRef(p: PTaiProp; Const Ref: POperReference);
Procedure ReadRef(p: PTaiProp; Const Ref: PReference);
Begin
If Ref^.Base <> R_NO Then
ReadReg(p, Ref^.Base);
@ -2591,7 +2591,13 @@ End.
{
$Log$
Revision 1.34 2002-05-12 16:53:16 peter
Revision 1.35 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.34 2002/05/12 16:53:16 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function

View File

@ -228,14 +228,16 @@ const
procedure tcgppc.a_call_name(list : taasmoutput;const s : string);
var
href : treference;
begin
{ save our RTOC register value. Only necessary when doing pointer based }
{ calls or cross TOC calls, but currently done always }
list.concat(taicpu.op_reg_ref(A_STW,R_RTOC,
new_reference(STACK_POINTER_REG,LA_RTOC)));
reference_reset_base(href,STACK_POINTER_REG,LA_RTOC);
list.concat(taicpu.op_reg_ref(A_STW,R_TOC,href));
list.concat(taicpu.op_sym(A_BL,newasmsymbol(s)));
list.concat(taicpu.op_reg_ref(A_LWZ,R_RTOC,
new_reference(STACK_POINTER_REG,LA_RTOC)));
reference_reset_base(href,STACK_POINTER_REG,LA_RTOC);
list.concat(taicpu.op_reg_ref(A_LWZ,R_TOC,href));
end;
{********************** load instructions ********************}
@ -302,19 +304,14 @@ const
ref2, tmpref: treference;
begin
if ref.is_immediate then
a_load_const_reg(list,size,ref.offset,reg)
else
begin
ref2 := ref;
fixref(list,ref2);
op := loadinstr[size,ref2.index<>R_NO,false];
a_load_store(list,op,reg,ref2);
{ sign extend shortint if necessary, since there is no }
{ load instruction that does that automatically (JM) }
if size = OS_S8 then
list.concat(taicpu.op_reg_reg(A_EXTSB,reg,reg));
end;
ref2 := ref;
fixref(list,ref2);
op := loadinstr[size,ref2.index<>R_NO,false];
a_load_store(list,op,reg,ref2);
{ sign extend shortint if necessary, since there is no }
{ load instruction that does that automatically (JM) }
if size = OS_S8 then
list.concat(taicpu.op_reg_reg(A_EXTSB,reg,reg));
end;
@ -701,6 +698,7 @@ const
{ combined size of ALL the parameters of a procedure called by the current }
{ one }
var regcounter: TRegister;
href : treference;
begin
if (localsize mod 8) <> 0 then internalerror(58991);
@ -716,7 +714,8 @@ const
{ save return address... }
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_LR));
{ ... in caller's frame }
list.concat(taicpu.op_reg_ref(A_STW,R_0,new_reference(STACK_POINTER_REG,4)));
reference_reset_base(href,STACK_POINTER_REG,4);
list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
a_reg_dealloc(list,R_0);
a_reg_alloc(list,R_11);
{ save end of fpr save area }
@ -761,6 +760,7 @@ const
{ combined size of ALL the parameters of a procedure called by the current }
{ one }
var regcounter: TRegister;
href : treference;
begin
if (localsize mod 8) <> 0 then internalerror(58991);
@ -776,19 +776,21 @@ const
{ save return address... }
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_LR));
{ ... in caller's frame }
list.concat(taicpu.op_reg_ref(A_STW,R_0,new_reference(STACK_POINTER_REG,8)));
reference_reset_base(href,STACK_POINTER_REG,8);
list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
a_reg_dealloc(list,R_0);
{ save floating-point registers }
{ !!! has to be optimized: only save registers that are used }
list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savef14'),0));
{ save gprs in gpr save area }
{ !!! has to be optimized: only save registers that are used }
list.concat(taicpu.op_reg_ref(A_STMW,R_13,new_reference(STACK_POINTER_REG,-220)));
reference_reset_base(href,STACK_POINTER_REG,-220);
list.concat(taicpu.op_reg_ref(A_STMW,R_13,href));
{ save the CR if necessary ( !!! always done currently ) }
a_reg_alloc(list,R_0);
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR));
list.concat(taicpu.op_reg_ref(A_STW,R_0,
new_reference(stack_pointer_reg,LA_CR)));
reference_reset_base(href,stack_pointer_reg,LA_CR);
list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
a_reg_dealloc(list,R_0);
{ save pointer to incoming arguments }
list.concat(taicpu.op_reg_reg_const(A_ORI,R_31,STACK_POINTER_REG,0));
@ -840,22 +842,20 @@ const
{ reference doesn't have a base, create one }
begin
tmpreg := get_scratch_reg(list);
reset_reference(tmpref);
reference_reset(tmpref);
tmpref.symbol := ref2.symbol;
tmpref.symaddr := refs_ha;
tmpref.is_immediate := true;
// tmpref.is_immediate := true;
if ref2.base <> R_NO then
list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
ref2.base,newreference(tmpref)))
ref2.base,tmpref))
else
list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,
newreference(tmpref)));
list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
ref2.base := tmpreg;
ref2.symaddr := refs_l;
{ can be folded with one of the next instructions by the }
{ optimizer probably }
list.concat(taicpu.op_reg_reg_ref(A_ADDI,tmpreg,tmpreg,
newreference(tmpref)));
list.concat(taicpu.op_reg_reg_ref(A_ADDI,tmpreg,tmpreg,tmpref));
end;
if ref2.offset <> 0 Then
if ref2.base <> R_NO then
@ -890,8 +890,8 @@ const
fixref(list,src);
dst := dest;
fixref(list,dst);
reset_reference(src);
reset_reference(dst);
reference_reset(src);
reference_reset(dst);
{ load the address of source into src.base }
src.base := get_scratch_reg(list);
if loadref then
@ -922,10 +922,9 @@ const
a_reg_alloc(list,R_0);
getlabel(lab);
a_label(list, lab);
list.concat(taicpu.op_reg_ref(A_LWZU,tempreg,
newreference(src)));
list.concat(taicpu.op_reg_ref(A_LWZU,tempreg,src));
list.concat(taicpu.op_reg_reg_const(A_CMPI,R_CR0,countreg,0));
list.concat(taicpu.op_reg_ref(A_STWU,tempreg,newreference(dst)));
list.concat(taicpu.op_reg_ref(A_STWU,tempreg,dst));
list.concat(taicpu.op_reg_reg_const(A_SUBI,countreg,countreg,1));
a_jmp(list,A_BC,C_NE,0,lab);
free_scratch_reg(list,countreg);
@ -1012,7 +1011,7 @@ const
var
regcounter: TRegister;
href : treference;
begin
{ release parameter registers }
for regcounter := R_3 to R_10 do
@ -1022,9 +1021,11 @@ const
{ restore SP }
list.concat(taicpu.op_reg_reg_const(A_ORI,STACK_POINTER_REG,R_31,0));
{ restore gprs }
list.concat(taicpu.op_reg_ref(A_LMW,R_13,new_reference(STACK_POINTER_REG,-220)));
reference_reset_base(href,STACK_POINTER_REG,-220);
list.concat(taicpu.op_reg_ref(A_LMW,R_13,href));
{ restore return address ... }
list.concat(taicpu.op_reg_ref(A_LWZ,R_0,new_reference(STACK_POINTER_REG,8)));
reference_reset_base(href,STACK_POINTER_REG,8);
list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
{ ... and return from _restf14 }
list.concat(taicpu.op_sym_ofs(A_B,newasmsymbol('_restf14'),0));
end;
@ -1137,20 +1138,19 @@ const
if assigned(ref.symbol) then
begin
tmpreg := get_scratch_reg(list);
reset_reference(tmpref);
reference_reset(tmpref);
tmpref.symbol := ref.symbol;
tmpref.symaddr := refs_ha;
tmpref.is_immediate := true;
// tmpref.is_immediate := true;
if ref.base <> R_NO then
list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
ref.base,newreference(tmpref)))
ref.base,tmpref))
else
list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,
newreference(tmpref)));
list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
ref.base := tmpreg;
ref.symaddr := refs_l;
end;
list.concat(taicpu.op_reg_ref(op,reg,newreference(ref)));
list.concat(taicpu.op_reg_ref(op,reg,ref));
if assigned(ref.symbol) then
free_scratch_reg(list,tmpreg);
end;
@ -1173,7 +1173,13 @@ begin
end.
{
$Log$
Revision 1.14 2002-05-13 19:52:46 peter
Revision 1.15 2002-05-14 17:28:10 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.14 2002/05/13 19:52:46 peter
* a ppcppc can be build again
Revision 1.13 2002/04/20 21:41:51 carl

View File

@ -31,54 +31,52 @@ uses
aasm,globals,verbose,
cpubase;
type
type
taicpu = class(taicpu_abstract)
constructor op_none(op : tasmop);
taicpu = class(tainstruction)
constructor op_none(op : tasmop);
constructor op_reg(op : tasmop;_op1 : tregister);
constructor op_const(op : tasmop;_op1 : longint);
constructor op_reg(op : tasmop;_op1 : tregister);
constructor op_const(op : tasmop;_op1 : longint);
constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
constructor op_const_reg(op:tasmop; _op1: longint; _op2: tregister);
constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
constructor op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
constructor op_const_reg(op:tasmop; _op1: longint; _op2: tregister);
constructor op_const_const(op : tasmop;_op1,_op2 : longint);
constructor op_const_const(op : tasmop;_op1,_op2 : longint);
constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint);
constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
constructor op_const_reg_reg(op : tasmop;_op1 : longint;_op2, _op3 : tregister);
constructor op_const_reg_const(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : longint);
constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint);
constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; _op3: preference);
constructor op_const_reg_reg(op : tasmop;_op1 : longint;_op2, _op3 : tregister);
constructor op_const_reg_const(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : longint);
constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
constructor op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
constructor op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: longint);
constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
constructor op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
constructor op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: longint);
constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : Longint);
constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : Longint);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
constructor op_const_const_sym(op : tasmop;_op1,_op2 : longint;_op3: tasmsymbol);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
constructor op_const_const_sym(op : tasmop;_op1,_op2 : longint;_op3: tasmsymbol);
constructor op_sym(op : tasmop;_op1 : tasmsymbol);
constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
constructor op_sym(op : tasmop;_op1 : tasmsymbol);
constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
procedure loadbool(opidx:longint;_b:boolean);
procedure loadconst(opidx:longint;l:longint);
procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
procedure loadref(opidx:longint;p:preference);
procedure loadreg(opidx:longint;r:tregister);
procedure loadoper(opidx:longint;o:toper);
procedure loadbool(opidx:longint;_b:boolean);
destructor destroy;override;
end;
destructor destroy;override;
end;
tai_align = class(tai_align_abstract)
{ nothing to add }
end;
procedure InitAsm;
procedure DoneAsm;
@ -90,93 +88,6 @@ implementation
taicpu Constructors
*****************************************************************************}
procedure taicpu.loadconst(opidx:longint;l:longint);
begin
if opidx>=ops then
ops:=opidx+1;
with oper[opidx] do
begin
if typ=top_ref then
disposereference(ref);
val:=l;
typ:=top_const;
end;
end;
procedure taicpu.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
begin
if opidx>=ops then
ops:=opidx+1;
with oper[opidx] do
begin
if typ=top_ref then
disposereference(ref);
sym:=s;
symofs:=sofs;
typ:=top_symbol;
end;
{ Mark the symbol as used }
if assigned(s) then
inc(s.refs);
end;
procedure taicpu.loadref(opidx:longint;p:preference);
begin
if opidx>=ops then
ops:=opidx+1;
with oper[opidx] do
begin
if typ=top_ref then
disposereference(ref);
if p^.is_immediate then
begin
{$ifdef REF_IMMEDIATE_WARN}
Comment(V_Warning,'Reference immediate');
{$endif}
val:=p^.offset;
disposereference(p);
typ:=top_const;
end
else
begin
ref:=p;
typ:=top_ref;
{ mark symbol as used }
if assigned(ref^.symbol) then
inc(ref^.symbol.refs);
end;
end;
end;
procedure taicpu.loadreg(opidx:longint;r:tregister);
begin
if opidx>=ops then
ops:=opidx+1;
with oper[opidx] do
begin
if typ=top_ref then
disposereference(ref);
reg:=r;
typ:=top_reg;
end;
end;
procedure taicpu.loadoper(opidx:longint;o:toper);
begin
if opidx>=ops then
ops:=opidx+1;
if oper[opidx].typ=top_ref then
disposereference(oper[opidx].ref);
oper[opidx]:=o;
{ copy also the reference }
if oper[opidx].typ=top_ref then
oper[opidx].ref:=newreference(o.ref^);
end;
procedure taicpu.loadbool(opidx:longint;_b:boolean);
begin
if opidx>=ops then
@ -184,7 +95,7 @@ implementation
with oper[opidx] do
begin
if typ=top_ref then
disposereference(ref);
dispose(ref);
b:=_b;
typ:=top_bool;
end;
@ -238,7 +149,7 @@ implementation
end;
constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
begin
inherited create(op);
ops:=2;
@ -283,7 +194,7 @@ implementation
loadsymbol(0,_op3,_op3ofs);
end;
constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; _op3: preference);
constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
begin
inherited create(op);
ops:=3;
@ -395,7 +306,7 @@ implementation
end;
constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
begin
inherited create(op);
ops:=2;
@ -426,7 +337,13 @@ implementation
end.
{
$Log$
Revision 1.4 2002-05-13 19:52:46 peter
Revision 1.5 2002-05-14 17:28:10 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.4 2002/05/13 19:52:46 peter
* a ppcppc can be build again
Revision 1.3 2001/12/29 15:28:58 jonas

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,7 @@ implementation
maybe_save(exprasmlist,right.registers32,left.location,saved);
secondpass(right);
maybe_restore(exprasmlist,left.location,saved);
set_location(location,left.location);
location_copy(location,left.location);
resultreg := R_NO;
{ put numerator in register }
@ -386,36 +386,8 @@ implementation
secondpass(left);
if is_64bitint(left.resulttype.def) then
begin
clear_location(location);
location.loc:=LOC_REGISTER;
case left.location.loc of
LOC_REGISTER, LOC_CREGISTER :
begin
src1 := left.location.registerlow;
src2 := left.location.registerhigh;
if left.location.loc = LOC_REGISTER then
begin
location.registerlow:=src1;
location.registerhigh:=src2;
end
else
begin
location.registerlow := rg.getregisterint(exprasmlist);
location.registerhigh := rg.getregisterint(exprasmlist);
end;
end;
LOC_REFERENCE,LOC_CREFERENCE :
begin
reference_release(exprasmlist,left.location.reference);
location.registerlow:=rg.getregisterint(exprasmlist);
src1 := location.registerlow;
location.registerhigh:=rg.getregisterint(exprasmlist);
src2 := location.registerhigh;
tcg64f32(cg).a_load64_ref_reg(exprasmlist,left.location.reference,
location.registerlow,
location.registerhigh);
end;
end;
location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
location_copy(location,left.location);
exprasmlist.concat(taicpu.op_reg_reg(A_NEG,location.registerlow,
src1));
cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_32,src2,location.registerhigh);
@ -546,36 +518,8 @@ implementation
else if is_64bitint(left.resulttype.def) then
begin
secondpass(left);
clear_location(location);
location.loc:=LOC_REGISTER;
{ make sure left is in a register and set the dest register }
case left.location.loc of
LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER:
begin
location.registerlow := rg.getregisterint(exprasmlist);
location.registerhigh := rg.getregisterint(exprasmlist);
if left.location.loc <> LOC_CREGISTER then
begin
tcg64f32(cg).a_load64_ref_reg(exprasmlist,
left.location.reference,location.registerlow,
location.registerhigh);
regl := location.registerlow;
regh := location.registerhigh;
end
else
begin
regl := left.location.registerlow;
regh := left.location.registerhigh;
end;
end;
LOC_REGISTER:
begin
regl := left.location.registerlow;
location.registerlow := regl;
regh := left.location.registerhigh;
location.registerhigh := regh;
end;
end;
location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
location_copy(location,left.location);
{ perform the NOT operation }
exprasmlist.concat(taicpu.op_reg_reg(A_NOT,location.registerhigh,
regh));
@ -585,32 +529,13 @@ implementation
else
begin
secondpass(left);
clear_location(location);
location.loc:=LOC_REGISTER;
{ make sure left is in a register and set the dest register }
case left.location.loc of
LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER:
begin
location.register := rg.getregisterint(exprasmlist);
if left.location.loc <> LOC_CREGISTER then
begin
cg.a_load_ref_reg(exprasmlist,
def_cgsize(left.resulttype.def),
left.location.reference,location.register);
regl := location.register;
end
else
regl := left.location.register;
end;
LOC_REGISTER:
regl := left.location.register;
end;
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 }
exprasmlist.concat(taicpu.op_reg_reg(A_NOT,location.register,
regl));
{ release the source reg if it wasn't reused }
if regl <> location.register then
rg.ungetregisterint(exprasmlist,regl);
left.location.register));
end;
end;
@ -622,7 +547,13 @@ begin
end.
{
$Log$
Revision 1.5 2002-05-13 19:52:46 peter
Revision 1.6 2002-05-14 17:28:10 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.5 2002/05/13 19:52:46 peter
* a ppcppc can be build again
Revision 1.4 2002/04/21 15:48:39 carl

View File

@ -716,7 +716,13 @@ begin
2 : size:=S_W{ could be S_IS};
4 : size:=S_L{ could be S_IL or S_FS};
8 : size:=S_IQ{ could be S_D or S_FL};
extended_size : size:=S_FX;
else
begin
{ extended_size can also be 8, resulting in a
duplicate label }
if _size=extended_size then
size:=S_FX;
end;
end;
end;
end;
@ -1585,7 +1591,13 @@ end;
end.
{
$Log$
Revision 1.31 2002-05-12 16:53:10 peter
Revision 1.32 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.31 2002/05/12 16:53:10 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function

View File

@ -26,36 +26,49 @@ Unit tainst;
interface
Uses aasm,cpubase,cpuinfo,cclasses;
Uses
cpuinfo,cpubase,aasm,cclasses;
Type
Type
tairegalloc = class(tai)
allocation : boolean;
reg : tregister;
constructor alloc(r : tregister);
constructor dealloc(r : tregister);
end;
tairegalloc = class(tai)
allocation : boolean;
reg : tregister;
constructor alloc(r : tregister);
constructor dealloc(r : tregister);
end;
tainstruction = class(tai)
condition : TAsmCond;
ops : longint;
oper : array[0..max_operands-1] of toper;
opcode : tasmop;
taicpu_abstract = class(tai)
condition : TAsmCond;
ops : longint;
oper : array[0..max_operands-1] of toper;
opcode : tasmop;
{$ifdef i386}
segprefix : tregister;
segprefix : tregister;
{$endif i386}
is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
Constructor Create(op : tasmop);
Destructor Destroy;override;
function getcopy:tlinkedlistitem;override;
procedure loadconst(opidx:longint;l:aword);
procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
procedure loadref(opidx:longint;const r:treference);
procedure loadreg(opidx:longint;r:tregister);
procedure loadoper(opidx:longint;o:toper);
procedure SetCondition(const c:TAsmCond);
end;
is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
Constructor Create(op : tasmop);
Destructor Destroy;override;
function getcopy:tlinkedlistitem;override;
procedure loadconst(opidx:longint;l:aword);
procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
procedure loadref(opidx:longint;const r:treference);
procedure loadreg(opidx:longint;r:tregister);
procedure loadoper(opidx:longint;o:toper);
procedure SetCondition(const c:TAsmCond);
end;
{ alignment for operator }
tai_align_abstract = class(tai)
buf : array[0..63] of char; { buf used for fill }
aligntype : byte; { 1 = no align, 2 = word align, 4 = dword align }
fillsize : byte; { real size to fill }
fillop : byte; { value to fill with - optional }
use_op : boolean;
constructor Create(b:byte);
constructor Create_op(b: byte; _op: byte);
function getfillbuf:pchar;virtual;
end;
implementation
@ -84,13 +97,12 @@ implementation
reg:=r;
end;
{ ---------------------------------------------------------------------
TaInstruction Constructor/Destructor
---------------------------------------------------------------------}
{*****************************************************************************
TaiInstruction
*****************************************************************************}
constructor Tainstruction.Create(op : tasmop);
constructor taicpu_abstract.Create(op : tasmop);
begin
inherited create;
@ -104,7 +116,7 @@ implementation
destructor Tainstruction.Destroy;
destructor taicpu_abstract.Destroy;
var
i : longint;
@ -127,7 +139,7 @@ implementation
procedure tainstruction.loadconst(opidx:longint;l:aword);
procedure taicpu_abstract.loadconst(opidx:longint;l:aword);
begin
if opidx>=ops then
ops:=opidx+1;
@ -142,7 +154,7 @@ implementation
procedure tainstruction.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
procedure taicpu_abstract.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
begin
if not assigned(s) then
internalerror(200204251);
@ -161,7 +173,7 @@ implementation
procedure tainstruction.loadref(opidx:longint;const r:treference);
procedure taicpu_abstract.loadref(opidx:longint;const r:treference);
begin
if opidx>=ops then
ops:=opidx+1;
@ -185,7 +197,7 @@ implementation
procedure tainstruction.loadreg(opidx:longint;r:tregister);
procedure taicpu_abstract.loadreg(opidx:longint;r:tregister);
begin
if opidx>=ops then
ops:=opidx+1;
@ -200,7 +212,7 @@ implementation
procedure tainstruction.loadoper(opidx:longint;o:toper);
procedure taicpu_abstract.loadoper(opidx:longint;o:toper);
begin
if opidx>=ops then
ops:=opidx+1;
@ -220,13 +232,13 @@ implementation
Miscellaneous methods.
---------------------------------------------------------------------}
procedure tainstruction.SetCondition(const c:TAsmCond);
procedure taicpu_abstract.SetCondition(const c:TAsmCond);
begin
condition:=c;
end;
Function tainstruction.getcopy:tlinkedlistitem;
Function taicpu_abstract.getcopy:tlinkedlistitem;
var
i : longint;
p : tlinkedlistitem;
@ -234,19 +246,63 @@ implementation
p:=inherited getcopy;
{ make a copy of the references }
for i:=1 to ops do
if (tainstruction(p).oper[i-1].typ=top_ref) then
if (taicpu_abstract(p).oper[i-1].typ=top_ref) then
begin
new(tainstruction(p).oper[i-1].ref);
tainstruction(p).oper[i-1].ref^:=oper[i-1].ref^;
new(taicpu_abstract(p).oper[i-1].ref);
taicpu_abstract(p).oper[i-1].ref^:=oper[i-1].ref^;
end;
getcopy:=p;
end;
{****************************************************************************
tai_align_abstract
****************************************************************************}
constructor tai_align_abstract.Create(b: byte);
begin
inherited Create;
typ:=ait_align;
if b in [1,2,4,8,16,32] then
aligntype := b
else
aligntype := 1;
fillsize:=0;
fillop:=0;
use_op:=false;
end;
constructor tai_align_abstract.Create_op(b: byte; _op: byte);
begin
inherited Create;
typ:=ait_align;
if b in [1,2,4,8,16,32] then
aligntype := b
else
aligntype := 1;
fillsize:=0;
fillop:=_op;
use_op:=true;
fillchar(buf,sizeof(buf),_op)
end;
function tai_align_abstract.getfillbuf:pchar;
begin
getfillbuf:=@buf;
end;
end.
{
$Log$
Revision 1.5 2002-04-25 20:16:39 peter
Revision 1.6 2002-05-14 17:28:09 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.5 2002/04/25 20:16:39 peter
* moved more routines from cga/n386util
Revision 1.4 2002/04/02 17:11:32 peter
@ -288,13 +344,13 @@ end.
because on powerpc it's a record now
Revision 1.3 1999/08/26 14:52:59 jonas
* added segprefix field for i386 in tainstruction object
* added segprefix field for i386 in taicpu_abstract object
Revision 1.2 1999/08/06 16:38:37 jonas
* declared getcopy virtual, since it's already declared as such
in cobjects.pas (FPC doesn't error on that, TP does)
Revision 1.1 1999/08/06 16:04:05 michael
+ introduced tainstruction
+ introduced taicpu_abstract
}

View File

@ -3,7 +3,7 @@
Copyright (c) 1998-2000 by Peter Vreman
This unit implements support import,export,link routines
for the (i386) Linux target
for the Linux targets
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
@ -64,7 +64,11 @@ implementation
cutils,cclasses,
verbose,systems,globtype,globals,
symconst,script,
fmodule,aasm,cpuasm,cpubase,symsym;
fmodule,symsym
{$ifdef i386}
,aasm,cpuasm,cpubase
{$endif i386}
;
{*****************************************************************************
TIMPORTLIBLINUX
@ -588,8 +592,23 @@ end;
res : res_none;
script : script_unix;
endian : endian_big;
stackalignment : 2;
maxCrecordalignment : 32;
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 : 128*1024;
stacksize : 32*1024*1024;
DllScanSupported:false;
@ -605,7 +624,6 @@ end;
shortname : 'linuxppc';
flags : [];
cpu : cpu_powerpc;
short_name : 'LINUX';
unit_env : '';
extradefines : 'UNIX';
sourceext : '.pp';
@ -633,13 +651,30 @@ end;
dirsep : '/';
files_case_relevent : true;
assem : as_powerpc_as;
assemsrc : as_powerpc_as;
ar : ar_powerpc_ar;
assemextern : as_powerpc_as;
link : ld_powerpc_linux;
linkextern : ld_powerpc_linux;
ar : ar_gnu_ar;
res : res_none;
script : script_unix;
endian : endian_big;
stackalignment : 8;
maxCrecordalignment : 32;
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 : 32*1024*1024;
DllScanSupported:false;
@ -690,9 +725,23 @@ end;
res : res_none;
script : script_unix;
endian : endian_little;
stackalignment : 8;
maxCrecordalignment : 32;
size_of_longint : 4;
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 : 32*1024*1024;
DllScanSupported:false;
@ -800,7 +849,13 @@ initialization
end.
{
$Log$
Revision 1.22 2002-05-06 19:46:36 carl
Revision 1.23 2002-05-14 17:28:10 peter
* synchronized cpubase between powerpc and i386
* moved more tables from cpubase to cpuasm
* tai_align_abstract moved to tainst, cpuasm must define
the tai_align class now, which may be empty
Revision 1.22 2002/05/06 19:46:36 carl
+ added more patches from Mazen for SPARC port
Revision 1.21 2002/04/22 18:19:22 carl