| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408 |
- MODULE RVMxI;
- IMPORT
- PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS IN "./utils/UTILS.ob07", 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.
|