| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415 |
- (*
- BSD 2-Clause License
- Copyright (c) 2020-2022, Anton Krotov
- All rights reserved.
- *)
- MODULE RVMxI;
- IMPORT
- PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS, STRINGS, ERRORS, TARGETS;
- CONST
- LTypes = 0;
- LStrings = 1;
- LGlobal = 2;
- LHeap = 3;
- LStack = 4;
- numGPRs = 3;
- R0 = 0; R1 = 1;
- BP = 3; SP = 4;
- ACC = R0;
- GPRs = {0 .. 2} + {5 .. numGPRs + 1};
- opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5;
- opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11;
- opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15;
- opLDD = 16; (* 17, 18 *)
- opJMP = 19; opCALL = 20; opCALLI = 21;
- opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32;
- opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *)
- opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54;
- opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64;
- opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33;
- opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *)
- opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55;
- opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65;
- opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69;
- opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75;
- opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81;
- VAR
- R: REG.REGS; count, szWord: INTEGER;
- ldr, str: PROCEDURE (r1, r2: INTEGER);
- PROCEDURE OutByte (n: BYTE);
- BEGIN
- WR.WriteByte(n);
- INC(count)
- END OutByte;
- PROCEDURE OutInt (n: INTEGER);
- BEGIN
- IF szWord = 8 THEN
- WR.Write64LE(n);
- INC(count, 8)
- ELSE (* szWord = 4 *)
- WR.Write32LE(n);
- INC(count, 4)
- END
- END OutInt;
- PROCEDURE Emit (op, par1, par2: INTEGER);
- BEGIN
- OutInt(op);
- OutInt(par1);
- OutInt(par2)
- END Emit;
- PROCEDURE drop;
- BEGIN
- REG.Drop(R)
- END drop;
- PROCEDURE GetAnyReg (): INTEGER;
- RETURN REG.GetAnyReg(R)
- END GetAnyReg;
- PROCEDURE GetAcc;
- BEGIN
- ASSERT(REG.GetReg(R, ACC))
- END GetAcc;
- PROCEDURE UnOp (VAR r: INTEGER);
- BEGIN
- REG.UnOp(R, r)
- END UnOp;
- PROCEDURE BinOp (VAR r1, r2: INTEGER);
- BEGIN
- REG.BinOp(R, r1, r2)
- END BinOp;
- PROCEDURE PushAll (NumberOfParameters: INTEGER);
- BEGIN
- REG.PushAll(R);
- DEC(R.pushed, NumberOfParameters)
- END PushAll;
- PROCEDURE push (r: INTEGER);
- BEGIN
- Emit(opPUSH, r, 0)
- END push;
- PROCEDURE pop (r: INTEGER);
- BEGIN
- Emit(opPOP, r, 0)
- END pop;
- PROCEDURE mov (r1, r2: INTEGER);
- BEGIN
- Emit(opMOV, r1, r2)
- END mov;
- PROCEDURE xchg (r1, r2: INTEGER);
- BEGIN
- Emit(opXCHG, r1, r2)
- END xchg;
- PROCEDURE addrc (r, c: INTEGER);
- BEGIN
- Emit(opADDC, r, c)
- END addrc;
- PROCEDURE subrc (r, c: INTEGER);
- BEGIN
- Emit(opSUBC, r, c)
- END subrc;
- PROCEDURE movrc (r, c: INTEGER);
- BEGIN
- Emit(opMOVC, r, c)
- END movrc;
- PROCEDURE pushc (c: INTEGER);
- BEGIN
- Emit(opPUSHC, c, 0)
- END pushc;
- PROCEDURE add (r1, r2: INTEGER);
- BEGIN
- Emit(opADD, r1, r2)
- END add;
- PROCEDURE sub (r1, r2: INTEGER);
- BEGIN
- Emit(opSUB, r1, r2)
- END sub;
- PROCEDURE ldr64 (r1, r2: INTEGER);
- BEGIN
- Emit(opLDD, r2 * 256 + r1, 0)
- END ldr64;
- PROCEDURE ldr32 (r1, r2: INTEGER);
- BEGIN
- Emit(opLDW, r2 * 256 + r1, 0)
- END ldr32;
- PROCEDURE ldr16 (r1, r2: INTEGER);
- BEGIN
- Emit(opLDH, r2 * 256 + r1, 0)
- END ldr16;
- PROCEDURE ldr8 (r1, r2: INTEGER);
- BEGIN
- Emit(opLDB, r2 * 256 + r1, 0)
- END ldr8;
- PROCEDURE str64 (r1, r2: INTEGER);
- BEGIN
- Emit(opSTD, r1 * 256 + r2, 0)
- END str64;
- PROCEDURE str32 (r1, r2: INTEGER);
- BEGIN
- Emit(opSTW, r1 * 256 + r2, 0)
- END str32;
- PROCEDURE str16 (r1, r2: INTEGER);
- BEGIN
- Emit(opSTH, r1 * 256 + r2, 0)
- END str16;
- PROCEDURE str8 (r1, r2: INTEGER);
- BEGIN
- Emit(opSTB, r1 * 256 + r2, 0)
- END str8;
- PROCEDURE GlobalAdr (r, offset: INTEGER);
- BEGIN
- Emit(opLEA, r + 256 * LGlobal, offset)
- END GlobalAdr;
- PROCEDURE StrAdr (r, offset: INTEGER);
- BEGIN
- Emit(opLEA, r + 256 * LStrings, offset)
- END StrAdr;
- PROCEDURE ProcAdr (r, label: INTEGER);
- BEGIN
- Emit(opLLA, r, label)
- END ProcAdr;
- PROCEDURE jnz (r, label: INTEGER);
- BEGIN
- Emit(opCMPC, r, 0);
- Emit(opJNE, label, 0)
- END jnz;
- PROCEDURE CallRTL (proc, par: INTEGER);
- BEGIN
- Emit(opCALL, IL.codes.rtl[proc], 0);
- addrc(SP, par * szWord)
- END CallRTL;
- PROCEDURE jcc (cc: INTEGER): INTEGER;
- BEGIN
- CASE cc OF
- |IL.opEQ, IL.opEQC: cc := opJEQ
- |IL.opNE, IL.opNEC: cc := opJNE
- |IL.opLT, IL.opLTC: cc := opJLT
- |IL.opLE, IL.opLEC: cc := opJLE
- |IL.opGT, IL.opGTC: cc := opJGT
- |IL.opGE, IL.opGEC: cc := opJGE
- END
- RETURN cc
- END jcc;
- PROCEDURE shift1 (op, param: INTEGER);
- VAR
- r1, r2: INTEGER;
- BEGIN
- r2 := GetAnyReg();
- Emit(opMOVC, r2, param);
- BinOp(r1, r2);
- Emit(op, r2, r1);
- mov(r1, r2);
- drop
- END shift1;
- PROCEDURE shift (op: INTEGER);
- VAR
- r1, r2: INTEGER;
- BEGIN
- BinOp(r1, r2);
- Emit(op, r1, r2);
- drop
- END shift;
- PROCEDURE translate (szWord: INTEGER);
- VAR
- cmd, next: IL.COMMAND;
- opcode, param1, param2, r1, r2, r3,
- a, b, label, opLD, opST, opSTC: INTEGER;
- BEGIN
- IF szWord = 8 THEN
- opLD := opLDD;
- opST := opSTD;
- opSTC := opSTDC
- ELSE
- opLD := opLDW;
- opST := opSTW;
- opSTC := opSTWC
- END;
- cmd := IL.codes.commands.first(IL.COMMAND);
- WHILE cmd # NIL DO
- param1 := cmd.param1;
- param2 := cmd.param2;
- opcode := cmd.opcode;
- CASE opcode OF
- |IL.opJMP:
- Emit(opJMP, param1, 0)
- |IL.opLABEL:
- Emit(opLABEL, param1, 0)
- |IL.opCALL:
- Emit(opCALL, param1, 0)
- |IL.opCALLP:
- UnOp(r1);
- Emit(opCALLI, r1, 0);
- drop;
- ASSERT(R.top = -1)
- |IL.opPUSHC:
- pushc(param2)
- |IL.opCLEANUP:
- IF param2 # 0 THEN
- addrc(SP, param2 * szWord)
- END
- |IL.opNOP, IL.opAND, IL.opOR:
- |IL.opSADR:
- StrAdr(GetAnyReg(), param2)
- |IL.opGADR:
- GlobalAdr(GetAnyReg(), param2)
- |IL.opLADR:
- param2 := param2 * szWord;
- next := cmd.next(IL.COMMAND);
- IF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 8) OR (next.opcode = IL.opSAVE64) THEN
- UnOp(r1);
- Emit(opSTD, BP * 256 + r1, param2);
- drop;
- cmd := next
- ELSIF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 4) OR (next.opcode = IL.opSAVE32) THEN
- UnOp(r1);
- Emit(opSTW, BP * 256 + r1, param2);
- drop;
- cmd := next
- ELSIF next.opcode = IL.opSAVE16 THEN
- UnOp(r1);
- Emit(opSTH, BP * 256 + r1, param2);
- drop;
- cmd := next
- ELSIF next.opcode = IL.opSAVE8 THEN
- UnOp(r1);
- Emit(opSTB, BP * 256 + r1, param2);
- drop;
- cmd := next
- ELSE
- Emit(opADDRC, BP * 256 + GetAnyReg(), param2)
- END
- |IL.opPARAM:
- IF param2 = 1 THEN
- UnOp(r1);
- push(r1);
- drop
- ELSE
- ASSERT(R.top + 1 <= param2);
- PushAll(param2)
- END
- |IL.opONERR:
- pushc(param2);
- Emit(opJMP, param1, 0)
- |IL.opPRECALL:
- PushAll(0)
- |IL.opRES, IL.opRESF:
- ASSERT(R.top = -1);
- GetAcc
- |IL.opENTER:
- ASSERT(R.top = -1);
- Emit(opLABEL, param1, 0);
- Emit(opENTER, param2, 0)
- |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
- IF opcode # IL.opLEAVE THEN
- UnOp(r1);
- IF r1 # ACC THEN
- mov(ACC, r1)
- END;
- drop
- END;
- ASSERT(R.top = -1);
- IF param1 > 0 THEN
- mov(SP, BP)
- END;
- pop(BP);
- Emit(opRET, 0, 0)
- |IL.opLEAVEC:
- Emit(opRET, 0, 0)
- |IL.opCONST:
- next := cmd.next(IL.COMMAND);
- IF (next.opcode = IL.opPARAM) & (next.param2 = 1) THEN
- pushc(param2);
- cmd := next
- ELSE
- movrc(GetAnyReg(), param2)
- END
- |IL.opDROP:
- UnOp(r1);
- drop
- |IL.opSAVEC:
- UnOp(r1);
- Emit(opSTC, r1, param2);
- drop
- |IL.opSAVE8C:
- UnOp(r1);
- Emit(opSTBC, r1, param2 MOD 256);
- drop
- |IL.opSAVE16C:
- UnOp(r1);
- Emit(opSTHC, r1, param2 MOD 65536);
- drop
- |IL.opSAVE, IL.opSAVEF:
- BinOp(r2, r1);
- str(r1, r2);
- drop;
- drop
- |IL.opSAVE32:
- BinOp(r2, r1);
- str32(r1, r2);
- drop;
- drop
- |IL.opSAVE64:
- BinOp(r2, r1);
- str64(r1, r2);
- drop;
- drop
- |IL.opSAVEFI:
- BinOp(r2, r1);
- str(r2, r1);
- drop;
- drop
- |IL.opSAVE8:
- BinOp(r2, r1);
- str8(r1, r2);
- drop;
- drop
- |IL.opSAVE16:
- BinOp(r2, r1);
- str16(r1, r2);
- drop;
- drop
- |IL.opGLOAD32:
- r1 := GetAnyReg();
- GlobalAdr(r1, param2);
- ldr32(r1, r1)
- |IL.opGLOAD64:
- r1 := GetAnyReg();
- GlobalAdr(r1, param2);
- ldr64(r1, r1)
- |IL.opVADR:
- Emit(opLD, BP * 256 + GetAnyReg(), param2 * szWord)
- |IL.opLLOAD32:
- Emit(opLDW, BP * 256 + GetAnyReg(), param2 * szWord)
- |IL.opLLOAD64:
- Emit(opLDD, BP * 256 + GetAnyReg(), param2 * szWord)
- |IL.opVLOAD32:
- r1 := GetAnyReg();
- Emit(opLD, BP * 256 + r1, param2 * szWord);
- ldr32(r1, r1)
- |IL.opVLOAD64:
- r1 := GetAnyReg();
- Emit(opLDD, BP * 256 + r1, param2 * szWord);
- ldr64(r1, r1)
- |IL.opGLOAD16:
- r1 := GetAnyReg();
- GlobalAdr(r1, param2);
- ldr16(r1, r1)
- |IL.opLLOAD16:
- Emit(opLDH, BP * 256 + GetAnyReg(), param2 * szWord)
- |IL.opVLOAD16:
- r1 := GetAnyReg();
- Emit(opLD, BP * 256 + r1, param2 * szWord);
- ldr16(r1, r1)
- |IL.opGLOAD8:
- r1 := GetAnyReg();
- GlobalAdr(r1, param2);
- ldr8(r1, r1)
- |IL.opLLOAD8:
- Emit(opLDB, BP * 256 + GetAnyReg(), param2 * szWord)
- |IL.opVLOAD8:
- r1 := GetAnyReg();
- Emit(opLD, BP * 256 + r1, param2 * szWord);
- ldr8(r1, r1)
- |IL.opLOAD8:
- UnOp(r1);
- ldr8(r1, r1)
- |IL.opLOAD16:
- UnOp(r1);
- ldr16(r1, r1)
- |IL.opLOAD32:
- UnOp(r1);
- ldr32(r1, r1)
- |IL.opLOAD64:
- UnOp(r1);
- ldr64(r1, r1)
- |IL.opLOADF:
- UnOp(r1);
- ldr(r1, r1)
- |IL.opUMINUS:
- UnOp(r1);
- Emit(opNEG, r1, 0)
- |IL.opADD:
- BinOp(r1, r2);
- add(r1, r2);
- drop
- |IL.opSUB:
- BinOp(r1, r2);
- sub(r1, r2);
- drop
- |IL.opADDC:
- UnOp(r1);
- next := cmd.next(IL.COMMAND);
- CASE next.opcode OF
- |IL.opLOADF:
- Emit(opLD, r1 * 256 + r1, param2);
- cmd := next
- |IL.opLOAD64:
- Emit(opLDD, r1 * 256 + r1, param2);
- cmd := next
- |IL.opLOAD32:
- Emit(opLDW, r1 * 256 + r1, param2);
- cmd := next
- |IL.opLOAD16:
- Emit(opLDH, r1 * 256 + r1, param2);
- cmd := next
- |IL.opLOAD8:
- Emit(opLDB, r1 * 256 + r1, param2);
- cmd := next
- ELSE
- addrc(r1, param2)
- END
- |IL.opSUBR:
- UnOp(r1);
- subrc(r1, param2)
- |IL.opSUBL:
- UnOp(r1);
- subrc(r1, param2);
- Emit(opNEG, r1, 0)
- |IL.opMULC:
- UnOp(r1);
- Emit(opMULC, r1, param2)
- |IL.opMUL:
- BinOp(r1, r2);
- Emit(opMUL, r1, r2);
- drop
- |IL.opDIV:
- BinOp(r1, r2);
- Emit(opDIV, r1, r2);
- drop
- |IL.opMOD:
- BinOp(r1, r2);
- Emit(opMOD, r1, r2);
- drop
- |IL.opDIVR:
- UnOp(r1);
- Emit(opDIVC, r1, param2)
- |IL.opMODR:
- UnOp(r1);
- Emit(opMODC, r1, param2)
- |IL.opDIVL:
- UnOp(r1);
- r2 := GetAnyReg();
- movrc(r2, param2);
- Emit(opDIV, r2, r1);
- mov(r1, r2);
- drop
- |IL.opMODL:
- UnOp(r1);
- r2 := GetAnyReg();
- movrc(r2, param2);
- Emit(opMOD, r2, r1);
- mov(r1, r2);
- drop
- |IL.opEQ .. IL.opGE, IL.opEQC .. IL.opGEC:
- IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
- BinOp(r1, r2);
- Emit(opCMP, r1, r2);
- drop
- ELSE
- UnOp(r1);
- Emit(opCMPC, r1, param2)
- END;
- next := cmd.next(IL.COMMAND);
- IF next.opcode = IL.opJZ THEN
- Emit(ORD(BITS(jcc(opcode)) / {0}), next.param1, 0);
- cmd := next;
- drop
- ELSIF next.opcode = IL.opJNZ THEN
- Emit(jcc(opcode), next.param1, 0);
- cmd := next;
- drop
- ELSE
- Emit(jcc(opcode) + 6, r1, 0)
- END
- |IL.opJNZ1:
- UnOp(r1);
- jnz(r1, param1)
- |IL.opJG:
- UnOp(r1);
- Emit(opCMPC, r1, 0);
- Emit(opJGT, param1, 0)
- |IL.opJNZ:
- UnOp(r1);
- jnz(r1, param1);
- drop
- |IL.opJZ:
- UnOp(r1);
- Emit(opCMPC, r1, 0);
- Emit(opJEQ, param1, 0);
- drop
- |IL.opMULS:
- BinOp(r1, r2);
- Emit(opAND, r1, r2);
- drop
- |IL.opMULSC:
- UnOp(r1);
- Emit(opANDC, r1, param2)
- |IL.opDIVS:
- BinOp(r1, r2);
- Emit(opXOR, r1, r2);
- drop
- |IL.opDIVSC:
- UnOp(r1);
- Emit(opXORC, r1, param2)
- |IL.opADDS:
- BinOp(r1, r2);
- Emit(opOR, r1, r2);
- drop
- |IL.opSUBS:
- BinOp(r1, r2);
- Emit(opNOT, r2, 0);
- Emit(opAND, r1, r2);
- drop
- |IL.opADDSC:
- UnOp(r1);
- Emit(opORC, r1, param2)
- |IL.opSUBSL:
- UnOp(r1);
- Emit(opNOT, r1, 0);
- Emit(opANDC, r1, param2)
- |IL.opSUBSR:
- UnOp(r1);
- Emit(opANDC, r1, ORD(-BITS(param2)))
- |IL.opUMINS:
- UnOp(r1);
- Emit(opNOT, r1, 0)
- |IL.opASR:
- shift(opASR)
- |IL.opLSL:
- shift(opLSL)
- |IL.opROR:
- shift(opROR)
- |IL.opLSR:
- shift(opLSR)
- |IL.opASR1:
- shift1(opASR, param2)
- |IL.opLSL1:
- shift1(opLSL, param2)
- |IL.opROR1:
- shift1(opROR, param2)
- |IL.opLSR1:
- shift1(opLSR, param2)
- |IL.opASR2:
- UnOp(r1);
- Emit(opASRC, r1, param2 MOD (szWord * 8))
- |IL.opLSL2:
- UnOp(r1);
- Emit(opLSLC, r1, param2 MOD (szWord * 8))
- |IL.opROR2:
- UnOp(r1);
- Emit(opRORC, r1, param2 MOD (szWord * 8))
- |IL.opLSR2:
- UnOp(r1);
- Emit(opLSRC, r1, param2 MOD (szWord * 8))
- |IL.opABS:
- UnOp(r1);
- Emit(opCMPC, r1, 0);
- label := IL.NewLabel();
- Emit(opJGE, label, 0);
- Emit(opNEG, r1, 0);
- Emit(opLABEL, label, 0)
- |IL.opLEN:
- UnOp(r1);
- drop;
- EXCL(R.regs, r1);
- WHILE param2 > 0 DO
- UnOp(r2);
- drop;
- DEC(param2)
- END;
- INCL(R.regs, r1);
- ASSERT(REG.GetReg(R, r1))
- |IL.opSWITCH:
- UnOp(r1);
- IF param2 = 0 THEN
- r2 := ACC
- ELSE
- r2 := R1
- END;
- IF r1 # r2 THEN
- ASSERT(REG.GetReg(R, r2));
- ASSERT(REG.Exchange(R, r1, r2));
- drop
- END;
- drop
- |IL.opENDSW:
- |IL.opCASEL:
- Emit(opCMPC, ACC, param1);
- Emit(opJLT, param2, 0)
- |IL.opCASER:
- Emit(opCMPC, ACC, param1);
- Emit(opJGT, param2, 0)
- |IL.opCASELR:
- Emit(opCMPC, ACC, param1);
- IF param2 = cmd.param3 THEN
- Emit(opJNE, param2, 0)
- ELSE
- Emit(opJLT, param2, 0);
- Emit(opJGT, cmd.param3, 0)
- END
- |IL.opSBOOL:
- BinOp(r2, r1);
- Emit(opCMPC, r2, 0);
- Emit(opSNE, r2, 0);
- str8(r1, r2);
- drop;
- drop
- |IL.opSBOOLC:
- UnOp(r1);
- Emit(opSTBC, r1, ORD(param2 # 0));
- drop
- |IL.opINCC:
- UnOp(r1);
- r2 := GetAnyReg();
- ldr(r2, r1);
- addrc(r2, param2);
- str(r1, r2);
- drop;
- drop
- |IL.opINCCB, IL.opDECCB:
- IF opcode = IL.opDECCB THEN
- param2 := -param2
- END;
- UnOp(r1);
- r2 := GetAnyReg();
- ldr8(r2, r1);
- addrc(r2, param2);
- str8(r1, r2);
- drop;
- drop
- |IL.opINCB, IL.opDECB:
- BinOp(r2, r1);
- r3 := GetAnyReg();
- ldr8(r3, r1);
- IF opcode = IL.opINCB THEN
- add(r3, r2)
- ELSE
- sub(r3, r2)
- END;
- str8(r1, r3);
- drop;
- drop;
- drop
- |IL.opINC, IL.opDEC:
- BinOp(r2, r1);
- r3 := GetAnyReg();
- ldr(r3, r1);
- IF opcode = IL.opINC THEN
- add(r3, r2)
- ELSE
- sub(r3, r2)
- END;
- str(r1, r3);
- drop;
- drop;
- drop
- |IL.opINCL, IL.opEXCL:
- BinOp(r2, r1);
- Emit(opBIT, r2, r2);
- r3 := GetAnyReg();
- ldr(r3, r1);
- IF opcode = IL.opINCL THEN
- Emit(opOR, r3, r2)
- ELSE
- Emit(opNOT, r2, 0);
- Emit(opAND, r3, r2)
- END;
- str(r1, r3);
- drop;
- drop;
- drop
- |IL.opINCLC, IL.opEXCLC:
- UnOp(r1);
- r2 := GetAnyReg();
- ldr(r2, r1);
- IF opcode = IL.opINCLC THEN
- Emit(opORC, r2, ORD({param2}))
- ELSE
- Emit(opANDC, r2, ORD(-{param2}))
- END;
- str(r1, r2);
- drop;
- drop
- |IL.opEQB, IL.opNEB:
- BinOp(r1, r2);
- Emit(opCMPC, r1, 0);
- Emit(opSNE, r1, 0);
- Emit(opCMPC, r2, 0);
- Emit(opSNE, r2, 0);
- Emit(opCMP, r1, r2);
- IF opcode = IL.opEQB THEN
- Emit(opSEQ, r1, 0)
- ELSE
- Emit(opSNE, r1, 0)
- END;
- drop
- |IL.opCHKIDX:
- UnOp(r1);
- Emit(opCMPC, r1, param2);
- Emit(opJBT, param1, 0)
- |IL.opCHKIDX2:
- BinOp(r1, r2);
- IF param2 # -1 THEN
- Emit(opCMP, r2, r1);
- Emit(opJBT, param1, 0)
- END;
- INCL(R.regs, r1);
- DEC(R.top);
- R.stk[R.top] := r2
- |IL.opEQP, IL.opNEP:
- ProcAdr(GetAnyReg(), param1);
- BinOp(r1, r2);
- Emit(opCMP, r1, r2);
- IF opcode = IL.opEQP THEN
- Emit(opSEQ, r1, 0)
- ELSE
- Emit(opSNE, r1, 0)
- END;
- drop
- |IL.opSAVEP:
- UnOp(r1);
- r2 := GetAnyReg();
- ProcAdr(r2, param2);
- str(r1, r2);
- drop;
- drop
- |IL.opPUSHP:
- ProcAdr(GetAnyReg(), param2)
- |IL.opPUSHT:
- UnOp(r1);
- Emit(opLD, r1 * 256 + GetAnyReg(), -szWord)
- |IL.opGET, IL.opGETC:
- IF opcode = IL.opGET THEN
- BinOp(r1, r2)
- ELSIF opcode = IL.opGETC THEN
- UnOp(r2);
- r1 := GetAnyReg();
- movrc(r1, param1)
- END;
- drop;
- drop;
- CASE param2 OF
- |1: ldr8(r1, r1); str8(r2, r1)
- |2: ldr16(r1, r1); str16(r2, r1)
- |4: ldr32(r1, r1); str32(r2, r1)
- |8: ldr64(r1, r1); str64(r2, r1)
- END
- |IL.opNOT:
- UnOp(r1);
- Emit(opCMPC, r1, 0);
- Emit(opSEQ, r1, 0)
- |IL.opORD:
- UnOp(r1);
- Emit(opCMPC, r1, 0);
- Emit(opSNE, r1, 0)
- |IL.opMIN, IL.opMAX:
- BinOp(r1, r2);
- Emit(opCMP, r1, r2);
- label := IL.NewLabel();
- IF opcode = IL.opMIN THEN
- Emit(opJLE, label, 0)
- ELSE
- Emit(opJGE, label, 0)
- END;
- Emit(opMOV, r1, r2);
- Emit(opLABEL, label, 0);
- drop
- |IL.opMINC, IL.opMAXC:
- UnOp(r1);
- Emit(opCMPC, r1, param2);
- label := IL.NewLabel();
- IF opcode = IL.opMINC THEN
- Emit(opJLE, label, 0)
- ELSE
- Emit(opJGE, label, 0)
- END;
- Emit(opMOVC, r1, param2);
- Emit(opLABEL, label, 0)
- |IL.opIN:
- BinOp(r1, r2);
- Emit(opBIT, r1, r1);
- Emit(opAND, r1, r2);
- Emit(opCMPC, r1, 0);
- Emit(opSNE, r1, 0);
- drop
- |IL.opINL:
- UnOp(r1);
- Emit(opANDC, r1, ORD({param2}));
- Emit(opCMPC, r1, 0);
- Emit(opSNE, r1, 0)
- |IL.opINR:
- UnOp(r1);
- Emit(opBIT, r1, r1);
- Emit(opANDC, r1, param2);
- Emit(opCMPC, r1, 0);
- Emit(opSNE, r1, 0)
- |IL.opERR:
- CallRTL(IL._error, 4)
- |IL.opEQS .. IL.opGES:
- PushAll(4);
- pushc(opcode - IL.opEQS);
- CallRTL(IL._strcmp, 5);
- GetAcc
- |IL.opEQSW .. IL.opGESW:
- PushAll(4);
- pushc(opcode - IL.opEQSW);
- CallRTL(IL._strcmpw, 5);
- GetAcc
- |IL.opCOPY:
- PushAll(2);
- pushc(param2);
- CallRTL(IL._move, 3)
- |IL.opMOVE:
- PushAll(3);
- CallRTL(IL._move, 3)
- |IL.opCOPYA:
- PushAll(4);
- pushc(param2);
- CallRTL(IL._arrcpy, 5);
- GetAcc
- |IL.opCOPYS:
- PushAll(4);
- pushc(param2);
- CallRTL(IL._strcpy, 5)
- |IL.opROT:
- PushAll(0);
- mov(ACC, SP);
- push(ACC);
- pushc(param2);
- CallRTL(IL._rot, 2)
- |IL.opLENGTH:
- PushAll(2);
- CallRTL(IL._length, 2);
- GetAcc
- |IL.opLENGTHW:
- PushAll(2);
- CallRTL(IL._lengthw, 2);
- GetAcc
- |IL.opSAVES:
- UnOp(r2);
- REG.PushAll_1(R);
- r1 := GetAnyReg();
- StrAdr(r1, param2);
- push(r1);
- drop;
- push(r2);
- drop;
- pushc(param1);
- CallRTL(IL._move, 3)
- |IL.opRSET:
- PushAll(2);
- CallRTL(IL._set, 2);
- GetAcc
- |IL.opRSETR:
- PushAll(1);
- pushc(param2);
- CallRTL(IL._set, 2);
- GetAcc
- |IL.opRSETL:
- UnOp(r1);
- REG.PushAll_1(R);
- pushc(param2);
- push(r1);
- drop;
- CallRTL(IL._set, 2);
- GetAcc
- |IL.opRSET1:
- PushAll(1);
- CallRTL(IL._set1, 1);
- GetAcc
- |IL.opNEW:
- PushAll(1);
- INC(param2, szWord);
- ASSERT(UTILS.Align(param2, szWord));
- pushc(param2);
- pushc(param1);
- CallRTL(IL._new, 3)
- |IL.opTYPEGP:
- UnOp(r1);
- PushAll(0);
- push(r1);
- pushc(param2);
- CallRTL(IL._guard, 2);
- GetAcc
- |IL.opIS:
- PushAll(1);
- pushc(param2);
- CallRTL(IL._is, 2);
- GetAcc
- |IL.opISREC:
- PushAll(2);
- pushc(param2);
- CallRTL(IL._guardrec, 3);
- GetAcc
- |IL.opTYPEGR:
- PushAll(1);
- pushc(param2);
- CallRTL(IL._guardrec, 2);
- GetAcc
- |IL.opTYPEGD:
- UnOp(r1);
- PushAll(0);
- subrc(r1, szWord);
- ldr(r1, r1);
- push(r1);
- pushc(param2);
- CallRTL(IL._guardrec, 2);
- GetAcc
- |IL.opCASET:
- push(R1);
- push(R1);
- pushc(param2);
- CallRTL(IL._guardrec, 2);
- pop(R1);
- jnz(ACC, param1)
- |IL.opCONSTF:
- IF szWord = 8 THEN
- movrc(GetAnyReg(), UTILS.splitf(cmd.float, a, b))
- ELSE (* szWord = 4 *)
- movrc(GetAnyReg(), UTILS.d2s(cmd.float))
- END
- |IL.opMULF:
- PushAll(2);
- CallRTL(IL._fmul, 2);
- GetAcc
- |IL.opDIVF:
- PushAll(2);
- CallRTL(IL._fdiv, 2);
- GetAcc
- |IL.opDIVFI:
- PushAll(2);
- CallRTL(IL._fdivi, 2);
- GetAcc
- |IL.opADDF:
- PushAll(2);
- CallRTL(IL._fadd, 2);
- GetAcc
- |IL.opSUBFI:
- PushAll(2);
- CallRTL(IL._fsubi, 2);
- GetAcc
- |IL.opSUBF:
- PushAll(2);
- CallRTL(IL._fsub, 2);
- GetAcc
- |IL.opEQF..IL.opGEF:
- PushAll(2);
- pushc(opcode - IL.opEQF);
- CallRTL(IL._fcmp, 3);
- GetAcc
- |IL.opFLOOR:
- PushAll(1);
- CallRTL(IL._floor, 1);
- GetAcc
- |IL.opFLT:
- PushAll(1);
- CallRTL(IL._flt, 1);
- GetAcc
- |IL.opUMINF:
- UnOp(r1);
- Emit(opRORC, r1, -1);
- Emit(opXORC, r1, 1);
- Emit(opRORC, r1, 1)
- |IL.opFABS:
- UnOp(r1);
- Emit(opLSLC, r1, 1);
- Emit(opLSRC, r1, 1)
- |IL.opINF:
- r1 := GetAnyReg();
- Emit(opMOVC, r1, 1);
- Emit(opRORC, r1, 1);
- Emit(opASRC, r1, 7 + 3 * ORD(szWord = 8));
- Emit(opLSRC, r1, 1)
- |IL.opPUSHF:
- UnOp(r1);
- push(r1);
- drop
- |IL.opPACK:
- PushAll(2);
- CallRTL(IL._pack, 2)
- |IL.opPACKC:
- PushAll(1);
- pushc(param2);
- CallRTL(IL._pack, 2)
- |IL.opUNPK:
- PushAll(2);
- CallRTL(IL._unpk, 2)
- |IL.opCODE:
- OutInt(param2)
- |IL.opLADR_SAVE:
- UnOp(r1);
- Emit(opST, BP * 256 + r1, param2 * szWord);
- drop
- |IL.opLADR_INCC:
- r1 := GetAnyReg();
- Emit(opLD, BP * 256 + r1, param1 * szWord);
- Emit(opADDC, r1, param2);
- Emit(opST, BP * 256 + r1, param1 * szWord);
- drop
- END;
- cmd := cmd.next(IL.COMMAND)
- END;
- ASSERT(R.pushed = 0);
- ASSERT(R.top = -1)
- END translate;
- PROCEDURE prolog;
- BEGIN
- Emit(opLEA, SP + LStack * 256, 0);
- Emit(opLEA, ACC + LTypes * 256, 0);
- push(ACC);
- Emit(opLEA, ACC + LHeap * 256, 0);
- push(ACC);
- pushc(CHL.Length(IL.codes.types));
- CallRTL(IL._init, 3)
- END prolog;
- PROCEDURE epilog (ram, szWord: INTEGER);
- VAR
- tcount, dcount, i, offTypes, offStrings,
- szData, szGlobal, szHeapStack: INTEGER;
- BEGIN
- Emit(opSTOP, 0, 0);
- offTypes := count;
- tcount := CHL.Length(IL.codes.types);
- FOR i := 0 TO tcount - 1 DO
- OutInt(CHL.GetInt(IL.codes.types, i))
- END;
- offStrings := count;
- dcount := CHL.Length(IL.codes.data);
- FOR i := 0 TO dcount - 1 DO
- OutByte(CHL.GetByte(IL.codes.data, i))
- END;
- IF dcount MOD szWord # 0 THEN
- i := szWord - dcount MOD szWord;
- WHILE i > 0 DO
- OutByte(0);
- DEC(i)
- END
- END;
- szData := count - offTypes;
- szGlobal := (IL.codes.bss DIV szWord + 1) * szWord;
- szHeapStack := ram - szData - szGlobal;
- OutInt(offTypes);
- OutInt(offStrings);
- OutInt(szGlobal DIV szWord);
- OutInt(szHeapStack DIV szWord);
- FOR i := 1 TO 8 DO
- OutInt(0)
- END
- END epilog;
- PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
- CONST
- minRAM = 32*1024;
- maxRAM = 256*1024;
- VAR
- szData, szRAM: INTEGER;
- BEGIN
- szWord := TARGETS.WordSize;
- IF szWord = 8 THEN
- ldr := ldr64;
- str := str64
- ELSE
- ldr := ldr32;
- str := str32
- END;
- szData := (CHL.Length(IL.codes.types) + CHL.Length(IL.codes.data) DIV szWord + IL.codes.bss DIV szWord + 2) * szWord;
- szRAM := MIN(MAX(options.ram, minRAM), maxRAM) * 1024;
- IF szRAM - szData < 1024*1024 THEN
- ERRORS.Error(208)
- END;
- count := 0;
- WR.Create(outname);
- REG.Init(R, push, pop, mov, xchg, GPRs);
- prolog;
- translate(szWord);
- epilog(szRAM, szWord);
- WR.Close
- END CodeGen;
- END RVMxI.
|