| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538 |
- MODULE X86;
- IMPORT IL, REG, UTILS IN "./utils/UTILS.ob07", 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.
|