mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 22:48:57 +02:00
* 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:
parent
4a176c81bc
commit
f6b3e2e37f
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user