| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545 |
- (*
- BSD 2-Clause License
- Copyright (c) 2018-2023, Anton Krotov
- All rights reserved.
- *)
- MODULE X86;
- IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG,
- CHL := CHUNKLISTS, PATHS, TARGETS, ERRORS;
- CONST
- eax = REG.R0; ecx = REG.R1; edx = REG.R2;
- al = eax; cl = ecx; dl = edx; ah = 4;
- ax = eax; cx = ecx; dx = edx;
- esp = 4;
- ebp = 5;
- MAX_FR = 7;
- sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H;
- je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H;
- CODECHUNK = 8;
- FPR_ERR = 41;
- TYPE
- COMMAND = IL.COMMAND;
- ANYCODE = POINTER TO RECORD (LISTS.ITEM)
- offset: INTEGER
- END;
- CODE = POINTER TO RECORD (ANYCODE)
- code: ARRAY CODECHUNK OF BYTE;
- length: INTEGER
- END;
- LABEL = POINTER TO RECORD (ANYCODE)
- label: INTEGER
- END;
- JUMP = POINTER TO RECORD (ANYCODE)
- label, diff: INTEGER;
- short: BOOLEAN
- END;
- JMP = POINTER TO RECORD (JUMP)
- END;
- JCC = POINTER TO RECORD (JUMP)
- jmp: INTEGER
- END;
- CALL = POINTER TO RECORD (JUMP)
- END;
- RELOC = POINTER TO RECORD (ANYCODE)
- op, value: INTEGER
- END;
- VAR
- R: REG.REGS;
- program: BIN.PROGRAM;
- CodeList: LISTS.LIST;
- tcount, LocVarSize, mainLocVarSize: INTEGER;
- FR: ARRAY 1000 OF INTEGER;
- fname: PATHS.PATH;
- FltConstLabel, mainFltConstLabel: LABEL;
- PROCEDURE OutByte* (n: BYTE);
- VAR
- c: CODE;
- last: ANYCODE;
- BEGIN
- last := CodeList.last(ANYCODE);
- IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN
- c := last(CODE);
- c.code[c.length] := n;
- INC(c.length)
- ELSE
- NEW(c);
- c.code[0] := n;
- c.length := 1;
- LISTS.push(CodeList, c)
- END
- END OutByte;
- PROCEDURE OutInt (n: INTEGER);
- BEGIN
- OutByte(n MOD 256);
- OutByte(UTILS.Byte(n, 1));
- OutByte(UTILS.Byte(n, 2));
- OutByte(UTILS.Byte(n, 3))
- END OutInt;
- PROCEDURE OutByte2 (a, b: BYTE);
- BEGIN
- OutByte(a);
- OutByte(b)
- END OutByte2;
- PROCEDURE OutByte3 (a, b, c: BYTE);
- BEGIN
- OutByte(a);
- OutByte(b);
- OutByte(c)
- END OutByte3;
- PROCEDURE OutWord (n: INTEGER);
- BEGIN
- ASSERT((0 <= n) & (n <= 65535));
- OutByte2(n MOD 256, n DIV 256)
- END OutWord;
- PROCEDURE isByte* (n: INTEGER): BOOLEAN;
- RETURN (-128 <= n) & (n <= 127)
- END isByte;
- PROCEDURE short (n: INTEGER): INTEGER;
- RETURN 2 * ORD(isByte(n))
- END short;
- PROCEDURE long (n: INTEGER): INTEGER;
- RETURN 40H * ORD(~isByte(n))
- END long;
- PROCEDURE OutIntByte (n: INTEGER);
- BEGIN
- IF isByte(n) THEN
- OutByte(n MOD 256)
- ELSE
- OutInt(n)
- END
- END OutIntByte;
- PROCEDURE shift* (op, reg: INTEGER);
- BEGIN
- CASE op OF
- |IL.opASR, IL.opASR1, IL.opASR2: OutByte(0F8H + reg)
- |IL.opROR, IL.opROR1, IL.opROR2: OutByte(0C8H + reg)
- |IL.opLSL, IL.opLSL1, IL.opLSL2: OutByte(0E0H + reg)
- |IL.opLSR, IL.opLSR1, IL.opLSR2: OutByte(0E8H + reg)
- END
- END shift;
- PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
- BEGIN
- OutByte2(op, 0C0H + 8 * reg2 + reg1)
- END oprr;
- PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *)
- BEGIN
- oprr(89H, reg1, reg2)
- END mov;
- PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *)
- BEGIN
- IF eax IN {reg1, reg2} THEN
- OutByte(90H + reg1 + reg2)
- ELSE
- oprr(87H, reg1, reg2)
- END
- END xchg;
- PROCEDURE pop (reg: INTEGER);
- BEGIN
- OutByte(58H + reg) (* pop reg *)
- END pop;
- PROCEDURE push (reg: INTEGER);
- BEGIN
- OutByte(50H + reg) (* push reg *)
- END push;
- PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *)
- BEGIN
- oprr(31H, reg1, reg2)
- END xor;
- PROCEDURE movrc (reg, n: INTEGER);
- BEGIN
- IF n = 0 THEN
- xor(reg, reg)
- ELSE
- OutByte(0B8H + reg); (* mov reg, n *)
- OutInt(n)
- END
- END movrc;
- PROCEDURE pushc* (n: INTEGER);
- BEGIN
- OutByte(68H + short(n)); (* push n *)
- OutIntByte(n)
- END pushc;
- PROCEDURE test (reg: INTEGER);
- BEGIN
- OutByte2(85H, 0C0H + reg * 9) (* test reg, reg *)
- END test;
- PROCEDURE neg (reg: INTEGER);
- BEGIN
- OutByte2(0F7H, 0D8H + reg) (* neg reg *)
- END neg;
- PROCEDURE not (reg: INTEGER);
- BEGIN
- OutByte2(0F7H, 0D0H + reg) (* not reg *)
- END not;
- PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *)
- BEGIN
- oprr(01H, reg1, reg2)
- END add;
- PROCEDURE oprc* (op, reg, n: INTEGER);
- BEGIN
- IF (reg = eax) & ~isByte(n) THEN
- CASE op OF
- |0C0H: op := 05H (* add *)
- |0E8H: op := 2DH (* sub *)
- |0F8H: op := 3DH (* cmp *)
- |0E0H: op := 25H (* and *)
- |0C8H: op := 0DH (* or *)
- |0F0H: op := 35H (* xor *)
- END;
- OutByte(op);
- OutInt(n)
- ELSE
- OutByte2(81H + short(n), op + reg MOD 8);
- OutIntByte(n)
- END
- END oprc;
- PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *)
- BEGIN
- oprc(0E0H, reg, n)
- END andrc;
- PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *)
- BEGIN
- oprc(0C8H, reg, n)
- END orrc;
- PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *)
- BEGIN
- oprc(0F0H, reg, n)
- END xorrc;
- PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *)
- BEGIN
- oprc(0C0H, reg, n)
- END addrc;
- PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *)
- BEGIN
- oprc(0E8H, reg, n)
- END subrc;
- PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *)
- BEGIN
- IF n = 0 THEN
- test(reg)
- ELSE
- oprc(0F8H, reg, n)
- END
- END cmprc;
- PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *)
- BEGIN
- oprr(39H, reg1, reg2)
- END cmprr;
- PROCEDURE setcc* (cc, reg: INTEGER); (* setcc reg *)
- BEGIN
- IF reg >= 8 THEN
- OutByte(41H)
- END;
- OutByte3(0FH, cc, 0C0H + reg MOD 8)
- END setcc;
- PROCEDURE ret*;
- BEGIN
- OutByte(0C3H)
- END ret;
- PROCEDURE drop;
- BEGIN
- REG.Drop(R)
- END drop;
- PROCEDURE GetAnyReg (): INTEGER;
- RETURN REG.GetAnyReg(R)
- END GetAnyReg;
- PROCEDURE cond* (op: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- CASE op OF
- |IL.opGT, IL.opGTC: res := jg
- |IL.opGE, IL.opGEC: res := jge
- |IL.opLT, IL.opLTC: res := jl
- |IL.opLE, IL.opLEC: res := jle
- |IL.opEQ, IL.opEQC: res := je
- |IL.opNE, IL.opNEC: res := jne
- END
- RETURN res
- END cond;
- PROCEDURE inv0* (op: INTEGER): INTEGER;
- RETURN ORD(BITS(op) / {0})
- END inv0;
- PROCEDURE Reloc* (op, value: INTEGER);
- VAR
- reloc: RELOC;
- BEGIN
- NEW(reloc);
- reloc.op := op;
- reloc.value := value;
- LISTS.push(CodeList, reloc)
- END Reloc;
- PROCEDURE PushFlt (label: LABEL; value: REAL);
- VAR
- a, b, n: INTEGER;
- PROCEDURE pushImm (label: LABEL; value: INTEGER);
- VAR
- c: CODE;
- i: INTEGER;
- BEGIN
- NEW(c);
- IF isByte(value) THEN
- c.code[0] := 6AH;
- c.code[1] := value MOD 256;
- c.length := 2
- ELSE
- c.code[0] := 68H;
- FOR i := 1 TO 4 DO
- c.code[i] := UTILS.Byte(value, i - 1)
- END;
- c.length := 5
- END;
- LISTS.insertL(CodeList, label, c)
- END pushImm;
- BEGIN
- n := UTILS.splitf(value, a, b);
- pushImm(label, b);
- pushImm(label, a)
- END PushFlt;
- PROCEDURE jcc* (cc, label: INTEGER);
- VAR
- j: JCC;
- BEGIN
- NEW(j);
- j.label := label;
- j.jmp := cc;
- j.short := FALSE;
- LISTS.push(CodeList, j)
- END jcc;
- PROCEDURE jmp* (label: INTEGER);
- VAR
- j: JMP;
- BEGIN
- NEW(j);
- j.label := label;
- j.short := FALSE;
- LISTS.push(CodeList, j)
- END jmp;
- PROCEDURE call* (label: INTEGER);
- VAR
- c: CALL;
- BEGIN
- NEW(c);
- c.label := label;
- c.short := TRUE;
- LISTS.push(CodeList, c)
- END call;
- PROCEDURE Pic (reg, opcode, value: INTEGER);
- BEGIN
- OutByte(0E8H); OutInt(0); (* call L
- L: *)
- pop(reg);
- OutByte2(081H, 0C0H + reg); (* add reg, ... *)
- Reloc(opcode, value)
- END Pic;
- PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER);
- VAR
- label: INTEGER;
- reg1: INTEGER;
- BEGIN
- label := IL.codes.rtl[proc];
- IF label < 0 THEN
- label := -label;
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICIMP, label);
- OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *)
- drop
- ELSE
- OutByte2(0FFH, 015H); (* call dword[label] *)
- Reloc(BIN.RIMP, label)
- END
- ELSE
- call(label)
- END
- END CallRTL;
- PROCEDURE SetLabel* (label: INTEGER);
- VAR
- L: LABEL;
- BEGIN
- NEW(L);
- L.label := label;
- LISTS.push(CodeList, L)
- END SetLabel;
- PROCEDURE fixup*;
- VAR
- code: ANYCODE;
- count, i: INTEGER;
- shorted: BOOLEAN;
- jump: JUMP;
- BEGIN
- REPEAT
- shorted := FALSE;
- count := 0;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- code.offset := count;
- CASE code OF
- |CODE: INC(count, code.length)
- |LABEL: BIN.SetLabel(program, code.label, count)
- |JMP: IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count
- |JCC: IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count
- |CALL: INC(count, 5); code.offset := count
- |RELOC: INC(count, 4)
- END;
- code := code.next(ANYCODE)
- END;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- IF code IS JUMP THEN
- jump := code(JUMP);
- jump.diff := BIN.GetLabel(program, jump.label) - code.offset;
- IF ~jump.short & isByte(jump.diff) THEN
- jump.short := TRUE;
- shorted := TRUE
- END
- END;
- code := code.next(ANYCODE)
- END
- UNTIL ~shorted;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- CASE code OF
- |CODE:
- FOR i := 0 TO code.length - 1 DO
- BIN.PutCode(program, code.code[i])
- END
- |LABEL:
- |JMP:
- IF code.short THEN
- BIN.PutCode(program, 0EBH);
- BIN.PutCode(program, code.diff MOD 256)
- ELSE
- BIN.PutCode(program, 0E9H);
- BIN.PutCode32LE(program, code.diff)
- END
- |JCC:
- IF code.short THEN
- BIN.PutCode(program, code.jmp - 16);
- BIN.PutCode(program, code.diff MOD 256)
- ELSE
- BIN.PutCode(program, 0FH);
- BIN.PutCode(program, code.jmp);
- BIN.PutCode32LE(program, code.diff)
- END
- |CALL:
- BIN.PutCode(program, 0E8H);
- BIN.PutCode32LE(program, code.diff)
- |RELOC:
- BIN.PutReloc(program, code.op);
- BIN.PutCode32LE(program, code.value)
- END;
- code := code.next(ANYCODE)
- END
- END fixup;
- PROCEDURE UnOp (VAR reg: INTEGER);
- BEGIN
- REG.UnOp(R, reg)
- END UnOp;
- PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
- BEGIN
- REG.BinOp(R, reg1, reg2)
- END BinOp;
- PROCEDURE PushAll (NumberOfParameters: INTEGER);
- BEGIN
- REG.PushAll(R);
- DEC(R.pushed, NumberOfParameters)
- END PushAll;
- PROCEDURE NewLabel (): INTEGER;
- BEGIN
- BIN.NewLabel(program)
- RETURN IL.NewLabel()
- END NewLabel;
- PROCEDURE GetRegA;
- BEGIN
- ASSERT(REG.GetReg(R, eax))
- END GetRegA;
- PROCEDURE fcmp;
- BEGIN
- GetRegA;
- OutByte2(0DAH, 0E9H); (* fucompp *)
- OutByte3(09BH, 0DFH, 0E0H); (* fstsw ax *)
- OutByte(09EH); (* sahf *)
- OutByte(0B8H); OutInt(0) (* mov eax, 0 *)
- END fcmp;
- PROCEDURE movzx* (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *)
- VAR
- b: BYTE;
- BEGIN
- OutByte2(0FH, 0B6H + ORD(word));
- IF (offs = 0) & (reg2 # ebp) THEN
- b := 0
- ELSE
- b := 40H + long(offs)
- END;
- OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8);
- IF reg2 = esp THEN
- OutByte(24H)
- END;
- IF b # 0 THEN
- OutIntByte(offs)
- END
- END movzx;
- PROCEDURE _movrm* (reg1, reg2, offs, size: INTEGER; mr: BOOLEAN);
- VAR
- b: BYTE;
- BEGIN
- IF size = 16 THEN
- OutByte(66H)
- END;
- IF (reg1 >= 8) OR (reg2 >= 8) OR (size = 64) THEN
- OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8) + 8 * ORD(size = 64))
- END;
- OutByte(8BH - 2 * ORD(mr) - ORD(size = 8));
- IF (offs = 0) & (reg2 # ebp) THEN
- b := 0
- ELSE
- b := 40H + long(offs)
- END;
- OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8);
- IF reg2 = esp THEN
- OutByte(24H)
- END;
- IF b # 0 THEN
- OutIntByte(offs)
- END
- END _movrm;
- PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2 *)
- BEGIN
- _movrm(reg2, reg1, offs, 32, TRUE)
- END movmr;
- PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, dword[reg2 + offs] *)
- BEGIN
- _movrm(reg1, reg2, offs, 32, FALSE)
- END movrm;
- PROCEDURE movmr8* (reg1, offs, reg2: INTEGER); (* mov byte[reg1+offs], reg2_8 *)
- BEGIN
- _movrm(reg2, reg1, offs, 8, TRUE)
- END movmr8;
- PROCEDURE movrm8* (reg1, reg2, offs: INTEGER); (* mov reg1_8, byte[reg2+offs] *)
- BEGIN
- _movrm(reg1, reg2, offs, 8, FALSE)
- END movrm8;
- PROCEDURE movmr16* (reg1, offs, reg2: INTEGER); (* mov word[reg1+offs], reg2_16 *)
- BEGIN
- _movrm(reg2, reg1, offs, 16, TRUE)
- END movmr16;
- PROCEDURE movrm16* (reg1, reg2, offs: INTEGER); (* mov reg1_16, word[reg2+offs] *)
- BEGIN
- _movrm(reg1, reg2, offs, 16, FALSE)
- END movrm16;
- PROCEDURE pushm* (reg, offs: INTEGER); (* push qword[reg+offs] *)
- VAR
- b: BYTE;
- BEGIN
- IF reg >= 8 THEN
- OutByte(41H)
- END;
- OutByte(0FFH);
- IF (offs = 0) & (reg # ebp) THEN
- b := 30H
- ELSE
- b := 70H + long(offs)
- END;
- OutByte(b + reg MOD 8);
- IF reg = esp THEN
- OutByte(24H)
- END;
- IF b # 30H THEN
- OutIntByte(offs)
- END
- END pushm;
- PROCEDURE LoadFltConst (value: REAL);
- BEGIN
- PushFlt(FltConstLabel, value);
- INC(LocVarSize, 8);
- IF FltConstLabel = mainFltConstLabel THEN
- mainLocVarSize := LocVarSize
- END;
- OutByte2(0DDH, 045H + long(-LocVarSize)); (* fld qword[ebp - LocVarSize] *)
- OutIntByte(-LocVarSize)
- END LoadFltConst;
- PROCEDURE translate (pic: BOOLEAN; stroffs, target: INTEGER);
- VAR
- cmd, next: COMMAND;
- reg1, reg2, reg3, fr: INTEGER;
- n, a, label, cc: INTEGER;
- opcode, param1, param2: INTEGER;
- float: REAL;
- BEGIN
- cmd := IL.codes.commands.first(COMMAND);
- fr := -1;
- WHILE cmd # NIL DO
- param1 := cmd.param1;
- param2 := cmd.param2;
- opcode := cmd.opcode;
- CASE opcode OF
- |IL.opJMP:
- jmp(param1)
- |IL.opCALL:
- call(param1)
- |IL.opCALLI:
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICIMP, param1);
- OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *)
- drop
- ELSE
- OutByte2(0FFH, 015H); (* call dword[L] *)
- Reloc(BIN.RIMP, param1)
- END
- |IL.opCALLP:
- UnOp(reg1);
- OutByte2(0FFH, 0D0H + reg1); (* call reg1 *)
- drop;
- ASSERT(R.top = -1)
- |IL.opFASTCALL:
- IF param2 = 1 THEN
- pop(ecx)
- ELSIF param2 = 2 THEN
- pop(ecx);
- pop(edx)
- END
- |IL.opPRECALL:
- PushAll(0);
- IF (param2 # 0) & (fr >= 0) THEN
- subrc(esp, 8)
- END;
- INC(FR[0]);
- FR[FR[0]] := fr + 1;
- WHILE fr >= 0 DO
- subrc(esp, 8);
- OutByte3(0DDH, 01CH, 024H); (* fstp qword[esp] *)
- DEC(fr)
- END;
- ASSERT(fr = -1)
- |IL.opALIGN16:
- ASSERT(eax IN R.regs);
- mov(eax, esp);
- andrc(esp, -16);
- n := (3 - param2 MOD 4) * 4;
- IF n > 0 THEN
- subrc(esp, n)
- END;
- push(eax)
- |IL.opRESF, IL.opRES:
- ASSERT(R.top = -1);
- ASSERT(fr = -1);
- n := FR[FR[0]]; DEC(FR[0]);
- IF opcode = IL.opRESF THEN
- INC(fr);
- IF n > 0 THEN
- OutByte3(0DDH, 5CH + long(n * 8), 24H);
- OutIntByte(n * 8); (* fstp qword[esp + n*8] *)
- DEC(fr);
- INC(n)
- END;
- IF fr + n > MAX_FR THEN
- ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
- END
- ELSE
- GetRegA
- END;
- WHILE n > 0 DO
- OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *)
- addrc(esp, 8);
- INC(fr);
- DEC(n)
- END
- |IL.opENTER:
- ASSERT(R.top = -1);
- SetLabel(param1);
- IF cmd.param3 > 0 THEN
- pop(eax);
- IF cmd.param3 >= 2 THEN
- push(edx)
- END;
- push(ecx);
- push(eax)
- END;
- push(ebp);
- mov(ebp, esp);
- n := param2;
- IF n > 4 THEN
- movrc(ecx, n);
- pushc(0); (* L: push 0 *)
- OutByte2(0E2H, 0FCH) (* loop L *)
- ELSE
- WHILE n > 0 DO
- pushc(0);
- DEC(n)
- END
- END;
- SetLabel(NewLabel());
- FltConstLabel := CodeList.last(LABEL);
- LocVarSize := param2 * 4
- |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
- IF opcode = IL.opLEAVER THEN
- UnOp(reg1);
- IF reg1 # eax THEN
- mov(eax, reg1)
- END;
- drop
- END;
- ASSERT(R.top = -1);
- IF opcode = IL.opLEAVEF THEN
- DEC(fr)
- END;
- ASSERT(fr = -1);
- IF LocVarSize > 0 THEN
- mov(esp, ebp)
- END;
- pop(ebp);
- IF param2 > 0 THEN
- OutByte(0C2H); OutWord(param2 * 4 MOD 65536) (* ret param2*4 *)
- ELSE
- ret
- END;
- FltConstLabel := mainFltConstLabel;
- LocVarSize := mainLocVarSize
- |IL.opPUSHC:
- pushc(param2)
- |IL.opONERR:
- pushc(param2);
- jmp(param1)
- |IL.opPARAM:
- IF param2 = 1 THEN
- UnOp(reg1);
- push(reg1);
- drop
- ELSE
- ASSERT(R.top + 1 <= param2);
- PushAll(param2)
- END
- |IL.opCLEANUP:
- IF param2 # 0 THEN
- addrc(esp, param2 * 4)
- END
- |IL.opPOPSP:
- pop(esp)
- |IL.opCONST:
- movrc(GetAnyReg(), param2)
- |IL.opLABEL:
- SetLabel(param1) (* L: *)
- |IL.opNOP, IL.opAND, IL.opOR:
- |IL.opGADR:
- next := cmd.next(COMMAND);
- IF next.opcode = IL.opADDC THEN
- INC(param2, next.param2);
- cmd := next
- END;
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICBSS, param2)
- ELSE
- OutByte(0B8H + reg1); (* mov reg1, _bss + param2 *)
- Reloc(BIN.RBSS, param2)
- END
- |IL.opLADR:
- next := cmd.next(COMMAND);
- n := param2 * 4;
- IF next.opcode = IL.opADDC THEN
- INC(n, next.param2);
- cmd := next
- END;
- OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); (* lea reg1, dword[ebp + n] *)
- OutIntByte(n)
- |IL.opVADR, IL.opLLOAD32:
- movrm(GetAnyReg(), ebp, param2 * 4)
- |IL.opSADR:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICDATA, stroffs + param2);
- ELSE
- OutByte(0B8H + reg1); (* mov reg1, _data + stroffs + param2 *)
- Reloc(BIN.RDATA, stroffs + param2)
- END
- |IL.opSAVEC:
- UnOp(reg1);
- OutByte2(0C7H, reg1); OutInt(param2); (* mov dword[reg1], param2 *)
- drop
- |IL.opSAVE8C:
- UnOp(reg1);
- OutByte3(0C6H, reg1, param2 MOD 256); (* mov byte[reg1], param2 *)
- drop
- |IL.opSAVE16C:
- UnOp(reg1);
- OutByte3(66H, 0C7H, reg1); OutWord(param2 MOD 65536); (* mov word[reg1], param2 *)
- drop
- |IL.opVLOAD32:
- reg1 := GetAnyReg();
- movrm(reg1, ebp, param2 * 4);
- movrm(reg1, reg1, 0)
- |IL.opGLOAD32:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICBSS, param2);
- movrm(reg1, reg1, 0)
- ELSE
- OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[_bss + param2] *)
- Reloc(BIN.RBSS, param2)
- END
- |IL.opLOAD32:
- UnOp(reg1);
- movrm(reg1, reg1, 0)
- |IL.opVLOAD8:
- reg1 := GetAnyReg();
- movrm(reg1, ebp, param2 * 4);
- movzx(reg1, reg1, 0, FALSE)
- |IL.opGLOAD8:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICBSS, param2);
- movzx(reg1, reg1, 0, FALSE)
- ELSE
- OutByte3(00FH, 0B6H, 05H + reg1 * 8); (* movzx reg1, byte[_bss + param2] *)
- Reloc(BIN.RBSS, param2)
- END
- |IL.opLLOAD8:
- movzx(GetAnyReg(), ebp, param2 * 4, FALSE)
- |IL.opLOAD8:
- UnOp(reg1);
- movzx(reg1, reg1, 0, FALSE)
- |IL.opVLOAD16:
- reg1 := GetAnyReg();
- movrm(reg1, ebp, param2 * 4);
- movzx(reg1, reg1, 0, TRUE)
- |IL.opGLOAD16:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICBSS, param2);
- movzx(reg1, reg1, 0, TRUE)
- ELSE
- OutByte3(00FH, 0B7H, 05H + reg1 * 8); (* movzx reg1, word[_bss + param2] *)
- Reloc(BIN.RBSS, param2)
- END
- |IL.opLLOAD16:
- movzx(GetAnyReg(), ebp, param2 * 4, TRUE)
- |IL.opLOAD16:
- UnOp(reg1);
- movzx(reg1, reg1, 0, TRUE)
- |IL.opUMINUS:
- UnOp(reg1);
- neg(reg1)
- |IL.opADD:
- BinOp(reg1, reg2);
- add(reg1, reg2);
- drop
- |IL.opADDC:
- IF param2 # 0 THEN
- UnOp(reg1);
- next := cmd.next(COMMAND);
- CASE next.opcode OF
- |IL.opLOAD32:
- movrm(reg1, reg1, param2);
- cmd := next
- |IL.opLOAD16:
- movzx(reg1, reg1, param2, TRUE);
- cmd := next
- |IL.opLOAD8:
- movzx(reg1, reg1, param2, FALSE);
- cmd := next
- |IL.opLOAD32_PARAM:
- pushm(reg1, param2);
- drop;
- cmd := next
- ELSE
- IF param2 = 1 THEN
- OutByte(40H + reg1) (* inc reg1 *)
- ELSIF param2 = -1 THEN
- OutByte(48H + reg1) (* dec reg1 *)
- ELSE
- addrc(reg1, param2)
- END
- END
- END
- |IL.opSUB:
- BinOp(reg1, reg2);
- oprr(29H, reg1, reg2); (* sub reg1, reg2 *)
- drop
- |IL.opSUBR, IL.opSUBL:
- UnOp(reg1);
- IF param2 = 1 THEN
- OutByte(48H + reg1) (* dec reg1 *)
- ELSIF param2 = -1 THEN
- OutByte(40H + reg1) (* inc reg1 *)
- ELSIF param2 # 0 THEN
- subrc(reg1, param2)
- END;
- IF opcode = IL.opSUBL THEN
- neg(reg1)
- END
- |IL.opMULC:
- IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
- BinOp(reg1, reg2);
- OutByte3(8DH, 04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); (* lea reg1, [reg1 + reg2 * param2] *)
- drop;
- cmd := cmd.next(COMMAND)
- ELSE
- UnOp(reg1);
- a := param2;
- IF a > 1 THEN
- n := UTILS.Log2(a)
- ELSIF a < -1 THEN
- n := UTILS.Log2(-a)
- ELSE
- n := -1
- END;
- IF a = 1 THEN
- ELSIF a = -1 THEN
- neg(reg1)
- ELSIF a = 0 THEN
- xor(reg1, reg1)
- ELSE
- IF n > 0 THEN
- IF a < 0 THEN
- neg(reg1)
- END;
- IF n # 1 THEN
- OutByte3(0C1H, 0E0H + reg1, n) (* shl reg1, n *)
- ELSE
- OutByte2(0D1H, 0E0H + reg1) (* shl reg1, 1 *)
- END
- ELSE
- OutByte2(69H + short(a), 0C0H + reg1 * 9); (* imul reg1, a *)
- OutIntByte(a)
- END
- END
- END
- |IL.opMUL:
- BinOp(reg1, reg2);
- OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); (* imul reg1, reg2 *)
- drop
- |IL.opSAVE, IL.opSAVE32:
- BinOp(reg2, reg1);
- movmr(reg1, 0, reg2);
- drop;
- drop
- |IL.opSAVE8:
- BinOp(reg2, reg1);
- movmr8(reg1, 0, reg2);
- drop;
- drop
- |IL.opSAVE16:
- BinOp(reg2, reg1);
- movmr16(reg1, 0, reg2);
- drop;
- drop
- |IL.opSAVEP:
- UnOp(reg1);
- IF pic THEN
- reg2 := GetAnyReg();
- Pic(reg2, BIN.PICCODE, param2);
- movmr(reg1, 0, reg2);
- drop
- ELSE
- OutByte2(0C7H, reg1); (* mov dword[reg1], L *)
- Reloc(BIN.RCODE, param2)
- END;
- drop
- |IL.opSAVEIP:
- UnOp(reg1);
- IF pic THEN
- reg2 := GetAnyReg();
- Pic(reg2, BIN.PICIMP, param2);
- pushm(reg2, 0);
- OutByte2(08FH, reg1); (* pop dword[reg1] *)
- drop
- ELSE
- OutByte2(0FFH, 035H); (* push dword[L] *)
- Reloc(BIN.RIMP, param2);
- OutByte2(08FH, reg1) (* pop dword[reg1] *)
- END;
- drop
- |IL.opPUSHP:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICCODE, param2)
- ELSE
- OutByte(0B8H + reg1); (* mov reg1, L *)
- Reloc(BIN.RCODE, param2)
- END
- |IL.opPUSHIP:
- reg1 := GetAnyReg();
- IF pic THEN
- Pic(reg1, BIN.PICIMP, param2);
- movrm(reg1, reg1, 0)
- ELSE
- OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[L] *)
- Reloc(BIN.RIMP, param2)
- END
- |IL.opNOT:
- UnOp(reg1);
- test(reg1);
- setcc(sete, reg1);
- andrc(reg1, 1)
- |IL.opORD:
- UnOp(reg1);
- test(reg1);
- setcc(setne, reg1);
- andrc(reg1, 1)
- |IL.opSBOOL:
- BinOp(reg2, reg1);
- test(reg2);
- OutByte3(0FH, 95H, reg1); (* setne byte[reg1] *)
- drop;
- drop
- |IL.opSBOOLC:
- UnOp(reg1);
- OutByte3(0C6H, reg1, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
- drop
- |IL.opEQ..IL.opGE,
- IL.opEQC..IL.opGEC:
- IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
- BinOp(reg1, reg2);
- cmprr(reg1, reg2);
- drop
- ELSE
- UnOp(reg1);
- cmprc(reg1, param2)
- END;
- drop;
- cc := cond(opcode);
- next := cmd.next(COMMAND);
- IF next.opcode = IL.opJNZ THEN
- jcc(cc, next.param1);
- cmd := next
- ELSIF next.opcode = IL.opJZ THEN
- jcc(inv0(cc), next.param1);
- cmd := next
- ELSE
- reg1 := GetAnyReg();
- setcc(cc + 16, reg1);
- andrc(reg1, 1)
- END
- |IL.opEQB, IL.opNEB:
- BinOp(reg1, reg2);
- drop;
- test(reg1);
- OutByte2(74H, 5); (* je @f *)
- movrc(reg1, 1); (* mov reg1, 1
- @@: *)
- test(reg2);
- OutByte2(74H, 5); (* je @f *)
- movrc(reg2, 1); (* mov reg2, 1
- @@: *)
- cmprr(reg1, reg2);
- IF opcode = IL.opEQB THEN
- setcc(sete, reg1)
- ELSE
- setcc(setne, reg1)
- END;
- andrc(reg1, 1)
- |IL.opDROP:
- UnOp(reg1);
- drop
- |IL.opJNZ1:
- UnOp(reg1);
- test(reg1);
- jcc(jne, param1)
- |IL.opJG:
- UnOp(reg1);
- test(reg1);
- jcc(jg, param1)
- |IL.opJNZ:
- UnOp(reg1);
- test(reg1);
- jcc(jne, param1);
- drop
- |IL.opJZ:
- UnOp(reg1);
- test(reg1);
- jcc(je, param1);
- drop
- |IL.opSWITCH:
- UnOp(reg1);
- IF param2 = 0 THEN
- reg2 := eax
- ELSE
- reg2 := ecx
- END;
- IF reg1 # reg2 THEN
- ASSERT(REG.GetReg(R, reg2));
- ASSERT(REG.Exchange(R, reg1, reg2));
- drop
- END;
- drop
- |IL.opENDSW:
- |IL.opCASEL:
- cmprc(eax, param1);
- jcc(jl, param2)
- |IL.opCASER:
- cmprc(eax, param1);
- jcc(jg, param2)
- |IL.opCASELR:
- cmprc(eax, param1);
- IF param2 = cmd.param3 THEN
- jcc(jne, param2)
- ELSE
- jcc(jl, param2);
- jcc(jg, cmd.param3)
- END
- |IL.opCODE:
- OutByte(param2)
- |IL.opGET, IL.opGETC:
- IF opcode = IL.opGET THEN
- BinOp(reg1, reg2)
- ELSIF opcode = IL.opGETC THEN
- UnOp(reg2);
- reg1 := GetAnyReg();
- movrc(reg1, param1)
- END;
- drop;
- drop;
- IF param2 # 8 THEN
- _movrm(reg1, reg1, 0, param2 * 8, FALSE);
- _movrm(reg1, reg2, 0, param2 * 8, TRUE)
- ELSE
- PushAll(0);
- push(reg1);
- push(reg2);
- pushc(8);
- CallRTL(pic, IL._move)
- END
- |IL.opSAVES:
- UnOp(reg2);
- REG.PushAll_1(R);
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICDATA, stroffs + param2);
- push(reg1);
- drop
- ELSE
- OutByte(068H); (* push _data + stroffs + param2 *)
- Reloc(BIN.RDATA, stroffs + param2);
- END;
- push(reg2);
- drop;
- pushc(param1);
- CallRTL(pic, IL._move)
- |IL.opCHKIDX:
- UnOp(reg1);
- cmprc(reg1, param2);
- jcc(jb, param1)
- |IL.opCHKIDX2:
- BinOp(reg1, reg2);
- IF param2 # -1 THEN
- cmprr(reg2, reg1);
- jcc(jb, param1)
- END;
- INCL(R.regs, reg1);
- DEC(R.top);
- R.stk[R.top] := reg2
- |IL.opLEN:
- n := param2;
- UnOp(reg1);
- drop;
- EXCL(R.regs, reg1);
- WHILE n > 0 DO
- UnOp(reg2);
- drop;
- DEC(n)
- END;
- INCL(R.regs, reg1);
- ASSERT(REG.GetReg(R, reg1))
- |IL.opINCC:
- UnOp(reg1);
- IF param2 = 1 THEN
- OutByte2(0FFH, reg1) (* inc dword[reg1] *)
- ELSIF param2 = -1 THEN
- OutByte2(0FFH, reg1 + 8) (* dec dword[reg1] *)
- ELSE
- OutByte2(81H + short(param2), reg1); OutIntByte(param2) (* add dword[reg1], param2 *)
- END;
- drop
- |IL.opINC, IL.opDEC:
- BinOp(reg1, reg2);
- OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); (* add/sub dword[reg2], reg1 *)
- drop;
- drop
- |IL.opINCCB, IL.opDECCB:
- UnOp(reg1);
- OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, param2 MOD 256); (* add/sub byte[reg1], n *)
- drop
- |IL.opINCB, IL.opDECB:
- BinOp(reg1, reg2);
- OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); (* add/sub byte[reg2], reg1 *)
- drop;
- drop
- |IL.opMULS:
- BinOp(reg1, reg2);
- oprr(21H, reg1, reg2); (* and reg1, reg2 *)
- drop
- |IL.opMULSC:
- UnOp(reg1);
- andrc(reg1, param2)
- |IL.opDIVS:
- BinOp(reg1, reg2);
- xor(reg1, reg2);
- drop
- |IL.opDIVSC:
- UnOp(reg1);
- xorrc(reg1, param2)
- |IL.opADDS:
- BinOp(reg1, reg2);
- oprr(9H, reg1, reg2); (* or reg1, reg2 *)
- drop
- |IL.opSUBS:
- BinOp(reg1, reg2);
- not(reg2);
- oprr(21H, reg1, reg2); (* and reg1, reg2 *)
- drop
- |IL.opADDSC:
- UnOp(reg1);
- orrc(reg1, param2)
- |IL.opSUBSL:
- UnOp(reg1);
- not(reg1);
- andrc(reg1, param2)
- |IL.opSUBSR:
- UnOp(reg1);
- andrc(reg1, ORD(-BITS(param2)))
- |IL.opUMINS:
- UnOp(reg1);
- not(reg1)
- |IL.opLENGTH:
- PushAll(2);
- CallRTL(pic, IL._length);
- GetRegA
- |IL.opLENGTHW:
- PushAll(2);
- CallRTL(pic, IL._lengthw);
- GetRegA
- |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
- UnOp(reg1);
- IF reg1 # ecx THEN
- ASSERT(REG.GetReg(R, ecx));
- ASSERT(REG.Exchange(R, reg1, ecx));
- drop
- END;
- BinOp(reg1, reg2);
- ASSERT(reg2 = ecx);
- OutByte(0D3H);
- shift(opcode, reg1); (* shift reg1, cl *)
- drop
- |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
- UnOp(reg1);
- IF reg1 # ecx THEN
- ASSERT(REG.GetReg(R, ecx));
- ASSERT(REG.Exchange(R, reg1, ecx));
- drop
- END;
- reg1 := GetAnyReg();
- movrc(reg1, param2);
- BinOp(reg1, reg2);
- ASSERT(reg1 = ecx);
- OutByte(0D3H);
- shift(opcode, reg2); (* shift reg2, cl *)
- drop;
- drop;
- ASSERT(REG.GetReg(R, reg2))
- |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
- UnOp(reg1);
- n := param2 MOD 32;
- IF n # 1 THEN
- OutByte(0C1H)
- ELSE
- OutByte(0D1H)
- END;
- shift(opcode, reg1); (* shift reg1, n *)
- IF n # 1 THEN
- OutByte(n)
- END
- |IL.opMAX, IL.opMIN:
- BinOp(reg1, reg2);
- cmprr(reg1, reg2);
- OutByte2(07DH + ORD(opcode = IL.opMIN), 2); (* jge/jle L *)
- mov(reg1, reg2);
- (* L: *)
- drop
- |IL.opMAXC, IL.opMINC:
- UnOp(reg1);
- cmprc(reg1, param2);
- label := NewLabel();
- IF opcode = IL.opMINC THEN
- cc := jle
- ELSE
- cc := jge
- END;
- jcc(cc, label);
- movrc(reg1, param2);
- SetLabel(label)
- |IL.opIN, IL.opINR:
- IF opcode = IL.opINR THEN
- reg2 := GetAnyReg();
- movrc(reg2, param2)
- END;
- label := NewLabel();
- BinOp(reg1, reg2);
- cmprc(reg1, 32);
- OutByte2(72H, 4); (* jb L *)
- xor(reg1, reg1);
- jmp(label);
- (* L: *)
- OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); (* bt reg2, reg1 *)
- setcc(setc, reg1);
- andrc(reg1, 1);
- SetLabel(label);
- drop
- |IL.opINL:
- UnOp(reg1);
- OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); (* bt reg1, param2 *)
- setcc(setc, reg1);
- andrc(reg1, 1)
- |IL.opRSET:
- PushAll(2);
- CallRTL(pic, IL._set);
- GetRegA
- |IL.opRSETR:
- PushAll(1);
- pushc(param2);
- CallRTL(pic, IL._set);
- GetRegA
- |IL.opRSETL:
- UnOp(reg1);
- REG.PushAll_1(R);
- pushc(param2);
- push(reg1);
- drop;
- CallRTL(pic, IL._set);
- GetRegA
- |IL.opRSET1:
- PushAll(1);
- CallRTL(pic, IL._set1);
- GetRegA
- |IL.opINCL, IL.opEXCL:
- BinOp(reg1, reg2);
- cmprc(reg1, 32);
- OutByte2(73H, 03H); (* jnb L *)
- OutByte(0FH);
- IF opcode = IL.opINCL THEN
- OutByte(0ABH) (* bts dword[reg2], reg1 *)
- ELSE
- OutByte(0B3H) (* btr dword[reg2], reg1 *)
- END;
- OutByte(reg2 + 8 * reg1);
- (* L: *)
- drop;
- drop
- |IL.opINCLC:
- UnOp(reg1);
- OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); (* bts dword[reg1], param2 *)
- drop
- |IL.opEXCLC:
- UnOp(reg1);
- OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); (* btr dword[reg1], param2 *)
- drop
- |IL.opDIV:
- PushAll(2);
- CallRTL(pic, IL._divmod);
- GetRegA
- |IL.opDIVR:
- n := UTILS.Log2(param2);
- IF n > 0 THEN
- UnOp(reg1);
- IF n # 1 THEN
- OutByte3(0C1H, 0F8H + reg1, n) (* sar reg1, n *)
- ELSE
- OutByte2(0D1H, 0F8H + reg1) (* sar reg1, 1 *)
- END
- ELSIF n < 0 THEN
- PushAll(1);
- pushc(param2);
- CallRTL(pic, IL._divmod);
- GetRegA
- END
- |IL.opDIVL:
- UnOp(reg1);
- REG.PushAll_1(R);
- pushc(param2);
- push(reg1);
- drop;
- CallRTL(pic, IL._divmod);
- GetRegA
- |IL.opMOD:
- PushAll(2);
- CallRTL(pic, IL._divmod);
- mov(eax, edx);
- GetRegA
- |IL.opMODR:
- n := UTILS.Log2(param2);
- IF n > 0 THEN
- UnOp(reg1);
- andrc(reg1, param2 - 1);
- ELSIF n < 0 THEN
- PushAll(1);
- pushc(param2);
- CallRTL(pic, IL._divmod);
- mov(eax, edx);
- GetRegA
- ELSE
- UnOp(reg1);
- xor(reg1, reg1)
- END
- |IL.opMODL:
- UnOp(reg1);
- REG.PushAll_1(R);
- pushc(param2);
- push(reg1);
- drop;
- CallRTL(pic, IL._divmod);
- mov(eax, edx);
- GetRegA
- |IL.opERR:
- CallRTL(pic, IL._error)
- |IL.opABS:
- UnOp(reg1);
- test(reg1);
- OutByte2(07DH, 002H); (* jge L *)
- neg(reg1) (* neg reg1
- L: *)
- |IL.opCOPY:
- IF (0 < param2) & (param2 <= 64) THEN
- BinOp(reg1, reg2);
- reg3 := GetAnyReg();
- FOR n := 0 TO param2 - param2 MOD 4 - 1 BY 4 DO
- movrm(reg3, reg1, n);
- movmr(reg2, n, reg3)
- END;
- n := param2 - param2 MOD 4;
- IF param2 MOD 4 >= 2 THEN
- movrm16(reg3, reg1, n);
- movmr16(reg2, n, reg3);
- INC(n, 2);
- DEC(param2, 2)
- END;
- IF param2 MOD 4 = 1 THEN
- movrm8(reg3, reg1, n);
- movmr8(reg2, n, reg3);
- END;
- drop;
- drop;
- drop
- ELSE
- PushAll(2);
- pushc(param2);
- CallRTL(pic, IL._move)
- END
- |IL.opMOVE:
- PushAll(3);
- CallRTL(pic, IL._move)
- |IL.opCOPYA:
- PushAll(4);
- pushc(param2);
- CallRTL(pic, IL._arrcpy);
- GetRegA
- |IL.opCOPYS:
- PushAll(4);
- pushc(param2);
- CallRTL(pic, IL._strcpy)
- |IL.opROT:
- PushAll(0);
- push(esp);
- pushc(param2);
- CallRTL(pic, IL._rot)
- |IL.opNEW:
- PushAll(1);
- CASE TARGETS.OS OF
- |TARGETS.osWIN32:
- n := param2 + 4;
- ASSERT(UTILS.Align(n, 4))
- |TARGETS.osLINUX32:
- n := param2 + 16;
- ASSERT(UTILS.Align(n, 16))
- |TARGETS.osKOS:
- n := param2 + 8;
- ASSERT(UTILS.Align(n, 32))
- END;
- pushc(n);
- pushc(param1);
- CallRTL(pic, IL._new)
- |IL.opDISP:
- PushAll(1);
- CallRTL(pic, IL._dispose)
- |IL.opEQS .. IL.opGES:
- PushAll(4);
- pushc(opcode - IL.opEQS);
- CallRTL(pic, IL._strcmp);
- GetRegA
- |IL.opEQSW .. IL.opGESW:
- PushAll(4);
- pushc(opcode - IL.opEQSW);
- CallRTL(pic, IL._strcmpw);
- GetRegA
- |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
- UnOp(reg1);
- CASE opcode OF
- |IL.opEQP, IL.opNEP:
- IF pic THEN
- reg2 := GetAnyReg();
- Pic(reg2, BIN.PICCODE, param1);
- cmprr(reg1, reg2);
- drop
- ELSE
- OutByte2(081H, 0F8H + reg1); (* cmp reg1, L *)
- Reloc(BIN.RCODE, param1)
- END
- |IL.opEQIP, IL.opNEIP:
- IF pic THEN
- reg2 := GetAnyReg();
- Pic(reg2, BIN.PICIMP, param1);
- OutByte2(03BH, reg1 * 8 + reg2); (* cmp reg1, dword [reg2] *)
- drop
- ELSE
- OutByte2(3BH, 05H + reg1 * 8); (* cmp reg1, dword[L] *)
- Reloc(BIN.RIMP, param1)
- END
- END;
- drop;
- reg1 := GetAnyReg();
- CASE opcode OF
- |IL.opEQP, IL.opEQIP: setcc(sete, reg1)
- |IL.opNEP, IL.opNEIP: setcc(setne, reg1)
- END;
- andrc(reg1, 1)
- |IL.opPUSHT:
- UnOp(reg1);
- movrm(GetAnyReg(), reg1, -4)
- |IL.opISREC:
- PushAll(2);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._isrec);
- GetRegA
- |IL.opIS:
- PushAll(1);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._is);
- GetRegA
- |IL.opTYPEGR:
- PushAll(1);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._guardrec);
- GetRegA
- |IL.opTYPEGP:
- UnOp(reg1);
- PushAll(0);
- push(reg1);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._guard);
- GetRegA
- |IL.opTYPEGD:
- UnOp(reg1);
- PushAll(0);
- pushm(reg1, -4);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._guardrec);
- GetRegA
- |IL.opCASET:
- push(ecx);
- push(ecx);
- IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
- param2 := param2*tcount
- END;
- pushc(param2);
- CallRTL(pic, IL._guardrec);
- pop(ecx);
- test(eax);
- jcc(jne, param1)
- |IL.opPACK:
- BinOp(reg1, reg2);
- push(reg2);
- OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
- OutByte2(0DDH, reg1); (* fld qword[reg1] *)
- OutByte2(0D9H, 0FDH); (* fscale *)
- OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
- OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
- pop(reg2);
- drop;
- drop
- |IL.opPACKC:
- UnOp(reg1);
- pushc(param2);
- OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
- OutByte2(0DDH, reg1); (* fld qword[reg1] *)
- OutByte2(0D9H, 0FDH); (* fscale *)
- OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
- OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
- pop(reg1);
- drop
- |IL.opUNPK:
- BinOp(reg1, reg2);
- OutByte2(0DDH, reg1); (* fld qword[reg1] *)
- OutByte2(0D9H, 0F4H); (* fxtract *)
- OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
- OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *)
- drop;
- drop
- |IL.opPUSHF:
- ASSERT(fr >= 0);
- DEC(fr);
- subrc(esp, 8);
- OutByte3(0DDH, 01CH, 024H) (* fstp qword[esp] *)
- |IL.opLOADF:
- INC(fr);
- IF fr > MAX_FR THEN
- ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
- END;
- UnOp(reg1);
- OutByte2(0DDH, reg1); (* fld qword[reg1] *)
- drop
- |IL.opCONSTF:
- INC(fr);
- IF fr > MAX_FR THEN
- ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
- END;
- float := cmd.float;
- IF float = 0.0 THEN
- OutByte2(0D9H, 0EEH) (* fldz *)
- ELSIF float = 1.0 THEN
- OutByte2(0D9H, 0E8H) (* fld1 *)
- ELSIF float = -1.0 THEN
- OutByte2(0D9H, 0E8H); (* fld1 *)
- OutByte2(0D9H, 0E0H) (* fchs *)
- ELSE
- LoadFltConst(float)
- END
- |IL.opSAVEF, IL.opSAVEFI:
- ASSERT(fr >= 0);
- DEC(fr);
- UnOp(reg1);
- OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
- drop
- |IL.opADDF:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0C1H) (* faddp st1, st *)
- |IL.opSUBF:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0E9H) (* fsubp st1, st *)
- |IL.opSUBFI:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0E1H) (* fsubrp st1, st *)
- |IL.opMULF:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0C9H) (* fmulp st1, st *)
- |IL.opDIVF:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0F9H) (* fdivp st1, st *)
- |IL.opDIVFI:
- ASSERT(fr >= 1);
- DEC(fr);
- OutByte2(0DEH, 0F1H) (* fdivrp st1, st *)
- |IL.opUMINF:
- ASSERT(fr >= 0);
- OutByte2(0D9H, 0E0H) (* fchs *)
- |IL.opFABS:
- ASSERT(fr >= 0);
- OutByte2(0D9H, 0E1H) (* fabs *)
- |IL.opFLT:
- INC(fr);
- IF fr > MAX_FR THEN
- ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
- END;
- UnOp(reg1);
- push(reg1);
- OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *)
- pop(reg1);
- drop
- |IL.opFLOOR:
- ASSERT(fr >= 0);
- DEC(fr);
- subrc(esp, 8);
- OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); (* fstcw word[esp+4] *)
- OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); (* fstcw word[esp+6] *)
- OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); (* and word[esp+4], 1111001111111111b *)
- OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); (* or word[esp+4], 0000010000000000b *)
- OutByte2(0D9H, 06CH); OutByte2(024H, 004H); (* fldcw word[esp+4] *)
- OutByte2(0D9H, 0FCH); (* frndint *)
- OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *)
- pop(GetAnyReg());
- OutByte2(0D9H, 06CH); OutByte2(024H, 002H); (* fldcw word[esp+2] *)
- addrc(esp, 4)
- |IL.opEQF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 003H); (* jp L *)
- setcc(sete, al)
- (* L: *)
- |IL.opNEF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 003H); (* jp L *)
- setcc(setne, al)
- (* L: *)
- |IL.opLTF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 00EH); (* jp L *)
- setcc(setc, al);
- setcc(sete, ah);
- test(eax);
- setcc(sete, al);
- andrc(eax, 1)
- (* L: *)
- |IL.opGTF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 00FH); (* jp L *)
- setcc(setc, al);
- setcc(sete, ah);
- cmprc(eax, 1);
- setcc(sete, al);
- andrc(eax, 1)
- (* L: *)
- |IL.opLEF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 003H); (* jp L *)
- setcc(setnc, al)
- (* L: *)
- |IL.opGEF:
- ASSERT(fr >= 1);
- DEC(fr, 2);
- fcmp;
- OutByte2(07AH, 010H); (* jp L *)
- setcc(setc, al);
- setcc(sete, ah);
- OutByte2(000H, 0E0H); (* add al, ah *)
- OutByte2(03CH, 001H); (* cmp al, 1 *)
- setcc(sete, al);
- andrc(eax, 1)
- (* L: *)
- |IL.opINF:
- INC(fr);
- IF fr > MAX_FR THEN
- ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
- END;
- LoadFltConst(UTILS.inf)
- |IL.opLADR_UNPK:
- n := param2 * 4;
- reg1 := GetAnyReg();
- OutByte2(8DH, 45H + reg1 * 8 + long(n)); (* lea reg1, dword[ebp + n] *)
- OutIntByte(n);
- BinOp(reg1, reg2);
- OutByte2(0DDH, reg1); (* fld qword[reg1] *)
- OutByte2(0D9H, 0F4H); (* fxtract *)
- OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *)
- OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *)
- drop;
- drop
- |IL.opSADR_PARAM:
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICDATA, stroffs + param2);
- push(reg1);
- drop
- ELSE
- OutByte(068H); (* push _data + stroffs + param2 *)
- Reloc(BIN.RDATA, stroffs + param2)
- END
- |IL.opVADR_PARAM, IL.opLLOAD32_PARAM:
- pushm(ebp, param2 * 4)
- |IL.opCONST_PARAM:
- pushc(param2)
- |IL.opGLOAD32_PARAM:
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICBSS, param2);
- pushm(reg1, 0);
- drop
- ELSE
- OutByte2(0FFH, 035H); (* push dword[_bss + param2] *)
- Reloc(BIN.RBSS, param2)
- END
- |IL.opLOAD32_PARAM:
- UnOp(reg1);
- pushm(reg1, 0);
- drop
- |IL.opGADR_SAVEC:
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICBSS, param1);
- OutByte2(0C7H, reg1); (* mov dword[reg1], param2 *)
- OutInt(param2);
- drop
- ELSE
- OutByte2(0C7H, 05H); (* mov dword[_bss + param1], param2 *)
- Reloc(BIN.RBSS, param1);
- OutInt(param2)
- END
- |IL.opLADR_SAVEC:
- n := param1 * 4;
- OutByte2(0C7H, 45H + long(n)); (* mov dword[ebp + n], param2 *)
- OutIntByte(n);
- OutInt(param2)
- |IL.opLADR_SAVE:
- UnOp(reg1);
- movmr(ebp, param2 * 4, reg1);
- drop
- |IL.opLADR_INCC:
- n := param1 * 4;
- IF ABS(param2) = 1 THEN
- OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec dword[ebp + n] *)
- OutIntByte(n)
- ELSE
- OutByte2(81H + short(param2), 45H + long(n)); (* add dword[ebp + n], param2 *)
- OutIntByte(n);
- OutIntByte(param2)
- END
- |IL.opLADR_INCCB, IL.opLADR_DECCB:
- n := param1 * 4;
- IF param2 = 1 THEN
- OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* inc/dec byte[ebp + n] *)
- OutIntByte(n)
- ELSE
- OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* add/sub byte[ebp + n], param2 *)
- OutIntByte(n);
- OutByte(param2 MOD 256)
- END
- |IL.opLADR_INC, IL.opLADR_DEC:
- n := param2 * 4;
- UnOp(reg1);
- OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); (* add/sub dword[ebp + n], reg1 *)
- OutIntByte(n);
- drop
- |IL.opLADR_INCB, IL.opLADR_DECB:
- n := param2 * 4;
- UnOp(reg1);
- OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); (* add/sub byte[ebp + n], reg1 *)
- OutIntByte(n);
- drop
- |IL.opLADR_INCL, IL.opLADR_EXCL:
- n := param2 * 4;
- UnOp(reg1);
- cmprc(reg1, 32);
- label := NewLabel();
- jcc(jnb, label);
- OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); (* bts(r) dword[ebp + n], reg1 *)
- OutIntByte(n);
- SetLabel(label);
- drop
- |IL.opLADR_INCLC, IL.opLADR_EXCLC:
- n := param1 * 4;
- OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); (* bts(r) dword[ebp + n], param2 *)
- OutIntByte(n);
- OutByte(param2)
- |IL.opFNAME:
- fname := cmd(IL.FNAMECMD).fname
- END;
- cmd := cmd.next(COMMAND)
- END;
- ASSERT(R.pushed = 0);
- ASSERT(R.top = -1);
- ASSERT(fr = -1)
- END translate;
- PROCEDURE prolog (pic: BOOLEAN; target, stack, dllret: INTEGER): INTEGER;
- VAR
- reg1, entry, L, dcount: INTEGER;
- BEGIN
- entry := NewLabel();
- SetLabel(entry);
- dcount := CHL.Length(IL.codes.data);
- push(ebp);
- mov(ebp, esp);
- SetLabel(NewLabel());
- mainFltConstLabel := CodeList.last(LABEL);
- FltConstLabel := mainFltConstLabel;
- mainLocVarSize := 0;
- LocVarSize := 0;
- IF target IN {TARGETS.Win32DLL, TARGETS.KolibriOSDrv} THEN
- IF target = TARGETS.Win32DLL THEN
- pushm(ebp, 16)
- ELSE
- pushc(0)
- END;
- pushm(ebp, 12);
- pushm(ebp, 8);
- CallRTL(pic, IL._dllentry);
- test(eax);
- jcc(je, dllret);
- pushc(0)
- ELSIF target = TARGETS.KolibriOSDLL THEN
- OutByte(68H); (* push IMPORT *)
- Reloc(BIN.IMPTAB, 0)
- ELSIF target = TARGETS.KolibriOS THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.IMPTAB, 0);
- push(reg1); (* push IMPORT *)
- drop
- ELSIF target = TARGETS.Linux32 THEN
- mov(eax, ebp);
- addrc(eax, 4);
- push(eax)
- ELSE
- pushc(0)
- END;
- IF pic THEN
- reg1 := GetAnyReg();
- Pic(reg1, BIN.PICCODE, entry);
- push(reg1); (* push CODE *)
- Pic(reg1, BIN.PICDATA, 0);
- push(reg1); (* push _data *)
- pushc(tcount);
- Pic(reg1, BIN.PICDATA, tcount * 4 + dcount);
- push(reg1); (* push _data + tcount * 4 + dcount *)
- drop
- ELSE
- OutByte(68H); (* push CODE *)
- Reloc(BIN.RCODE, entry);
- OutByte(68H); (* push _data *)
- Reloc(BIN.RDATA, 0);
- pushc(tcount);
- OutByte(68H); (* push _data + tcount * 4 + dcount *)
- Reloc(BIN.RDATA, tcount * 4 + dcount)
- END;
- CallRTL(pic, IL._init);
- IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.Linux32} THEN
- L := NewLabel();
- pushc(0);
- push(esp);
- pushc(1024 * 1024 * stack);
- pushc(0);
- CallRTL(pic, IL._new);
- pop(eax);
- test(eax);
- jcc(je, L);
- addrc(eax, 1024 * 1024 * stack - 4);
- mov(esp, eax);
- SetLabel(L)
- END
- RETURN entry
- END prolog;
- PROCEDURE epilog (pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER);
- VAR
- exp: IL.EXPORT_PROC;
- path, name, ext: PATHS.PATH;
- dcount, i: INTEGER;
- PROCEDURE _import (imp: LISTS.LIST);
- VAR
- lib: IL.IMPORT_LIB;
- proc: IL.IMPORT_PROC;
- BEGIN
- lib := imp.first(IL.IMPORT_LIB);
- WHILE lib # NIL DO
- BIN.Import(program, lib.name, 0);
- proc := lib.procs.first(IL.IMPORT_PROC);
- WHILE proc # NIL DO
- BIN.Import(program, proc.name, proc.label);
- proc := proc.next(IL.IMPORT_PROC)
- END;
- lib := lib.next(IL.IMPORT_LIB)
- END
- END _import;
- BEGIN
- IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.KolibriOS, TARGETS.Linux32} THEN
- pushc(0);
- CallRTL(pic, IL._exit);
- ELSIF target = TARGETS.Win32DLL THEN
- SetLabel(dllret);
- movrc(eax, 1);
- OutByte(0C9H); (* leave *)
- OutByte3(0C2H, 0CH, 0) (* ret 12 *)
- ELSIF target = TARGETS.KolibriOSDrv THEN
- OutByte(0C9H); (* leave *)
- ret;
- SetLabel(dllret);
- movrc(eax, 0);
- OutByte(0C9H); (* leave *)
- ret
- ELSIF target = TARGETS.KolibriOSDLL THEN
- movrc(eax, 1);
- OutByte(0C9H); (* leave *)
- ret
- ELSIF target = TARGETS.KolibriOSKer THEN
- OutByte(0C9H); (* leave *)
- ret;
- ELSIF target = TARGETS.Linux32SO THEN
- OutByte(0C9H); (* leave *)
- ret;
- SetLabel(sofinit);
- CallRTL(pic, IL._sofinit);
- ret
- END;
- fixup;
- dcount := CHL.Length(IL.codes.data);
- FOR i := 0 TO tcount - 1 DO
- BIN.PutData32LE(program, CHL.GetInt(IL.codes.types, i))
- END;
- FOR i := 0 TO dcount - 1 DO
- BIN.PutData(program, CHL.GetByte(IL.codes.data, i))
- END;
- program.modname := CHL.Length(program.data);
- PATHS.split(modname, path, name, ext);
- BIN.PutDataStr(program, name);
- BIN.PutDataStr(program, ext);
- BIN.PutData(program, 0);
- IF target = TARGETS.KolibriOSDLL THEN
- BIN.Export(program, "lib_init", dllinit);
- END;
- exp := IL.codes.export.first(IL.EXPORT_PROC);
- WHILE exp # NIL DO
- BIN.Export(program, exp.name, exp.label);
- exp := exp.next(IL.EXPORT_PROC)
- END;
- _import(IL.codes._import);
- IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
- BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536))
- END epilog;
- PROCEDURE align16* (bit64: BOOLEAN);
- BEGIN
- IF TARGETS.WinLin THEN
- WHILE CHL.Length(IL.codes.data) MOD 16 # 0 DO
- CHL.PushByte(IL.codes.data, 0)
- END;
- WHILE CHL.Length(IL.codes.types) MOD (4 - 2*ORD(bit64)) # 0 DO
- CHL.PushInt(IL.codes.types, 0)
- END
- END
- END align16;
- PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
- VAR
- dllret, dllinit, sofinit: INTEGER;
- opt: PROG.OPTIONS;
- BEGIN
- FR[0] := 0;
- align16(FALSE);
- tcount := CHL.Length(IL.codes.types);
- opt := options;
- CodeList := LISTS.create(NIL);
- program := BIN.create(IL.codes.lcount);
- dllret := NewLabel();
- sofinit := NewLabel();
- IF target = TARGETS.KolibriOSDLL THEN
- opt.pic := FALSE
- END;
- IF target IN {TARGETS.KolibriOSKer, TARGETS.KolibriOSDrv} THEN
- opt.pic := TRUE
- END;
- IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN
- opt.pic := TRUE
- END;
- REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx});
- dllinit := prolog(opt.pic, target, opt.stack, dllret);
- translate(opt.pic, tcount * 4, target);
- epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit);
- BIN.fixup(program);
- IF TARGETS.OS = TARGETS.osWIN32 THEN
- PE32.write(program, outname, target = TARGETS.Win32C, target = TARGETS.Win32DLL, FALSE, opt.PE32FileAlignment)
- ELSIF target = TARGETS.KolibriOSDrv THEN
- PE32.write(program, outname, FALSE, TRUE, FALSE, 512)
- ELSIF target IN {TARGETS.KolibriOS, TARGETS.KolibriOSKer} THEN
- KOS.write(program, outname, target = TARGETS.KolibriOSKer)
- ELSIF target = TARGETS.KolibriOSDLL THEN
- MSCOFF.write(program, outname, opt.version)
- ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN
- ELF.write(program, outname, sofinit, target = TARGETS.Linux32SO, FALSE)
- END
- END CodeGen;
- PROCEDURE SetProgram* (prog: BIN.PROGRAM);
- BEGIN
- program := prog;
- CodeList := LISTS.create(NIL)
- END SetProgram;
- END X86.
|