1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215 |
- MODULE PCAAMD64; (** AUTHOR "negelef"; PURPOSE "AMD64 assembler"; *)
- IMPORT
- SYSTEM, Modules, Commands, Streams, CompilerInterface, PCLIR, PCP, PCS, PCT, PCBT, PCM, Diagnostics,
- Texts, TextUtilities, Files, ASM := ASMAMD64, StringPool, Strings;
- CONST
- maxName = 128; (* maximum name length for labels and identifiers*)
- maxPasses = 2; (* two pass assembler *)
- binSuffix = ".Bin";
- (* scanner codes *)
- TAB = 09X;
- LF = 0AX;
- CR = 0DX;
- SPACE = 20X;
- (* symbol values *)
- symNone = 0;
- symIdent = 1;
- symLabel = 2;
- symNumber = 3;
- symSemicolon = 4;
- symColon = 5;
- symLn = 6;
- symComma = 7;
- symString = 8;
- symPlus = 9;
- symMinus = 10;
- symTimes = 11;
- symDiv = 12;
- symLParen = 13;
- symRParen = 14;
- symLBrace = 15;
- symRBrace = 16;
- symLBraket = 17;
- symRBraket = 18;
- symPC = 19;
- symPCOffset = 20;
- symNegate = 21;
- symComposite = 22;
- symMod = 23;
- symPeriod = 24;
- (* rex prefix bit positions *)
- rexB = 0;
- rexX = 1;
- rexR = 2;
- rexW= 3;
- rex = 4;
- rAX = 0;
- rCX = 1;
- rDX = 2;
- rBX = 3;
- rSP = 4;
- rBP = 5;
- rSI = 6;
- rDI = 7;
- r8 = 8;
- r9 = 9;
- r10 = 10;
- r11 = 11;
- r12 = 12;
- r13 = 13;
- r14 = 14;
- r15 = 15;
- rIP = 16;
- (* segment registers *)
- segES = 0;
- segCS = 1;
- segSS = 2;
- segDS = 3;
- segFS = 4;
- segGS = 5;
- regIP = 109;
- regRIP = 110;
- (* sizes *)
- default* = 0;
- size8 = 8;
- size16 = 16;
- size32 = 32;
- size64 = 64;
- size128 = 128;
- TYPE
- Name = ARRAY maxName OF CHAR;
- Size = LONGINT;
- Label = POINTER TO RECORD;
- name: Name;
- pc, pass: LONGINT;
- equ: BOOLEAN;
- next: Label;
- END;
- Operand* = OBJECT (PCLIR.InstructionAttribute)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- END Matches;
- END Operand;
- Reg* = OBJECT (Operand)
- VAR
- index-: LONGINT;
- PROCEDURE &New *(i: LONGINT);
- BEGIN index := i END New;
- END Reg;
- Reg8* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.reg8, ASM.regmem8:
- RETURN TRUE;
- | ASM.AL, ASM.rAX:
- RETURN index = rAX;
- | ASM.CL:
- RETURN index = rCX;
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END Reg8;
- MemReg = OBJECT (Reg)
- END MemReg;
- Reg16* = OBJECT (MemReg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.reg16, ASM.regmem16:
- RETURN TRUE;
- | ASM.AX, ASM.rAX:
- RETURN index = rAX;
- | ASM.DX:
- RETURN index = rDX;
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END Reg16;
- Reg32* = OBJECT (MemReg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.reg32, ASM.regmem32:
- RETURN TRUE;
- | ASM.EAX, ASM.rAX:
- RETURN index = rAX;
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END Reg32;
- Reg64* = OBJECT (MemReg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.reg64, ASM.regmem64:
- RETURN TRUE;
- | ASM.RAX, ASM.rAX:
- RETURN index = rAX;
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END Reg64;
- RegCR* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.CRn:
- RETURN TRUE;
- | ASM.CR8:
- RETURN index = 8;
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END RegCR;
- RegDR* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- RETURN type = ASM.DRn;
- END Matches;
- END RegDR;
- SegReg* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.segReg:
- RETURN TRUE;
- | ASM.ES:
- RETURN index = segES;
- | ASM.CS:
- RETURN index = segCS;
- | ASM.SS:
- RETURN index = segSS;
- | ASM.DS:
- RETURN index = segDS;
- | ASM.FS:
- RETURN index = segFS;
- | ASM.GS:
- RETURN index = segGS;
- ELSE
- RETURN FALSE;
- END
- END Matches;
- END SegReg;
- FPReg* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.sti:
- RETURN TRUE;
- | ASM.st0:
- RETURN index = 0;
- ELSE
- RETURN FALSE;
- END
- END Matches;
- END FPReg;
- MMXReg* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.mmx, ASM.mmxmem32, ASM.mmxmem64:
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END
- END Matches;
- END MMXReg;
- XMMReg* = OBJECT (Reg)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.xmm, ASM.xmmmem32, ASM.xmmmem64, ASM.xmmmem128:
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END
- END Matches;
- END XMMReg;
- Mem* = OBJECT (Operand)
- VAR
- size-: Size;
- seg, reg, index: Reg;
- scale, displacement: LONGINT;
- fixup: PCM.Attribute;
- PROCEDURE &New *(s: Size);
- BEGIN size := s; displacement := 0; scale := 1
- END New;
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- | ASM.mem:
- RETURN TRUE;
- | ASM.mem8:
- RETURN (size = default) OR (size = size8);
- | ASM.regmem8:
- RETURN ((size = default) OR (size = size8)) & ((reg = NIL) OR (reg IS MemReg));
- | ASM.mem16:
- RETURN (size = default) OR (size = size16);
- | ASM.regmem16:
- RETURN ((size = default) OR (size = size16)) & ((reg = NIL) OR (reg IS MemReg));
- | ASM.mem32:
- RETURN (size = default) OR (size = size32);
- | ASM.regmem32, ASM.mmxmem32, ASM.xmmmem32:
- RETURN ((size = default) OR (size = size32)) & ((reg = NIL) OR (reg IS MemReg));
- | ASM.mem64:
- RETURN (size = default) OR (size = size64);
- | ASM.regmem64, ASM.mmxmem64, ASM.xmmmem64:
- RETURN ((size = default) OR (size = size64)) & ((reg = NIL) OR (reg IS MemReg));
- | ASM.mem128:
- RETURN (size = default) OR (size = size128);
- | ASM.xmmmem128:
- RETURN ((size = default) OR (size = size128)) & ((reg = NIL) OR (reg IS MemReg));
- | ASM.moffset8:
- RETURN ((size = default) OR (size = size8)) & (reg = NIL);
- | ASM.moffset16:
- RETURN ((size = default) OR (size = size16)) & (reg = NIL);
- | ASM.moffset32:
- RETURN ((size = default) OR (size = size32)) & (reg = NIL);
- | ASM.moffset64:
- RETURN ((size = default) OR (size = size64)) & (reg = NIL);
- ELSE
- RETURN FALSE;
- END;
- END Matches;
- END Mem;
- Imm* = OBJECT (Operand)
- VAR
- size: Size;
- val-: HUGEINT;
- pc-: LONGINT;
- fixup: PCM.Attribute;
- PROCEDURE &New *(s: Size; v: HUGEINT);
- BEGIN size:= s; val := v; pc := -1
- END New;
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- CASE type OF
- ASM.one:
- RETURN val = 1
- | ASM.three:
- RETURN val = 3
- | ASM.rel8off:
- RETURN (size = default) OR (size = size8)
- | ASM.imm8:
- RETURN ((size = default) OR (size = size8)) & (val >= -80H) & (val < 100H)
- | ASM.simm8:
- RETURN ((size = default) OR (size = size8)) & (val >= -80H) & (val < 80H)
- | ASM.uimm8:
- RETURN ((size = default) OR (size = size8)) & (val >= 0H) & (val < 100H)
- | ASM.rel16off:
- RETURN (size = default) OR (size = size16)
- | ASM.imm16:
- RETURN ((size = default) OR (size = size16)) & (val >= -8000H) & (val < 10000H)
- | ASM.simm16:
- RETURN ((size = default) OR (size = size16)) & (val >= -8000H) & (val < 8000H)
- | ASM.uimm16:
- RETURN ((size = default) OR (size = size16)) & (val >= 0H) & (val < 10000H)
- | ASM.rel32off:
- RETURN (size = default) OR (size = size32)
- | ASM.imm32:
- RETURN ((size = default) OR (size = size32)) (* & & (val >= -80000000H) & (val < 100000000H) PACO confused? *)
- | ASM.simm32:
- RETURN ((size = default) OR (size = size32)) (* & & (val >= -80000000H) & (val < 80000000H) PACO confused? *)
- | ASM.uimm32:
- RETURN ((size = default) OR (size = size32)) & (val >= 0H) (* & (val < 100000000H) PACO confused? *)
- | ASM.imm64:
- RETURN (size = default) OR (size = size64)
- ELSE
- RETURN FALSE
- END
- END Matches;
- END Imm;
- Offset* = OBJECT (Imm)
- END Offset;
- Pntr1616 = OBJECT (Operand)
- VAR
- selector, offset: LONGINT;
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN RETURN type = ASM.pntr1616;
- END Matches;
- PROCEDURE &New *(s, o: LONGINT);
- BEGIN selector := s; offset := o
- END New;
- END Pntr1616;
- Pntr1632 = OBJECT (Pntr1616)
- PROCEDURE Matches (type: ASM.OperandType): BOOLEAN;
- BEGIN
- RETURN type = ASM.pntr1632;
- END Matches;
- END Pntr1632;
- Assembly* = OBJECT (PCLIR.AsmInline)
- VAR
- pc-, pcOffset, errPos*: LONGINT;
- current: PCLIR.AsmBlock;
- bits: Size;
- cpuoptions: ASM.CPUOptions;
- firstLabel: Label;
- diagnostics: Diagnostics.Diagnostics;
- listing: Streams.Writer;
- PROCEDURE &Init *(d: Diagnostics.Diagnostics; list: Streams.Writer);
- BEGIN
- NEW (code);
- Reset;
- current.len := 0;
- diagnostics := d;
- listing := list;
- END Init;
- PROCEDURE Reset*;
- BEGIN
- current := code;
- pc := 0;
- pcOffset := 0;
- bits := 64;
- cpuoptions := {ASM.cpu8086 .. ASM.cpuAMD64} + ASM.cpuOptions;
- END Reset;
- PROCEDURE SetPC* (newPC: LONGINT);
- BEGIN
- current := code;
- pc := newPC;
- pcOffset := 0;
- WHILE newPC - pcOffset > current.len DO
- INC (pcOffset, current.len);
- current := current.next;
- END;
- END SetPC;
- PROCEDURE AddFixup (adr: PCM.Attribute; offset: LONGINT);
- VAR asmFixup: PCLIR.AsmFixup;
- BEGIN
- NEW (asmFixup);
- asmFixup.offset := offset;
- asmFixup.adr := adr;
- asmFixup.next := fixup;
- fixup := asmFixup;
- END AddFixup;
- PROCEDURE PutByte* (b: LONGINT);
- BEGIN
- IF pc - pcOffset = LEN (current.code) THEN
- IF current.next = NIL THEN
- NEW (current.next);
- current.next.len := 0;
- END;
- INC (pcOffset, current.len);
- current := current.next;
- END;
- current.code[pc - pcOffset] := SYSTEM.VAL (CHAR, b);
- IF (current.len = pc - pcOffset) THEN INC (current.len) END;
- INC (pc);
- END PutByte;
- PROCEDURE GetByte* (): CHAR;
- BEGIN
- IF pc - pcOffset = current.len THEN
- INC (pcOffset, current.len);
- current := current.next;
- END;
- INC (pc);
- RETURN current.code[pc - pcOffset - 1];
- END GetByte;
- PROCEDURE GetWord* (): INTEGER;
- VAR word: INTEGER;
- BEGIN
- word := ORD (GetByte ());
- INC (word, ORD (GetByte ()) * 100H);
- RETURN word;
- END GetWord;
- PROCEDURE GetDWord* (): LONGINT;
- VAR dword, byte: LONGINT;
- BEGIN
- dword := ORD (GetByte ());
- INC (dword, LONG (ORD (GetByte ())) * 100H);
- INC (dword, LONG (ORD (GetByte ())) * 10000H);
- byte := LONG (ORD (GetByte ()));
- IF byte >= 128 THEN DEC (byte, 256) END;
- RETURN dword + byte * 1000000H;
- END GetDWord;
- PROCEDURE PutWord* (w: LONGINT);
- BEGIN
- PutByte (w MOD 100H);
- PutByte ((w DIV 100H) MOD 100H);
- END PutWord;
- PROCEDURE PutDWord* (d: LONGINT);
- BEGIN
- PutByte (d MOD 100H);
- PutByte ((d DIV 100H) MOD 100H);
- PutByte ((d DIV 10000H) MOD 100H);
- PutByte ((d DIV 1000000H) MOD 100H);
- END PutDWord;
- PROCEDURE PutQWord* (q: HUGEINT);
- VAR d: LONGINT;
- BEGIN
- SYSTEM.GET (ADDRESSOF (q), d);
- PutDWord (d);
- SYSTEM.GET (ADDRESSOF (q) + 4, d);
- PutDWord (d);
- END PutQWord;
- PROCEDURE Put (data: LONGINT; size: Size);
- BEGIN
- CASE size OF
- size8: PutByte (data);
- | size16: PutWord (data);
- | size32: PutDWord (data);
- END
- END Put;
- PROCEDURE InsertLabel (CONST name: ARRAY OF CHAR): Label;
- VAR label: Label;
- BEGIN
- label := GetLabel (name);
- IF label = NIL THEN
- NEW (label);
- COPY (name, label.name);
- label.next := firstLabel;
- label.pass := -1;
- label.equ := FALSE;
- firstLabel := label;
- END;
- RETURN label;
- END InsertLabel;
- PROCEDURE GetLabel (CONST name: ARRAY OF CHAR): Label;
- VAR label: Label;
- BEGIN
- label := firstLabel;
- WHILE (label # NIL) & (label.name # name) DO label := label.next END;
- RETURN label;
- END GetLabel;
- PROCEDURE Assemble (scan: PCS.Scanner; scope: PCT.Scope; exported, inlined, inlineAssembly: BOOLEAN);
- VAR
- scanner: PCS.Scanner;
- symbol, reg: LONGINT;
- ident, idents: Name;
- val, times, val2, val3: LONGINT;
- currentLabel: Label;
- prevPC: LONGINT;
- pass: LONGINT;
- absoluteMode: BOOLEAN;
- absoluteOffset: LONGINT;
- orgOffset: LONGINT;
- PROCEDURE NextChar;
- BEGIN IF (listing # NIL) & (pass = maxPasses) THEN listing.Char (scanner.ch) END; scanner.NextChar
- END NextChar;
- PROCEDURE SkipBlanks;
- BEGIN
- (* tf returns 01X when an embedded object is encountered *)
- WHILE (scanner.ch = SPACE) OR (scanner.ch = TAB) OR (scanner.ch = 01X) DO NextChar END;
- IF scanner.ch = ";" THEN
- WHILE (scanner.ch # CR) & (scanner.ch # LF) DO NextChar END (* Skip comments *)
- END;
- END SkipBlanks;
- PROCEDURE GetNumber (VAR intval: LONGINT);
- VAR i, m, n: INTEGER; dig: ARRAY 24 OF CHAR;
- BEGIN
- i := 0; m := 0; n := 0;
- WHILE ('0' <= scanner.ch) & (scanner.ch <= '9') OR ('A' <= CAP (scanner.ch)) & (CAP (scanner.ch) <= 'F') DO
- IF (m > 0) OR (scanner.ch # "0") THEN (* ignore leading zeros *)
- IF n < LEN(dig) THEN dig[n] := scanner.ch; INC(n) END;
- INC(m)
- END;
- NextChar; INC(i)
- END;
- IF n = m THEN intval := 0; i := 0;
- IF CAP (scanner.ch) = "H" THEN NextChar;
- IF (n = PCM.MaxHDig) & (dig[0] > "7") THEN (* prevent overflow *) intval := -1 END;
- WHILE i < n DO intval := intval * 10H + HexOrd (dig[i]); INC(i) END;
- ELSE
- IF (n = PCM.MaxHDig) & (dig[0] > "7") THEN (* prevent overflow *) intval := -1 END;
- WHILE i < n DO intval := intval * 10 + Ord (dig[i]); INC(i) END
- END
- END;
- END GetNumber;
- PROCEDURE GetIdentifier;
- VAR i: LONGINT;
- BEGIN
- i := 0;
- REPEAT
- IF i < maxName - 1 THEN
- IF ('0' <= scanner.ch) & (scanner.ch <= '9') THEN
- ident[i] := scanner.ch; idents[i] := scanner.ch;
- ELSE
- ident[i] := CAP (scanner.ch); idents[i] := scanner.ch; END;
- INC (i);
- END;
- NextChar
- UNTIL ~((('A' <= CAP(scanner.ch)) & (CAP(scanner.ch) <= 'Z')) OR (('0' <= scanner.ch) & (scanner.ch <= '9')));
- ident[i] := 0X; idents[i] := 0X;
- END GetIdentifier;
- PROCEDURE GetString;
- VAR i: LONGINT;
- BEGIN
- i := 0;
- NextChar;
- WHILE (scanner.ch # "'") & (i < maxName - 1) DO
- ident[i] := scanner.ch; INC (i);
- NextChar;
- END;
- ident[i] := 0X;
- NextChar;
- END GetString;
- PROCEDURE NextSymbol;
- BEGIN
- SkipBlanks;
- errPos := scanner.curpos - 1;
- CASE scanner.ch OF
- 'A' .. 'Z', 'a' .. 'z' :
- GetIdentifier;
- SkipBlanks;
- IF scanner.ch = ':' THEN
- NextChar; symbol := symLabel;
- ELSE
- symbol := symIdent;
- END;
- | '0' .. '9':
- GetNumber (val);
- symbol := symNumber;
- | "'": GetString;
- symbol := symString;
- | '.': symbol := symPeriod;
- NextChar;
- | ';': symbol := symSemicolon;
- NextChar;
- | ':': symbol := symColon;
- NextChar;
- | CR, LF: symbol := symLn;
- NextChar;
- | ',': symbol := symComma;
- NextChar;
- | '+': symbol := symPlus;
- NextChar;
- | '-': symbol := symMinus;
- NextChar;
- | '*': symbol := symTimes;
- NextChar;
- | '/': symbol := symDiv;
- NextChar;
- | '%': symbol := symMod;
- NextChar;
- | '~': symbol := symNegate;
- NextChar;
- | '(': symbol := symLParen;
- NextChar;
- | ')': symbol := symRParen;
- NextChar;
- | '[': symbol := symLBraket;
- NextChar;
- | ']': symbol := symRBraket;
- NextChar;
- | '{': symbol := symLBrace;
- NextChar;
- | '}': symbol := symRBrace;
- NextChar;
- | '$': NextChar;
- IF scanner.ch = '$' THEN
- symbol := symPCOffset; NextChar;
- ELSE
- symbol := symPC;
- END
- ELSE
- symbol := symNone;
- NextChar;
- END;
- END NextSymbol;
- PROCEDURE SkipLine;
- BEGIN
- WHILE (symbol # symLn) & (symbol # symNone) DO
- NextSymbol;
- END;
- END SkipLine;
- PROCEDURE Ensure (desiredSymbol, errNumber : LONGINT) : BOOLEAN;
- BEGIN
- IF symbol = desiredSymbol THEN
- NextSymbol;
- RETURN TRUE;
- ELSE
- PCM.Error (errNumber, errPos, "");
- RETURN FALSE;
- END;
- END Ensure;
- PROCEDURE SetBits (newBits: LONGINT): BOOLEAN;
- BEGIN
- CASE newBits OF
- 16: bits := size16;
- | 32: bits := size32;
- | 64: bits := size64;
- ELSE
- PCM.Error (553, errPos, ""); RETURN FALSE;
- END;
- RETURN TRUE;
- END SetBits;
- PROCEDURE GetCPU (cumulateOptions: BOOLEAN): BOOLEAN;
- VAR i: LONGINT;
- BEGIN
- SkipBlanks;
- GetIdentifier;
- i := ASM.FindCPU (ident);
- IF i # ASM.none THEN
- IF cumulateOptions THEN
- cpuoptions := cpuoptions + ASM.cpus[i].cpuoptions;
- ELSE
- cpuoptions := ASM.cpus[i].cpuoptions + ASM.cpuOptions;
- END;
- NextSymbol;
- RETURN TRUE;
- ELSE
- PCM.Error (552, errPos, ident);
- RETURN FALSE;
- END;
- END GetCPU;
- PROCEDURE GetScopeSymbol (ident: ARRAY OF CHAR): PCT.Symbol;
- VAR idx: LONGINT;
- BEGIN
- StringPool.GetIndex(ident, idx);
- RETURN PCT.Find (scope, scope, idx, PCT.procdeclared, TRUE);
- END GetScopeSymbol;
- PROCEDURE Factor (VAR x: LONGINT; critical: BOOLEAN): BOOLEAN;
- VAR label: Label; scopeSymbol: PCT.Symbol; l: LONGINT;
- BEGIN
- IF symbol = symNumber THEN
- x := val; NextSymbol; RETURN TRUE;
- ELSIF symbol = symPC THEN
- x := orgOffset + pc; NextSymbol; RETURN TRUE;
- ELSIF symbol = symPCOffset THEN
- x := orgOffset; NextSymbol; RETURN TRUE;
- ELSIF symbol = symString THEN
- x := 0; l := Strings.Length (ident);
- IF l > 0 THEN INC (x, ORD (ident [0])) END;
- IF l > 1 THEN INC (x, ORD (ident [1])*100H) END;
- IF l > 2 THEN INC (x, ORD (ident [2])*10000H) END;
- IF l > 3 THEN INC (x, ORD (ident [3])*1000000H) END;
- NextSymbol; RETURN TRUE;
- ELSIF symbol = symIdent THEN
- label := GetLabel (ident); NextSymbol;
- IF label # NIL THEN
- IF label.equ THEN
- x := label.pc;
- ELSE
- x := orgOffset + label.pc;
- END;
- RETURN TRUE;
- ELSIF inlineAssembly THEN
- scopeSymbol := GetScopeSymbol (idents);
- IF scopeSymbol # NIL THEN
- IF scopeSymbol IS PCT.Value THEN
- IF scopeSymbol.type = PCT.Char8 THEN
- x := scopeSymbol(PCT.Value).const.int
- ELSIF PCT.IsCardinalType(scopeSymbol.type) THEN
- x := scopeSymbol(PCT.Value).const.int
- ELSE
- PCM.Error(51, errPos, "");
- RETURN FALSE;
- END;
- RETURN TRUE;
- ELSIF pass = maxPasses THEN
- PCM.Error (560, errPos, idents);
- RETURN FALSE;
- END;
- END
- END;
- IF (~critical) & (pass # maxPasses) THEN
- x := 0;
- RETURN TRUE
- END;
- PCM.Error (554, errPos, idents);
- RETURN FALSE;
- ELSIF symbol = symLParen THEN
- NextSymbol;
- RETURN Expression (x, critical) & Ensure (symRParen, 555);
- END;
- PCM.Error (555, errPos, "");
- RETURN FALSE
- END Factor;
- PROCEDURE Term (VAR x: LONGINT; critical: BOOLEAN): BOOLEAN;
- VAR y, op : LONGINT;
- BEGIN
- IF Factor (x, critical) THEN
- WHILE (symbol = symTimes) OR (symbol = symDiv) OR (symbol = symMod) DO
- op := symbol; NextSymbol;
- IF Factor (y, critical) THEN
- IF op = symTimes THEN x := x * y
- ELSIF op = symDiv THEN x := x DIV y
- ELSE x := x MOD y
- END;
- ELSE
- RETURN FALSE;
- END;
- END;
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END;
- END Term;
- PROCEDURE Expression (VAR x: LONGINT; critical: BOOLEAN): BOOLEAN;
- VAR y, op : LONGINT;
- BEGIN
- IF symbol = symMinus THEN
- op := symbol; NextSymbol;
- IF Term (x, critical) THEN
- x := -x
- ELSE
- RETURN FALSE;
- END;
- ELSIF symbol = symPlus THEN
- op := symbol; NextSymbol;
- IF ~Term (x, critical) THEN
- RETURN FALSE;
- END;
- ELSIF symbol = symNegate THEN
- op := symbol; NextSymbol;
- IF Term (x, critical) THEN
- x := -x - 1
- ELSE
- RETURN FALSE;
- END;
- ELSIF ~Term (x, critical) THEN
- RETURN FALSE;
- END;
- WHILE (symbol = symPlus) OR (symbol = symMinus) DO
- op := symbol; NextSymbol;
- IF Term (y, critical) THEN
- IF op = symPlus THEN x := x + y ELSE x := x - y END;
- ELSE
- RETURN FALSE;
- END;
- END;
- RETURN TRUE;
- END Expression;
- PROCEDURE PutData (size: Size): BOOLEAN;
- VAR i: LONGINT;
- BEGIN
- NextSymbol;
- WHILE symbol # symLn DO
- IF symbol = symString THEN
- i := 0;
- WHILE ident[i] # 0X DO
- PutByte (ORD (ident[i]));
- INC (i);
- END;
- IF size # size8 THEN
- i := (size DIV 8) - i MOD (size DIV 8);
- WHILE i # 0 DO PutByte (0); DEC (i) END;
- END;
- NextSymbol;
- ELSIF Expression (i, FALSE) THEN
- Put (i, size);
- ELSE
- RETURN FALSE;
- END;
- IF symbol = symComma THEN
- NextSymbol;
- ELSIF symbol # symLn THEN
- PCM.Error(511, errPos, "");
- END
- END;
- Duplicate (pc - prevPC, NIL);
- RETURN TRUE;
- END PutData;
- PROCEDURE Duplicate (size: LONGINT; fixup: PCLIR.AsmFixup);
- VAR i: LONGINT; buffer: ARRAY 100 OF CHAR;
- BEGIN
- IF times = 1 THEN RETURN END;
- SetPC (prevPC);
- IF times > 0 THEN
- IF (listing # NIL) & (pass = maxPasses) THEN listing.Hex (pc, 0); listing.Char (' ') END;
- FOR i := 0 TO size - 1 DO
- buffer[i] := GetByte ();
- IF (listing # NIL) & (pass = maxPasses) THEN listing.Hex (ORD (buffer[i]), -2); END;
- END;
- WHILE times # 1 DO
- IF fixup # NIL THEN
- AddFixup (fixup.adr, pc + fixup.offset - prevPC);
- END;
- FOR i := 0 TO size - 1 DO
- PutByte (ORD (buffer[i]));
- IF (listing # NIL) & (pass = maxPasses) THEN listing.Hex (ORD (buffer[i]), -2); END;
- END;
- DEC (times);
- END;
- ELSE
- times := 1;
- END;
- IF (listing # NIL) & (pass = maxPasses) THEN listing.Ln END;
- END Duplicate;
- PROCEDURE Reserve (size: Size) : BOOLEAN;
- BEGIN
- IF Expression (val2, TRUE) THEN
- absoluteOffset := absoluteOffset + val * size;
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END;
- END Reserve;
- PROCEDURE GetMemFixup (CONST ident: ARRAY OF CHAR; VAR mem: Mem);
- VAR scopeSymbol: PCT.Symbol;
- BEGIN
- scopeSymbol := GetScopeSymbol (ident);
- IF scopeSymbol = NIL THEN RETURN END;
- IF (scopeSymbol IS PCT.GlobalVar) THEN
- RETURN;
- IF ~inlined OR ~exported THEN
- mem.displacement := scopeSymbol.adr(PCBT.GlobalVariable).offset;
- END;
- ELSIF scopeSymbol IS PCT.Parameter THEN
- mem.displacement := scopeSymbol.adr(PCBT.Variable).offset;
- ELSIF scopeSymbol IS PCT.Variable THEN
- mem.displacement := scopeSymbol.adr(PCBT.Variable).offset;
- ELSE
- RETURN;
- END;
- mem.fixup := scopeSymbol.adr;
- NextSymbol;
- END GetMemFixup;
- PROCEDURE GetOffsetFixup (CONST ident: ARRAY OF CHAR; VAR offset: Offset);
- VAR scopeSymbol: PCT.Symbol;
- BEGIN
- scopeSymbol := GetScopeSymbol (ident);
- IF scopeSymbol = NIL THEN RETURN END;
- IF (scopeSymbol IS PCT.GlobalVar) THEN
- IF ~inlined OR ~exported THEN
- offset.val := scopeSymbol.adr(PCBT.GlobalVariable).offset;
- ELSE
- RETURN;
- END;
- ELSIF (scopeSymbol IS PCT.Proc) THEN
- IF ~inlined OR ~exported THEN
- offset.val := scopeSymbol.adr(PCBT.Procedure).codeoffset;
- ELSE
- RETURN;
- END;
- ELSE
- RETURN;
- END;
- offset.size := size64;
- offset.fixup := scopeSymbol.adr;
- END GetOffsetFixup;
- PROCEDURE GetInstruction (): BOOLEAN;
- VAR
- mnem, opCount: LONGINT;
- size: Size;
- operands: ARRAY ASM.maxOperands OF Operand;
- prevFixup: PCLIR.AsmFixup;
- mem: Mem;
- offset: Offset;
- BEGIN
- mnem := ASM.FindMnem (ident);
- IF mnem = ASM.none THEN
- PCM.Error (554, errPos, idents);
- RETURN FALSE;
- END;
- opCount := 0;
- NextSymbol;
- WHILE (symbol # symLn) & (symbol # symNone) DO
- IF symbol = symIdent THEN
- IF (ident = "BYTE") OR (ident = "SHORT") THEN
- size := size8; NextSymbol;
- ELSIF (ident = "WORD") OR (ident = "NEAR") THEN
- size := size16; NextSymbol;
- ELSIF ident = "DWORD" THEN
- size := size32; NextSymbol;
- ELSIF ident = "QWORD" THEN
- size := size64; NextSymbol;
- ELSIF ident = "TWORD" THEN
- size := size128; NextSymbol;
- ELSE
- size := default;
- END;
- ELSE
- size := default;
- END;
- IF symbol = symIdent THEN
- reg := ASM.FindReg (ident);
- IF reg # ASM.none THEN
- IF size # default THEN
- PCM.Error (562, errPos, ""); RETURN FALSE;
- END;
- operands[opCount] := NewReg (ASM.registers[reg].type, ASM.registers[reg].index);
- INC (opCount);
- NextSymbol;
- END;
- ELSE
- reg := ASM.none;
- END;
- IF reg = ASM.none THEN
- IF symbol = symLBraket THEN
- NextSymbol;
- NEW (mem, size);
- operands[opCount] := mem;
- INC (opCount);
- IF symbol = symLabel THEN
- reg := ASM.FindReg (ident);
- IF reg = ASM.none THEN
- PCM.Error (554, errPos, idents); RETURN FALSE;
- END;
- mem.seg := NewReg (ASM.registers[reg].type, ASM.registers[reg].index);
- NextSymbol;
- END;
- IF symbol = symIdent THEN
- reg := ASM.FindReg (ident);
- IF reg # ASM.none THEN
- mem.reg := NewReg (ASM.registers[reg].type, ASM.registers[reg].index);
- NextSymbol;
- IF symbol = symTimes THEN
- NextSymbol;
- IF ~Factor (mem.scale, FALSE) THEN
- RETURN FALSE;
- END;
- mem.index := mem.reg;
- mem.reg := NIL;
- END;
- IF symbol = symPlus THEN
- NextSymbol;
- IF symbol = symIdent THEN
- reg := ASM.FindReg (ident);
- IF reg # ASM.none THEN
- NextSymbol;
- IF mem.index = NIL THEN
- mem.index := NewReg (ASM.registers[reg].type, ASM.registers[reg].index);
- IF symbol = symTimes THEN
- NextSymbol;
- IF ~Factor (mem.scale, FALSE) THEN
- RETURN FALSE;
- END;
- END;
- ELSE
- mem.reg := NewReg (ASM.registers[reg].type, ASM.registers[reg].index);
- END;
- END;
- END;
- END;
- END;
- END;
- IF symbol = symPlus THEN
- NextSymbol;
- END;
- IF inlineAssembly & (symbol = symIdent) THEN
- GetMemFixup (idents, mem);
- END;
- IF (symbol # symRBraket) & (symbol # symNegate) THEN
- val2 := 0;
- IF ~Expression (val2, FALSE) THEN
- RETURN FALSE;
- END;
- INC (mem.displacement, val2);
- ELSIF (mem.reg = NIL) & (mem.index = NIL) THEN
- PCM.Error (511, errPos, ""); RETURN FALSE;
- END;
- IF ~Ensure (symRBraket, 556) THEN
- RETURN FALSE;
- END;
- ELSE
- offset := NewOffset (size, val2);
- IF inlineAssembly & (symbol = symIdent) THEN
- GetOffsetFixup (idents, offset);
- END;
- IF offset.fixup = NIL THEN
- IF ~Expression (val2, FALSE) THEN
- RETURN FALSE;
- END;
- offset.val := val2;
- IF symbol = symColon THEN
- NextSymbol;
- IF ~Expression (val3, FALSE) THEN
- RETURN FALSE;
- END;
- operands[opCount] := NewOffset (default, val3);
- INC (opCount);
- END;
- ELSE
- NextSymbol;
- END;
- operands[opCount] := offset;
- INC (opCount);
- END;
- END;
- IF symbol = symComma THEN
- NextSymbol;
- ELSIF symbol # symLn THEN
- PCM.Error(511, errPos, "");
- END
- END;
- prevFixup := fixup;
- IF ~EmitInstr (mnem, operands, pass = maxPasses) THEN
- RETURN FALSE;
- END;
- IF fixup = prevFixup THEN
- Duplicate (pc - prevPC, NIL);
- ELSE
- Duplicate (pc - prevPC, fixup);
- END;
- RETURN TRUE;
- END GetInstruction;
- BEGIN
- FOR pass := 1 TO maxPasses DO
- scanner := PCS.ForkScanner (scan);
- Reset;
- times := 1;
- prevPC := pc;
- currentLabel := NIL;
- absoluteMode := FALSE;
- orgOffset := 0;
- NextSymbol;
- IF inlineAssembly THEN
- cpuoptions := {};
- IF ~Ensure (symLBrace, 550) THEN
- RETURN
- END;
- LOOP
- IF ~Ensure (symIdent, 551) THEN
- RETURN
- END;
- IF ident # "SYSTEM" THEN
- PCM.Error (552, errPos, ident); RETURN
- END;
- IF symbol # symPeriod THEN
- PCM.Error (551, errPos, ""); RETURN;
- END;
- IF ~GetCPU (TRUE) THEN
- RETURN;
- END;
- IF symbol = symRBrace THEN
- EXIT
- ELSIF symbol = symComma THEN
- NextSymbol
- ELSE
- PCM.Error (550, errPos, ident); RETURN;
- END;
- END;
- NextSymbol;
- END;
- LOOP
- IF (listing # NIL) & (pass = maxPasses) THEN listing.Char (9X); listing.Char (9X) END;
- IF symbol = symLn THEN
- NextSymbol;
- ELSIF symbol = symLabel THEN
- currentLabel := InsertLabel (ident);
- IF absoluteMode THEN
- currentLabel.pc := absoluteOffset;
- ELSE
- currentLabel.pc := pc;
- END;
- IF currentLabel.pass < pass THEN
- currentLabel.pass := pass;
- ELSE
- PCM.Error (1, errPos, ident);
- END;
- NextSymbol;
- ELSIF symbol = symIdent THEN
- IF ident = "END" THEN
- symbol := symNone;
- ELSIF ~inlineAssembly & (ident = "BITS") THEN
- NextSymbol;
- IF ~Ensure (symNumber, 553) OR ~SetBits (val) THEN
- SkipLine;
- ELSE
- NextSymbol;
- END;
- ELSIF ~inlineAssembly & (ident = "CPU") THEN
- IF ~GetCPU (FALSE) THEN
- SkipLine;
- END;
- ELSIF ~inlineAssembly & (ident = "ABSOLUTE") THEN
- absoluteMode := TRUE;
- NextSymbol;
- IF ~Expression (absoluteOffset, TRUE) THEN
- SkipLine;
- END;
- ELSIF ~inlineAssembly & (ident = "ORG") THEN
- NextSymbol;
- IF (orgOffset # 0) OR ~Expression (orgOffset, TRUE) THEN
- SkipLine;
- END;
- ELSIF ~inlineAssembly & (ident = "RESB") THEN
- NextSymbol;
- IF ~Reserve (1) THEN SkipLine END;
- ELSIF ~inlineAssembly & (ident = "RESW") THEN
- NextSymbol;
- IF ~Reserve (2) THEN SkipLine END;
- ELSIF ~inlineAssembly & (ident = "RESD") THEN
- NextSymbol;
- IF ~Reserve (4) THEN SkipLine END;
- ELSIF ident = "EQU" THEN
- IF currentLabel # NIL THEN
- NextSymbol;
- IF Expression (val2, FALSE) THEN
- currentLabel.pc := val2;
- currentLabel.equ := TRUE;
- ELSE
- SkipLine;
- END;
- ELSE
- PCM.Error (520, errPos, ""); RETURN;
- END;
- ELSIF ident = "TIMES" THEN
- NextSymbol;
- IF ~Expression (times, TRUE) THEN
- SkipLine;
- ELSIF times < 0 THEN
- PCM.Error (561, errPos, ""); RETURN;
- ELSE
- prevPC := pc;
- END;
- ELSIF ident = "DB" THEN
- IF ~PutData (size8) THEN SkipLine END;
- ELSIF ident = "DW" THEN
- IF ~PutData (size16) THEN SkipLine END;
- ELSIF ident = "DD" THEN
- IF ~PutData (size32) THEN SkipLine END;
- ELSIF ident = "REP" THEN
- NextSymbol;
- PutByte (ASM.prfREP);
- ELSIF ident = "LOCK" THEN
- NextSymbol;
- PutByte (ASM.prfLOCK);
- ELSIF ident = "REPE" THEN
- NextSymbol;
- PutByte (ASM.prfREPE);
- ELSIF ident = "REPZ" THEN
- NextSymbol;
- PutByte (ASM.prfREPZ);
- ELSIF ident = "REPNE" THEN
- NextSymbol;
- PutByte (ASM.prfREPNE);
- ELSIF ident = "REPNZ" THEN
- NextSymbol;
- PutByte (ASM.prfREPNZ);
- ELSIF ~GetInstruction () THEN
- SkipLine
- END;
- currentLabel := NIL;
- ELSIF symbol = symNone THEN
- EXIT
- ELSE
- PCM.Error (551, errPos, "");
- RETURN;
- END;
- END;
- END;
- END Assemble;
- PROCEDURE EmitPrefix* (prefix: LONGINT);
- BEGIN PutByte (prefix);
- END EmitPrefix;
- PROCEDURE Emit* (mnem: LONGINT; op1, op2, op3: Operand);
- VAR operands: ARRAY ASM.maxOperands OF Operand; res: BOOLEAN;
- BEGIN
- operands[0] := op1;
- operands[1] := op2;
- operands[2] := op3;
- res := EmitInstr (mnem, operands, TRUE);
- END Emit;
- PROCEDURE EmitInstr (mnem: LONGINT; operands: ARRAY OF Operand; lastPass: BOOLEAN): BOOLEAN;
- VAR instr, i, oppos, op: LONGINT;
- val: LONGINT;
- regOperand: LONGINT;
- addressOperand: LONGINT;
- regField, modField, rmField: LONGINT;
- scaleField, indexField, baseField: LONGINT;
- free: ARRAY ASM.maxOperands OF BOOLEAN;
- byte: LONGINT;
- offset: LONGINT;
- mem: Mem;
- lastPC: LONGINT;
- opPrefix, adrPrefix: BOOLEAN;
- segPrefix: LONGINT; rexPrefix: SET;
- PROCEDURE MatchesInstruction (): BOOLEAN;
- BEGIN
- FOR i := 0 TO ASM.maxOperands - 1 DO
- IF operands[i] = NIL THEN
- IF ASM.instructions[instr].operands[i] # ASM.none THEN RETURN FALSE END;
- ELSIF ~operands[i].Matches (ASM.instructions[instr].operands[i]) THEN
- RETURN FALSE
- ELSIF (bits = size64) & (ASM.optI64 IN ASM.instructions[instr].options) THEN
- RETURN FALSE;
- END;
- END;
- RETURN TRUE;
- END MatchesInstruction;
- PROCEDURE GetRegOperand (): LONGINT;
- VAR i: LONGINT;
- BEGIN
- FOR i := 0 TO ASM.maxOperands -1 DO
- CASE ASM.instructions[instr].operands[i] OF
- ASM.reg8, ASM.reg16, ASM.reg32, ASM.reg64, ASM.xmm, ASM.mmx:
- RETURN i;
- ELSE
- END;
- END;
- RETURN ASM.none;
- END GetRegOperand;
- PROCEDURE GetAddressOperand (): LONGINT;
- VAR i: LONGINT;
- BEGIN
- FOR i := 0 TO ASM.maxOperands -1 DO
- CASE ASM.instructions[instr].operands[i] OF
- ASM.mem,
- ASM.mem8, ASM.mem16, ASM.mem32, ASM.mem64, ASM.mem128,
- ASM.regmem8, ASM.regmem16, ASM.regmem32, ASM.regmem64,
- ASM.mmxmem32, ASM.mmxmem64,
- ASM.xmmmem32, ASM.xmmmem64, ASM.xmmmem128:
- RETURN i;
- ELSE
- END;
- END;
- RETURN ASM.none;
- END GetAddressOperand;
- PROCEDURE GetSpecialOperand (): LONGINT;
- VAR i: LONGINT;
- BEGIN
- FOR i := 0 TO ASM.maxOperands -1 DO
- CASE ASM.instructions[instr].operands[i] OF
- ASM.segReg, ASM.mmx, ASM.xmm, ASM.CRn, ASM.DRn:
- RETURN i;
- ELSE
- END;
- END;
- RETURN ASM.none;
- END GetSpecialOperand;
- PROCEDURE ModRM (mod, reg, rm: LONGINT);
- BEGIN PutByte (mod MOD 4 * 40H + reg MOD 8 * 8H + rm MOD 8);
- END ModRM;
- PROCEDURE SIB (scale, index, base: LONGINT);
- BEGIN PutByte (scale MOD 4 * 40H + index MOD 8 * 8H + base MOD 8);
- END SIB;
- BEGIN
- instr := ASM.mnemonics[mnem].firstInstr;
- WHILE (~MatchesInstruction ()) & (instr # ASM.mnemonics[mnem].lastInstr) DO INC (instr); END;
- IF instr = ASM.mnemonics[mnem].lastInstr THEN
- PCM.Error (557, errPos, ASM.mnemonics[mnem].name); RETURN FALSE;
- ELSIF ASM.instructions[instr].cpuoptions * cpuoptions # ASM.instructions[instr].cpuoptions THEN
- PCM.Error (558, errPos, ASM.mnemonics[mnem].name); RETURN FALSE;
- END;
- oppos := 0;
- val := -1;
- lastPC := pc;
- opPrefix := FALSE;
- adrPrefix := FALSE;
- segPrefix := ASM.none;
- rexPrefix := {};
- IF (ASM.optO16 IN ASM.instructions[instr].options) & (bits # size16) THEN
- opPrefix := TRUE;
- END;
- IF (ASM.optO32 IN ASM.instructions[instr].options) & (bits = size16) THEN
- opPrefix := TRUE;
- END;
- IF (ASM.optO64 IN ASM.instructions[instr].options) & (bits = size64) THEN
- INCL (rexPrefix, rexW)
- END;
- IF ASM.optPOP IN ASM.instructions[instr].options THEN
- opPrefix := TRUE;
- END;
- regOperand := GetSpecialOperand ();
- addressOperand := GetAddressOperand ();
- IF regOperand = ASM.none THEN
- regOperand := GetRegOperand ();
- END;
- IF addressOperand = ASM.none THEN
- addressOperand := GetRegOperand();
- END;
- (* KernelLog.String (ASM.mnemonics[mnem].name); KernelLog.Int (regOperand, 10); KernelLog.Int (addressOperand, 10); KernelLog.Ln; *)
- FOR i := 0 TO ASM.maxOperands - 1 DO
- IF operands[i] # NIL THEN
- IF operands[i] IS Mem THEN
- mem := operands[i](Mem);
- IF mem.seg # NIL THEN
- segPrefix := mem.seg.index;
- END;
- IF mem.reg # NIL THEN
- IF (mem.reg.index >= 8) THEN
- INCL (rexPrefix, rexB)
- END;
- IF (mem.reg IS Reg32) & (bits # size32) THEN
- adrPrefix := TRUE;
- END;
- IF mem.reg IS Reg16 THEN
- IF bits = size64 THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- ELSIF bits = size32 THEN
- adrPrefix := TRUE;
- END;
- END;
- END;
- IF mem.index # NIL THEN
- IF (mem.index IS Reg64) & (mem.index.index >= 8) THEN
- INCL (rexPrefix, rexX)
- END
- END;
- IF (mem.size = size64) & ~(ASM.optD64 IN ASM.instructions[instr].options) THEN
- INCL (rexPrefix, rexW)
- END;
- IF ASM.instructions[instr].operands[i] = ASM.moffset64 THEN
- adrPrefix := TRUE;
- END;
- ELSIF operands[i] IS Reg THEN
- IF (operands[i] IS Reg64) & ~(ASM.optD64 IN ASM.instructions[instr].options) THEN
- INCL (rexPrefix, rexW)
- END;
- IF operands[i](Reg).index >= 8 THEN
- IF i = addressOperand THEN
- INCL (rexPrefix, rexB)
- ELSIF i = regOperand THEN
- INCL (rexPrefix, rexR)
- END;
- ELSIF (bits = size64) & (operands[i] IS Reg8) & (operands[i](Reg).index >= 4) THEN
- INCL (rexPrefix, rex);
- END;
- END;
- END;
- free[i] := operands[i] # NIL;
- END;
- CASE segPrefix OF
- ASM.none:
- | segES: PutByte (ASM.prfES);
- | segCS: PutByte (ASM.prfCS);
- | segSS: PutByte (ASM.prfSS);
- | segDS: PutByte (ASM.prfDS);
- | segFS: PutByte (ASM.prfFS);
- | segGS: PutByte (ASM.prfGS);
- END;
- IF opPrefix THEN PutByte (ASM.prfOP) END;
- IF adrPrefix THEN PutByte (ASM.prfADR) END;
- IF ASM.optPLOCK IN ASM.instructions[instr].options THEN PutByte (ASM.prfLOCK) END;
- IF ASM.optPREP IN ASM.instructions[instr].options THEN PutByte (ASM.prfREP) END;
- IF ASM.optPREPN IN ASM.instructions[instr].options THEN PutByte (ASM.prfREPNE) END;
- IF rexPrefix # {} THEN
- byte := 40H;
- IF rexB IN rexPrefix THEN byte := byte + 1H END;
- IF rexX IN rexPrefix THEN byte := byte + 2H END;
- IF rexR IN rexPrefix THEN byte := byte + 4H END;
- IF rexW IN rexPrefix THEN byte := byte + 8H END;
- PutByte (byte);
- END;
- op := 0;
- WHILE ASM.instructions[instr].opcode[oppos] # 0X DO
- IF ASM.instructions[instr].opcode[oppos] = 'i' THEN
- IF val # -1 THEN PutByte (val); val := -1 END;
- CASE ASM.instructions[instr].opcode[oppos + 1] OF
- 'b': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Imm) THEN
- offset := SHORT (operands[i](Imm).val);
- IF FALSE & lastPass & ~ValueInByteRange (offset) THEN
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- operands[i](Imm).pc := pc;
- PutByte (SHORT (operands[i](Imm).val));
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- | 'w': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Imm) THEN
- operands[i](Imm).pc := pc;
- PutWord (SHORT (operands[i](Imm).val));
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- | 'd': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Imm) THEN
- operands[i](Imm).pc := pc;
- PutDWord (SHORT (operands[i](Imm).val));
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- | 'q': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Imm) THEN
- operands[i](Imm).pc := pc;
- IF lastPass & (operands[i](Imm).fixup # NIL) THEN
- AddFixup (operands[i](Imm).fixup, pc);
- END;
- PutQWord (operands[i](Imm).val);
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- END;
- ELSIF ASM.instructions[instr].opcode[oppos] = 'c' THEN
- IF val # -1 THEN PutByte (val); val := -1 END;
- CASE ASM.instructions[instr].opcode[oppos + 1] OF
- 'b': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Offset) THEN
- offset := SHORT (operands[i](Offset).val - pc - 1);
- IF lastPass & ~ValueInByteRange (offset) THEN
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- operands[i](Offset).pc := pc;
- PutByte (offset);
- free[i] := FALSE; i:= ASM.maxOperands;
- ELSIF (free[i]) & (operands[i] IS Imm) THEN
- offset := SHORT (operands[i](Imm).val);
- IF lastPass & ~ValueInByteRange (offset) THEN
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- operands[i](Imm).pc := pc;
- PutByte (offset);
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- |'w': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Offset) THEN
- offset := SHORT (operands[i](Offset).val - pc - 2);
- IF lastPass & ~ValueInWordRange (offset) THEN
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- operands[i](Offset).pc := pc;
- PutWord (offset);
- free[i] := FALSE; i:= ASM.maxOperands;
- ELSIF (free[i]) & (operands[i] IS Imm) THEN
- offset := SHORT (operands[i](Imm).val);
- IF lastPass & ~ValueInWordRange (offset) THEN
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- operands[i](Imm).pc := pc;
- PutWord (offset);
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- |'d': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Offset) THEN
- operands[i](Offset).pc := pc;
- PutDWord (SHORT (operands[i](Offset).val - pc - 4));
- free[i] := FALSE; i:= ASM.maxOperands;
- ELSIF (free[i]) & (operands[i] IS Imm) THEN
- operands[i](Imm).pc := pc;
- PutDWord (SHORT (operands[i](Imm).val));
- free[i] := FALSE; i:= ASM.maxOperands;
- END
- END;
- END;
- ELSIF ASM.instructions[instr].opcode[oppos] = '/' THEN
- IF val # -1 THEN PutByte (val); val := -1 END;
- CASE ASM.instructions[instr].opcode[oppos + 1] OF
- 'r':
- regField := operands[regOperand](Reg).index MOD 8;
- | '0'..'9':
- regField := ORD (ASM.instructions[instr].opcode[oppos + 1]) - ORD ('0');
- END;
- IF operands[addressOperand] IS Reg THEN
- ModRM (3, regField, operands[addressOperand](Reg).index MOD 8);
- ELSIF (bits = size16) & ((operands[addressOperand](Mem).reg = NIL) OR ~(operands[addressOperand](Mem).reg IS Reg32)) THEN
- mem := operands[addressOperand](Mem);
- IF (mem.scale # 1) OR (mem.fixup # NIL) THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- ELSIF mem.reg = NIL THEN
- IF mem.index # NIL THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- ModRM (0, regField, 6);
- PutWord (mem.displacement);
- ELSIF mem.reg IS Reg16 THEN
- IF mem.displacement = 0 THEN
- modField := 0;
- ELSIF (mem.displacement >= -80H) & (mem.displacement < 80H) THEN
- modField := 1;
- ELSIF (mem.displacement >= -8000H) & (mem.displacement < 8000H) THEN
- modField := 2;
- ELSE
- PCM.Error (559, errPos, ""); RETURN FALSE;
- END;
- CASE mem.reg.index OF
- | rBX:
- IF mem.index = NIL THEN
- rmField := 7;
- ELSIF mem.index.index = rSI THEN
- rmField := 0;
- ELSIF mem.index.index = rDI THEN
- rmField := 1;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END
- | rBP:
- IF mem.index = NIL THEN
- rmField := 6;
- IF modField = 0 THEN modField := 1 END;
- ELSIF mem.index.index = rSI THEN
- rmField := 2;
- ELSIF mem.index.index = rDI THEN
- rmField := 3;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END
- | rSI:
- IF mem.index = NIL THEN
- rmField := 4;
- ELSIF mem.index.index = rBX THEN
- rmField := 0;
- ELSIF mem.index.index = rBP THEN
- rmField := 2;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- | rDI:
- IF mem.index = NIL THEN
- rmField := 5;
- ELSIF mem.index.index = rBX THEN
- rmField := 1;
- ELSIF mem.index.index = rBP THEN
- rmField := 3;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- ModRM (modField, regField, rmField);
- IF modField = 1 THEN
- PutByte (mem.displacement);
- ELSIF modField = 2 THEN
- PutWord (mem.displacement);
- END;
- END;
- ELSE
- mem := operands[addressOperand](Mem);
- IF (mem.reg = NIL) & (mem.index = NIL) THEN
- IF mem.scale # 1 THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- IF bits = size64 THEN
- ModRM (0, regField, 4);
- SIB (0, 4, 5);
- ELSE
- ModRM (0, regField, 5);
- END;
- (* fixup must be 8bit wide for linker!
- IF lastPass & (mem.fixup # NIL) THEN
- AddFixup (mem.fixup, pc);
- END;
- *)
- PutDWord (mem.displacement);
- ELSE
- IF (mem.index # NIL) THEN
- IF (mem.index.index = rSP) OR (mem.index.index = rIP) THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- IF (mem.reg # NIL) & (mem.reg.index = rIP) THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- CASE mem.scale OF
- 1: scaleField := 0;
- | 2: scaleField := 1;
- | 4: scaleField := 2;
- | 8: scaleField := 3;
- ELSE
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- rmField := 4;
- ELSE
- IF (mem.scale # 1) THEN
- PCM.Error (556, errPos, ""); RETURN FALSE;
- END;
- IF mem.reg.index = rIP THEN
- rmField := 5;
- ELSIF mem.reg.index MOD 8 = rSP THEN
- rmField := 4;
- ELSE
- rmField := mem.reg.index MOD 8;
- END;
- END;
- (* IF mem.fixup # NIL THEN
- modField := 2;
- mem fixups only for local variables and parameters
- *)
- IF mem.displacement = 0 THEN
- IF (mem.reg # NIL) & (mem.reg.index = rBP) THEN
- modField := 1;
- ELSE
- modField := 0;
- END;
- ELSIF (mem.reg # NIL) & (mem.reg.index = rIP) THEN
- modField := 0;
- ELSIF (mem.displacement >= -80H) & (mem.displacement < 80H) THEN
- modField := 1;
- ELSE
- modField := 2;
- END;
- ModRM (modField, regField, rmField);
- IF (mem.index # NIL) OR (mem.reg.index MOD 8 = rSP) THEN
- IF mem.index # NIL THEN
- indexField := mem.index.index MOD 8;
- ELSE
- indexField := 4;
- END;
- IF mem.reg # NIL THEN
- baseField := mem.reg.index MOD 8;
- ELSE
- baseField := 5;
- END;
- SIB (scaleField, indexField, baseField);
- END;
- IF (modField = 0) & (mem.reg # NIL) & (mem.reg.index = rIP) THEN
- PutDWord (mem.displacement);
- ELSIF modField = 1 THEN
- PutByte (mem.displacement);
- ELSIF modField = 2 THEN
- (* fixup must be 8bit wide for linker!
- IF lastPass & (mem.fixup # NIL) THEN
- AddFixup (mem.fixup, pc);
- END;
- *)
- PutDWord (mem.displacement);
- END;
- END;
- END;
- ELSIF ASM.instructions[instr].opcode[oppos] = '+' THEN
- CASE ASM.instructions[instr].opcode[oppos + 1] OF
- 'o':
- IF val # -1 THEN PutByte (val); val := -1 END;
- FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS Mem) THEN
- mem := operands[i](Mem);
- IF bits = size16 THEN
- PutWord (mem.displacement);
- ELSE
- IF lastPass & (mem.fixup # NIL) THEN
- AddFixup (mem.fixup, pc);
- END;
- PutDWord (mem.displacement);
- END;
- free[i] := FALSE; i:= ASM.maxOperands;
- END;
- END;
- | 'i': FOR i := 0 TO ASM.maxOperands - 1 DO
- IF (free[i]) & (operands[i] IS FPReg) & (ASM.instructions[instr].operands[i] # ASM.st0) THEN
- val := val + operands[i](FPReg).index;
- PutByte (val); val := -1;
- free[i] := FALSE; i:= ASM.maxOperands;
- END;
- END;
- END;
- ELSIF ASM.instructions[instr].opcode[oppos] = 'r' THEN
- regOperand := GetRegOperand ();
- val := val + operands[regOperand](Reg).index MOD 8;
- PutByte (val); val := -1;
- free[regOperand] := FALSE;
- ELSE
- IF val # -1 THEN PutByte (val) END;
- val := HexOrd (ASM.instructions[instr].opcode[oppos]) * 10H + HexOrd (ASM.instructions[instr].opcode[oppos + 1]);
- END;
- INC (oppos, 2);
- END;
- IF val # -1 THEN PutByte (val) END;
- RETURN TRUE;
- END EmitInstr;
- END Assembly;
- (** Text processing handler registered at CompilerInterface *)
- PROCEDURE AssembleText(
- text : Texts.Text;
- CONST source: ARRAY OF CHAR;
- pos: LONGINT; (* ignore *)
- CONST pc,opt: ARRAY OF CHAR; (* filename *)
- log: Streams.Writer; diagnostics : Diagnostics.Diagnostics; VAR error: BOOLEAN);
- VAR
- assembly: Assembly;
- destFile : Files.FileName;
- BEGIN
- ASSERT(text # NIL);
- ASSERT(log # NIL);
- ASSERT(diagnostics # NIL);
- IF (opt = "") THEN
- log.String("Error: Expected target filename as parameter"); log.Ln;
- log.Update;
- RETURN;
- END;
- PCM.Init(source, NIL, diagnostics);
- NEW (assembly, diagnostics, NIL);
- assembly.Assemble (PCS.InitWithText (text, 0), NIL, FALSE, FALSE, FALSE);
- error := PCM.error;
- IF error THEN
- (* error reported to diagnostics interface *)
- ELSE
- COPY(opt, destFile);
- ReplaceSuffix(destFile, binSuffix);
- log.String("Assembling "); log.String(destFile); log.String("... "); log.Update;
- WriteBinary(destFile, assembly, diagnostics, error);
- IF error THEN
- log.String("error: could not write binary.");
- ELSE
- log.String("done.");
- END;
- log.Update;
- END;
- END AssembleText;
- PROCEDURE AssembleFile* (CONST fileName: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; labels, listing: Streams.Writer);
- VAR
- format: LONGINT; res: WORD;
- text: Texts.Text;
- assembly: Assembly;
- destFile: ARRAY Files.NameLength OF CHAR;
- label: Label;
- ignore : BOOLEAN;
- BEGIN
- PCM.Init (fileName, NIL, diagnostics);
- NEW (text);
- TextUtilities.LoadAuto (text, fileName, format, res);
- IF res # 0 THEN
- diagnostics.Error (fileName, Streams.Invalid, "failed to open file"); RETURN;
- END;
- NEW (assembly, diagnostics, NIL);
- assembly.Assemble (PCS.InitWithText (text, 0), NIL, FALSE, FALSE, FALSE);
- IF PCM.error THEN
- (* error reported to diagnostics interface *)
- ELSE
- COPY (fileName, destFile);
- ReplaceSuffix(destFile, binSuffix);
- WriteBinary(destFile, assembly, diagnostics, ignore);
- IF labels # NIL THEN
- label := assembly.firstLabel;
- WHILE label # NIL DO
- labels.String (label.name); labels.String (" := ");
- labels.Int (label.pc, 0); labels.String (" (");
- labels.Hex (label.pc, 0); labels.String (")");
- labels.Ln;
- label := label.next;
- END;
- END;
- END;
- END AssembleFile;
- (* Assemble file: usage: PCAAMD64.Assemble file [l] *)
- PROCEDURE Assemble* (context: Commands.Context);
- VAR fileName: Files.FileName; labels: Streams.Writer; diagnostics: Diagnostics.StreamDiagnostics;
- BEGIN
- context.arg.SkipWhitespace; context.arg.String (fileName); context.arg.SkipWhitespace;
- IF context.arg.Peek () = 'l' THEN labels := context.out ELSE labels := NIL END;
- NEW (diagnostics, context.error);
- AssembleFile (fileName, diagnostics, labels, context.out);
- END Assemble;
- PROCEDURE InlineAssemble (scanner: PCS.Scanner; scope: PCT.Scope; exported, inlined: BOOLEAN): PCM.Attribute;
- VAR assembly: Assembly;
- BEGIN
- NEW (assembly, PCM.diagnostics, NIL);
- assembly.Assemble (scanner, scope, exported, inlined, TRUE);
- RETURN assembly;
- END InlineAssemble;
- PROCEDURE WriteBinary(CONST filename : ARRAY OF CHAR; assembly : Assembly; diagnostics : Diagnostics.Diagnostics; VAR error : BOOLEAN);
- VAR file : Files.File; writer : Files.Writer; asmblock: PCLIR.AsmBlock;
- BEGIN
- ASSERT(assembly # NIL);
- ASSERT(diagnostics # NIL);
- file := Files.New (filename);
- IF (file # NIL) THEN
- error := FALSE;
- Files.OpenWriter (writer, file, 0);
- asmblock := assembly.code;
- WHILE asmblock # NIL DO
- writer.Bytes (asmblock.code, 0, asmblock.len);
- asmblock := asmblock.next;
- END;
- writer.Update;
- Files.Register(file);
- ELSE
- diagnostics.Error(filename, Streams.Invalid, "Could not create output file");
- error := TRUE;
- END;
- END WriteBinary;
- PROCEDURE ReplaceSuffix (VAR destFile : ARRAY OF CHAR; CONST suffix: ARRAY OF CHAR);
- VAR i, j: LONGINT; fileName : Files.FileName;
- BEGIN
- COPY(destFile, fileName);
- i := 0; WHILE (fileName[i] # 0X) & (fileName[i] # '.') DO destFile[i] := fileName[i]; INC(i) END;
- j := 0; WHILE suffix[j] # 0X DO destFile[i+j] := suffix[j]; INC(j) END;
- destFile[i+j] := 0X;
- END ReplaceSuffix;
- PROCEDURE Ord (ch: CHAR): INTEGER;
- BEGIN RETURN ORD (ch) - ORD ("0")
- END Ord;
- PROCEDURE HexOrd (ch: CHAR): INTEGER;
- BEGIN
- IF ch <= "9" THEN RETURN ORD (ch) - ORD ("0")
- ELSE RETURN ORD (CAP (ch)) - ORD ("A") + 10
- END
- END HexOrd;
- PROCEDURE ValueInByteRange (value: HUGEINT): BOOLEAN;
- BEGIN RETURN SYSTEM.VAL (SHORTINT, value) = value
- END ValueInByteRange;
- PROCEDURE ValueInWordRange (value: HUGEINT): BOOLEAN;
- BEGIN RETURN SYSTEM.VAL (INTEGER, value) = value
- END ValueInWordRange;
- PROCEDURE NewReg (type, index: LONGINT): Reg;
- BEGIN
- CASE type OF
- ASM.reg8: RETURN NewReg8 (index);
- | ASM.reg16: RETURN NewReg16 (index);
- | ASM.reg32: RETURN NewReg32 (index);
- | ASM.reg64: RETURN NewReg64 (index);
- | ASM.segReg: RETURN NewSegReg (index);
- | ASM.CRn: RETURN NewRegCR (index);
- | ASM.DRn: RETURN NewRegDR (index);
- | ASM.st0: RETURN NewFPReg (0);
- | ASM.sti: RETURN NewFPReg (index);
- | ASM.xmm: RETURN NewXMMReg (index);
- | ASM.mmx: RETURN NewMMXReg (index);
- END;
- END NewReg;
- PROCEDURE NewReg8* (index: LONGINT): Reg8;
- VAR reg8: Reg8;
- BEGIN
- NEW (reg8, index);
- RETURN reg8;
- END NewReg8;
- PROCEDURE NewReg16* (index: LONGINT): Reg16;
- VAR reg16: Reg16;
- BEGIN
- NEW (reg16, index);
- RETURN reg16;
- END NewReg16;
- PROCEDURE NewReg32* (index: LONGINT): Reg32;
- VAR reg32: Reg32;
- BEGIN
- NEW (reg32, index);
- RETURN reg32;
- END NewReg32;
- PROCEDURE NewReg64* (index: LONGINT): Reg64;
- VAR reg64: Reg64;
- BEGIN
- NEW (reg64, index);
- RETURN reg64;
- END NewReg64;
- PROCEDURE NewRegCR* (index: LONGINT): RegCR;
- VAR regCR: RegCR;
- BEGIN
- NEW (regCR, index);
- RETURN regCR;
- END NewRegCR;
- PROCEDURE NewRegDR* (index: LONGINT): RegDR;
- VAR regDR: RegDR;
- BEGIN
- NEW (regDR, index);
- RETURN regDR;
- END NewRegDR;
- PROCEDURE NewSegReg* (index: LONGINT): SegReg;
- VAR segReg: SegReg;
- BEGIN
- NEW (segReg, index);
- RETURN segReg;
- END NewSegReg;
- PROCEDURE NewFPReg* (index: LONGINT): FPReg;
- VAR fpReg: FPReg;
- BEGIN
- NEW (fpReg, index);
- RETURN fpReg;
- END NewFPReg;
- PROCEDURE NewMMXReg* (index: LONGINT): MMXReg;
- VAR mmxReg: MMXReg;
- BEGIN
- NEW (mmxReg, index);
- RETURN mmxReg;
- END NewMMXReg;
- PROCEDURE NewXMMReg* (index: LONGINT): XMMReg;
- VAR xmmReg: XMMReg;
- BEGIN
- NEW (xmmReg, index);
- RETURN xmmReg;
- END NewXMMReg;
- PROCEDURE NewMem (size: Size; reg: Reg; displacement: LONGINT): Mem;
- VAR mem: Mem;
- BEGIN
- NEW (mem, size);
- mem.reg := reg;
- mem.displacement := displacement;
- RETURN mem;
- END NewMem;
- PROCEDURE NewMem8* (reg: Reg; displacement: LONGINT): Mem;
- BEGIN RETURN NewMem (size8, reg, displacement);
- END NewMem8;
- PROCEDURE NewMem16* (reg: Reg; displacement: LONGINT): Mem;
- BEGIN RETURN NewMem (size16, reg, displacement);
- END NewMem16;
- PROCEDURE NewMem32* (reg: Reg; displacement: LONGINT): Mem;
- BEGIN RETURN NewMem (size32, reg, displacement);
- END NewMem32;
- PROCEDURE NewMem64* (reg: Reg; displacement: LONGINT): Mem;
- BEGIN RETURN NewMem (size64, reg, displacement);
- END NewMem64;
- PROCEDURE NewMem128* (reg: Reg; displacement: LONGINT): Mem;
- BEGIN RETURN NewMem (size128, reg, displacement);
- END NewMem128;
- PROCEDURE NewImm* (size: LONGINT; val: HUGEINT): Imm;
- VAR imm: Imm;
- BEGIN
- NEW (imm, size, val);
- RETURN imm;
- END NewImm;
- PROCEDURE NewImm8* (val: HUGEINT): Imm;
- BEGIN RETURN NewImm (size8, val);
- END NewImm8;
- PROCEDURE NewImm16* (val: HUGEINT): Imm;
- BEGIN RETURN NewImm (size16, val);
- END NewImm16;
- PROCEDURE NewImm32* (val: HUGEINT): Imm;
- BEGIN RETURN NewImm (size32, val);
- END NewImm32;
- PROCEDURE NewImm64* (val: HUGEINT): Imm;
- BEGIN RETURN NewImm (size64, val);
- END NewImm64;
- PROCEDURE NewOffset* (size: LONGINT; val: HUGEINT): Offset;
- VAR offset: Offset;
- BEGIN
- NEW (offset, size, val);
- RETURN offset;
- END NewOffset;
- PROCEDURE NewOffset8* (val: HUGEINT): Offset;
- BEGIN RETURN NewOffset (size8, val);
- END NewOffset8;
- PROCEDURE NewOffset16* (val: HUGEINT): Offset;
- BEGIN RETURN NewOffset (size16, val);
- END NewOffset16;
- PROCEDURE NewOffset32* (val: HUGEINT): Offset;
- BEGIN RETURN NewOffset (size32, val);
- END NewOffset32;
- PROCEDURE NewOffset64* (val: HUGEINT): Offset;
- BEGIN RETURN NewOffset (size64, val);
- END NewOffset64;
- PROCEDURE NewPntr1616* (s, o: LONGINT): Pntr1616;
- VAR pntr1616: Pntr1616;
- BEGIN
- NEW (pntr1616, s, o);
- RETURN pntr1616;
- END NewPntr1616;
- PROCEDURE NewPntr1632* (s, o: LONGINT): Pntr1632;
- VAR pntr1632: Pntr1632;
- BEGIN
- NEW (pntr1632, s, o);
- RETURN pntr1632;
- END NewPntr1632;
- PROCEDURE Install*;
- BEGIN PCP.Assemble := InlineAssemble;
- END Install;
- PROCEDURE Cleanup;
- BEGIN
- CompilerInterface.Unregister("AAMD64");
- END Cleanup;
- BEGIN
- Modules.InstallTermHandler(Cleanup);
- CompilerInterface.Register("AAMD64", "AMD64 Assembler", "ASM", AssembleText);
- END PCAAMD64.
|