| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771 |
- (*
- BSD 2-Clause License
- Copyright (c) 2019-2022, Anton Krotov
- All rights reserved.
- *)
- MODULE MSP430;
- IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX,
- UTILS, C := CONSOLE, PROG, RTL := MSP430RTL;
- CONST
- chkSTK* = 6;
- minRAM* = 128; maxRAM* = 2048;
- minROM* = 2048; maxROM* = 24576;
- StkReserve = RTL.StkReserve;
- IntVectorSize* = RTL.IntVectorSize;
- PC = 0; SP = 1; SR = 2; CG = 3;
- R4 = 4; R5 = 5; R6 = 6; R7 = 7;
- HP = RTL.HP;
- ACC = R4;
- opRRC = 1000H; opSWPB = 1080H; opRRA = 1100H; opSXT = 1180H;
- opPUSH = 1200H; opCALL = 1280H; opRETI = 1300H;
- opMOV = 04000H; opADD = 05000H; opADDC = 06000H; opSUBC = 07000H;
- opSUB = 08000H; opCMP = 09000H; opDADD = 0A000H; opBIT = 0B000H;
- opBIC = 0C000H; opBIS = 0D000H; opXOR = 0E000H; opAND = 0F000H;
- opJNE = 2000H; opJEQ = 2400H; opJNC = 2800H; opJC = 2C00H;
- opJN = 3000H; opJGE = 3400H; opJL = 3800H; opJMP = 3C00H;
- sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128;
- NOWORD = 10000H;
- RCODE = 0; RDATA = 1; RBSS = 2;
- je = 0; jne = je + 1;
- jge = 2; jl = jge + 1;
- jle = 4; jg = jle + 1;
- jb = 6;
- TYPE
- ANYCODE = POINTER TO RECORD (LISTS.ITEM)
- offset: INTEGER
- END;
- WORD = POINTER TO RECORD (ANYCODE)
- val: INTEGER
- END;
- LABEL = POINTER TO RECORD (ANYCODE)
- num: INTEGER
- END;
- JMP = POINTER TO RECORD (ANYCODE)
- cc, label: INTEGER;
- short: BOOLEAN
- END;
- CALL = POINTER TO RECORD (ANYCODE)
- label: INTEGER
- END;
- COMMAND = IL.COMMAND;
- RELOC = POINTER TO RECORD (LISTS.ITEM)
- section: INTEGER;
- WordPtr: WORD
- END;
- VAR
- R: REG.REGS;
- CodeList: LISTS.LIST;
- RelList: LISTS.LIST;
- mem: ARRAY 65536 OF BYTE;
- Labels: CHL.INTLIST;
- IV: ARRAY RTL.LenIV OF INTEGER;
- IdxWords: RECORD src, dst: INTEGER END;
- StkCnt, MaxStkCnt: INTEGER;
- PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN;
- RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize
- END CheckProcDataSize;
- PROCEDURE EmitLabel (L: INTEGER);
- VAR
- label: LABEL;
- BEGIN
- NEW(label);
- label.num := L;
- LISTS.push(CodeList, label)
- END EmitLabel;
- PROCEDURE EmitWord (val: INTEGER);
- VAR
- word: WORD;
- BEGIN
- IF val < 0 THEN
- ASSERT(val >= -32768);
- val := val MOD 65536
- ELSE
- ASSERT(val <= 65535)
- END;
- NEW(word);
- word.val := val;
- LISTS.push(CodeList, word)
- END EmitWord;
- PROCEDURE EmitJmp (cc, label: INTEGER);
- VAR
- jmp: JMP;
- BEGIN
- NEW(jmp);
- jmp.cc := cc;
- jmp.label := label;
- jmp.short := FALSE;
- LISTS.push(CodeList, jmp)
- END EmitJmp;
- PROCEDURE EmitCall (label: INTEGER);
- VAR
- call: CALL;
- BEGIN
- NEW(call);
- call.label := label;
- LISTS.push(CodeList, call)
- END EmitCall;
- PROCEDURE IncStk;
- BEGIN
- INC(StkCnt);
- MaxStkCnt := MAX(StkCnt, MaxStkCnt)
- END IncStk;
- PROCEDURE bw (b: BOOLEAN): INTEGER;
- RETURN BW * ORD(b)
- END bw;
- PROCEDURE src_x (x, Rn: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN
- res := Rn * 256 + sINDIR
- ELSE
- IdxWords.src := x;
- res := Rn * 256 + sIDX
- END
- RETURN res
- END src_x;
- PROCEDURE dst_x (x, Rn: INTEGER): INTEGER;
- BEGIN
- IdxWords.dst := x
- RETURN Rn + dIDX
- END dst_x;
- PROCEDURE indir (Rn: INTEGER): INTEGER;
- RETURN Rn * 256 + sINDIR
- END indir;
- PROCEDURE incr (Rn: INTEGER): INTEGER;
- RETURN Rn * 256 + sINCR
- END incr;
- PROCEDURE imm (x: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- CASE x OF
- | 0: res := CG * 256
- | 1: res := CG * 256 + sIDX
- | 2: res := indir(CG)
- | 4: res := indir(SR)
- | 8: res := incr(SR)
- |-1: res := incr(CG)
- ELSE
- res := incr(PC);
- IdxWords.src := x
- END
- RETURN res
- END imm;
- PROCEDURE Op2 (op, src, dst: INTEGER);
- BEGIN
- ASSERT(BITS(op) - {6, 12..15} = {});
- ASSERT(BITS(src) - {4, 5, 8..11} = {});
- ASSERT(BITS(dst) - {0..3, 7} = {});
- EmitWord(op + src + dst);
- IF IdxWords.src # NOWORD THEN
- EmitWord(IdxWords.src);
- IdxWords.src := NOWORD
- END;
- IF IdxWords.dst # NOWORD THEN
- EmitWord(IdxWords.dst);
- IdxWords.dst := NOWORD
- END
- END Op2;
- PROCEDURE Op1 (op, reg, As: INTEGER);
- BEGIN
- EmitWord(op + reg + As)
- END Op1;
- PROCEDURE MovRR (src, dst: INTEGER);
- BEGIN
- Op2(opMOV, src * 256, dst)
- END MovRR;
- PROCEDURE PushImm (imm: INTEGER);
- BEGIN
- imm := UTILS.Long(imm);
- CASE imm OF
- | 0: Op1(opPUSH, CG, sREG)
- | 1: Op1(opPUSH, CG, sIDX)
- | 2: Op1(opPUSH, CG, sINDIR)
- |-1: Op1(opPUSH, CG, sINCR)
- ELSE
- Op1(opPUSH, PC, sINCR);
- EmitWord(imm)
- END;
- IncStk
- END PushImm;
- PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER);
- BEGIN
- ASSERT(~ODD(adr));
- ASSERT((0 <= word) & (word <= 65535));
- mem[adr] := word MOD 256;
- mem[adr + 1] := word DIV 256;
- INC(adr, 2)
- END PutWord;
- PROCEDURE NewLabel (): INTEGER;
- BEGIN
- CHL.PushInt(Labels, 0)
- RETURN IL.NewLabel()
- END NewLabel;
- PROCEDURE LabelOffs (n: INTEGER): INTEGER;
- RETURN CHL.GetInt(Labels, n)
- END LabelOffs;
- PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER;
- VAR
- cmd: ANYCODE;
- adr: INTEGER;
- offset: INTEGER;
- diff: INTEGER;
- cc: INTEGER;
- shorted: BOOLEAN;
- BEGIN
- REPEAT
- shorted := FALSE;
- offset := CodeAdr DIV 2;
- cmd := CodeList.first(ANYCODE);
- WHILE cmd # NIL DO
- cmd.offset := offset;
- CASE cmd OF
- |LABEL: CHL.SetInt(Labels, cmd.num, offset)
- |JMP: INC(offset);
- IF ~cmd.short THEN
- INC(offset);
- IF cmd.cc # opJMP THEN
- INC(offset)
- END
- END
- |CALL: INC(offset, 2)
- |WORD: INC(offset)
- END;
- cmd := cmd.next(ANYCODE)
- END;
- cmd := CodeList.first(ANYCODE);
- WHILE cmd # NIL DO
- IF (cmd IS JMP) & ~cmd(JMP).short THEN
- diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1;
- IF ABS(diff) <= 512 THEN
- cmd(JMP).short := TRUE;
- shorted := TRUE
- END
- END;
- cmd := cmd.next(ANYCODE)
- END
- UNTIL ~shorted;
- IF offset * 2 > 10000H - IntVectorSize THEN
- ERRORS.Error(203)
- END;
- adr := CodeAdr;
- cmd := CodeList.first(ANYCODE);
- WHILE cmd # NIL DO
- CASE cmd OF
- |LABEL:
- |JMP: IF ~cmd.short THEN
- CASE cmd.cc OF
- |opJNE: cc := opJEQ
- |opJEQ: cc := opJNE
- |opJNC: cc := opJC
- |opJC: cc := opJNC
- |opJGE: cc := opJL
- |opJL: cc := opJGE
- |opJMP: cc := opJMP
- END;
- IF cc # opJMP THEN
- PutWord(cc + 2, adr) (* jcc L *)
- END;
- PutWord(4030H, adr); (* MOV @PC+, PC *)
- PutWord(LabelOffs(cmd.label) * 2, adr)
- (* L: *)
- ELSE
- diff := LabelOffs(cmd.label) - cmd.offset - 1;
- ASSERT((-512 <= diff) & (diff <= 511));
- PutWord(cmd.cc + diff MOD 1024, adr)
- END
- |CALL: PutWord(12B0H, adr); (* CALL @PC+ *)
- PutWord(LabelOffs(cmd.label) * 2, adr)
- |WORD: PutWord(cmd.val, adr)
- END;
- cmd := cmd.next(ANYCODE)
- END
- RETURN adr - CodeAdr
- END Fixup;
- PROCEDURE Push (reg: INTEGER);
- BEGIN
- Op1(opPUSH, reg, sREG);
- IncStk
- END Push;
- PROCEDURE Pop (reg: INTEGER);
- BEGIN
- Op2(opMOV, incr(SP), reg);
- DEC(StkCnt)
- END Pop;
- PROCEDURE Test (reg: INTEGER);
- BEGIN
- Op2(opCMP, imm(0), reg)
- END Test;
- PROCEDURE Clear (reg: INTEGER);
- BEGIN
- Op2(opMOV, imm(0), reg)
- END Clear;
- PROCEDURE mov (dst, src: INTEGER);
- BEGIN
- MovRR(src, dst)
- END mov;
- PROCEDURE xchg (reg1, reg2: INTEGER);
- BEGIN
- Push(reg1);
- mov(reg1, reg2);
- Pop(reg2)
- END xchg;
- PROCEDURE Reloc (section: INTEGER);
- VAR
- reloc: RELOC;
- BEGIN
- NEW(reloc);
- reloc.section := section;
- reloc.WordPtr := CodeList.last(WORD);
- LISTS.push(RelList, reloc)
- END Reloc;
- PROCEDURE CallRTL (proc, params: INTEGER);
- BEGIN
- IncStk;
- DEC(StkCnt);
- EmitCall(RTL.rtl[proc].label);
- RTL.Used(proc);
- IF params > 0 THEN
- Op2(opADD, imm(params * 2), SP);
- DEC(StkCnt, params)
- END
- END CallRTL;
- 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 GetRegA;
- BEGIN
- ASSERT(REG.GetReg(R, ACC))
- END GetRegA;
- PROCEDURE drop;
- BEGIN
- REG.Drop(R)
- END drop;
- PROCEDURE GetAnyReg (): INTEGER;
- RETURN REG.GetAnyReg(R)
- END GetAnyReg;
- PROCEDURE PushAll (NumberOfParameters: INTEGER);
- BEGIN
- REG.PushAll(R);
- DEC(R.pushed, NumberOfParameters)
- END PushAll;
- PROCEDURE PushAll_1;
- BEGIN
- REG.PushAll_1(R)
- END PushAll_1;
- 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 jcc (cc, label: INTEGER);
- VAR
- L: INTEGER;
- BEGIN
- CASE cc OF
- |jne:
- EmitJmp(opJNE, label)
- |je:
- EmitJmp(opJEQ, label)
- |jge:
- EmitJmp(opJGE, label)
- |jl:
- EmitJmp(opJL, label)
- |jle:
- EmitJmp(opJL, label);
- EmitJmp(opJEQ, label)
- |jg:
- L := NewLabel();
- EmitJmp(opJEQ, L);
- EmitJmp(opJGE, label);
- EmitLabel(L)
- |jb:
- EmitJmp(opJNC, label)
- END
- END jcc;
- PROCEDURE setcc (cc, reg: INTEGER);
- VAR
- L: INTEGER;
- BEGIN
- L := NewLabel();
- Op2(opMOV, imm(1), reg);
- jcc(cc, L);
- Clear(reg);
- EmitLabel(L)
- END setcc;
- PROCEDURE Shift2 (op, reg, n: INTEGER);
- VAR
- reg2: INTEGER;
- BEGIN
- IF n >= 8 THEN
- CASE op OF
- |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG)
- |IL.opROR2: Op1(opSWPB, reg, sREG)
- |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg)
- |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG)
- END;
- DEC(n, 8)
- END;
- IF (op = IL.opROR2) & (n > 0) THEN
- reg2 := GetAnyReg();
- MovRR(reg, reg2)
- ELSE
- reg2 := -1
- END;
- WHILE n > 0 DO
- CASE op OF
- |IL.opASR2: Op1(opRRA, reg, sREG)
- |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG)
- |IL.opLSL2: Op2(opADD, reg * 256, reg)
- |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG)
- END;
- DEC(n)
- END;
- IF reg2 # -1 THEN
- drop
- END
- END Shift2;
- PROCEDURE Neg (reg: INTEGER);
- BEGIN
- Op2(opXOR, imm(-1), reg);
- Op2(opADD, imm(1), reg)
- END Neg;
- PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
- RETURN (offset + StkCnt - ORD(offset > 0)) * 2
- END LocalOffset;
- PROCEDURE LocalDst (offset: INTEGER): INTEGER;
- RETURN dst_x(LocalOffset(offset), SP)
- END LocalDst;
- PROCEDURE LocalSrc (offset: INTEGER): INTEGER;
- RETURN src_x(LocalOffset(offset), SP)
- END LocalSrc;
- PROCEDURE translate (chk_stk: BOOLEAN);
- VAR
- cmd, next: COMMAND;
- opcode, param1, param2, L, a, n, c1, c2: INTEGER;
- reg1, reg2: INTEGER;
- cc: INTEGER;
- word: WORD;
- BEGIN
- cmd := IL.codes.commands.first(COMMAND);
- WHILE cmd # NIL DO
- param1 := cmd.param1;
- param2 := cmd.param2;
- opcode := cmd.opcode;
- CASE opcode OF
- |IL.opJMP:
- EmitJmp(opJMP, param1)
- |IL.opCALL:
- IncStk;
- DEC(StkCnt);
- EmitCall(param1)
- |IL.opCALLP:
- IncStk;
- DEC(StkCnt);
- UnOp(reg1);
- Op1(opCALL, reg1, sREG);
- drop;
- ASSERT(R.top = -1)
- |IL.opPRECALL:
- PushAll(0)
- |IL.opLABEL:
- EmitLabel(param1)
- |IL.opSADR_PARAM:
- Op1(opPUSH, PC, sINCR);
- IncStk;
- EmitWord(param2);
- Reloc(RDATA)
- |IL.opERR:
- CallRTL(RTL._error, 2)
- |IL.opPUSHC:
- PushImm(param2)
- |IL.opONERR:
- DEC(StkCnt);
- EmitWord(0C232H); (* BIC #8, SR; DINT *)
- EmitWord(4303H); (* MOV R3, R3; NOP *)
- PushImm(param2);
- EmitJmp(opJMP, param1)
- |IL.opLEAVEC:
- Pop(PC)
- |IL.opENTER:
- ASSERT(R.top = -1);
- EmitLabel(param1);
- n := param2 MOD 65536;
- param2 := param2 DIV 65536;
- StkCnt := 0;
- IF chk_stk THEN
- L := NewLabel();
- Op2(opMOV, SP * 256, R4);
- Op2(opSUB, HP * 256, R4);
- Op2(opCMP, imm(StkReserve), R4);
- word := CodeList.last(WORD);
- jcc(jge, L);
- DEC(StkCnt);
- EmitWord(0C232H); (* BIC #8, SR; DINT *)
- EmitWord(4303H); (* MOV R3, R3; NOP *)
- PushImm(n);
- EmitJmp(opJMP, cmd.param3);
- EmitLabel(L)
- END;
- IF param2 > 8 THEN
- Op2(opMOV, imm(param2), R4);
- L := NewLabel();
- EmitLabel(L);
- Push(CG);
- Op2(opSUB, imm(1), R4);
- jcc(jne, L)
- ELSE
- FOR n := 1 TO param2 DO
- Push(CG)
- END
- END;
- StkCnt := param2;
- MaxStkCnt := StkCnt
- |IL.opLEAVE, IL.opLEAVER:
- ASSERT(param2 = 0);
- IF opcode = IL.opLEAVER THEN
- UnOp(reg1);
- IF reg1 # ACC THEN
- mov(ACC, reg1)
- END;
- drop
- END;
- ASSERT(R.top = -1);
- ASSERT(StkCnt = param1);
- IF chk_stk THEN
- INC(word.val, MaxStkCnt * 2)
- END;
- IF param1 > 0 THEN
- Op2(opADD, imm(param1 * 2), SP)
- END;
- Pop(PC)
- |IL.opRES:
- ASSERT(R.top = -1);
- GetRegA
- |IL.opCLEANUP:
- IF param2 # 0 THEN
- Op2(opADD, imm(param2 * 2), SP);
- DEC(StkCnt, param2)
- END
- |IL.opCONST:
- next := cmd.next(COMMAND);
- IF next.opcode = IL.opCONST THEN
- c1 := param2;
- c2 := next.param2;
- next := next.next(COMMAND);
- IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
- Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR));
- cmd := next
- ELSE
- Op2(opMOV, imm(param2), GetAnyReg())
- END
- ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
- UnOp(reg1);
- Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR));
- drop;
- cmd := next
- ELSE
- Op2(opMOV, imm(param2), GetAnyReg())
- END
- |IL.opSADR:
- Op2(opMOV, incr(PC), GetAnyReg());
- EmitWord(param2);
- Reloc(RDATA)
- |IL.opGADR:
- Op2(opMOV, incr(PC), GetAnyReg());
- EmitWord(param2);
- Reloc(RBSS)
- |IL.opLADR:
- reg1 := GetAnyReg();
- n := LocalOffset(param2);
- Op2(opMOV, SP * 256, reg1);
- IF n # 0 THEN
- Op2(opADD, imm(n), reg1)
- END
- |IL.opLLOAD8:
- Op2(opMOV + BW, LocalSrc(param2), GetAnyReg())
- |IL.opLLOAD16, IL.opVADR:
- Op2(opMOV, LocalSrc(param2), GetAnyReg())
- |IL.opGLOAD8:
- Op2(opMOV + BW, src_x(param2, SR), GetAnyReg());
- Reloc(RBSS)
- |IL.opGLOAD16:
- Op2(opMOV, src_x(param2, SR), GetAnyReg());
- Reloc(RBSS)
- |IL.opLOAD8:
- UnOp(reg1);
- Op2(opMOV + BW, indir(reg1), reg1)
- |IL.opLOAD16:
- UnOp(reg1);
- Op2(opMOV, indir(reg1), reg1)
- |IL.opVLOAD8:
- reg1 := GetAnyReg();
- Op2(opMOV, LocalSrc(param2), reg1);
- Op2(opMOV + BW, indir(reg1), reg1)
- |IL.opVLOAD16:
- reg1 := GetAnyReg();
- Op2(opMOV, LocalSrc(param2), reg1);
- Op2(opMOV, indir(reg1), reg1)
- |IL.opSAVE, IL.opSAVE16:
- BinOp(reg2, reg1);
- Op2(opMOV, reg2 * 256, dst_x(0, reg1));
- drop;
- drop
- |IL.opSAVE8:
- BinOp(reg2, reg1);
- Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
- drop;
- drop
- |IL.opSAVE8C:
- UnOp(reg1);
- Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
- drop
- |IL.opSAVE16C, IL.opSAVEC:
- UnOp(reg1);
- Op2(opMOV, imm(param2), dst_x(0, reg1));
- drop
- |IL.opUMINUS:
- UnOp(reg1);
- Neg(reg1)
- |IL.opADD:
- BinOp(reg1, reg2);
- Op2(opADD, reg2 * 256, reg1);
- drop
- |IL.opADDC:
- IF param2 # 0 THEN
- UnOp(reg1);
- Op2(opADD, imm(param2), reg1)
- END
- |IL.opSUB:
- BinOp(reg1, reg2);
- Op2(opSUB, reg2 * 256, reg1);
- drop
- |IL.opSUBR, IL.opSUBL:
- UnOp(reg1);
- IF param2 # 0 THEN
- Op2(opSUB, imm(param2), reg1)
- END;
- IF opcode = IL.opSUBL THEN
- Neg(reg1)
- END
- |IL.opLADR_SAVEC:
- Op2(opMOV, imm(param2), LocalDst(param1))
- |IL.opLADR_SAVE:
- UnOp(reg1);
- Op2(opMOV, reg1 * 256, LocalDst(param2));
- drop
- |IL.opGADR_SAVEC:
- Op2(opMOV, imm(param2), dst_x(param1, SR));
- Reloc(RBSS)
- |IL.opCONST_PARAM:
- PushImm(param2)
- |IL.opPARAM:
- IF param2 = 1 THEN
- UnOp(reg1);
- Push(reg1);
- drop
- ELSE
- ASSERT(R.top + 1 <= param2);
- PushAll(param2)
- END
- |IL.opEQ..IL.opGE,
- IL.opEQC..IL.opGEC:
- IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
- BinOp(reg1, reg2);
- Op2(opCMP, reg2 * 256, reg1);
- drop
- ELSE
- UnOp(reg1);
- Op2(opCMP, imm(param2), reg1)
- 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(ORD(BITS(cc) / {0}), next.param1);
- cmd := next
- ELSE
- setcc(cc, GetAnyReg())
- END
- |IL.opNOP, IL.opAND, IL.opOR:
- |IL.opCODE:
- EmitWord(param2)
- |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.opNOT:
- UnOp(reg1);
- Test(reg1);
- setcc(je, reg1)
- |IL.opORD:
- UnOp(reg1);
- Test(reg1);
- setcc(jne, reg1)
- |IL.opGET:
- BinOp(reg1, reg2);
- drop;
- drop;
- Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2))
- |IL.opGETC:
- UnOp(reg2);
- drop;
- Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2))
- |IL.opCHKIDX:
- UnOp(reg1);
- Op2(opCMP, imm(param2), reg1);
- jcc(jb, param1)
- |IL.opCHKIDX2:
- BinOp(reg1, reg2);
- IF param2 # -1 THEN
- Op2(opCMP, reg1 * 256, reg2);
- jcc(jb, param1)
- END;
- INCL(R.regs, reg1);
- DEC(R.top);
- R.stk[R.top] := reg2
- |IL.opINCC, IL.opINCCB:
- UnOp(reg1);
- Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1));
- drop
- |IL.opDECCB:
- UnOp(reg1);
- Op2(opSUB + BW, imm(param2), dst_x(0, reg1));
- drop
- |IL.opINC, IL.opINCB:
- BinOp(reg1, reg2);
- Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2));
- drop;
- drop
- |IL.opDEC, IL.opDECB:
- BinOp(reg1, reg2);
- Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2));
- drop;
- drop
- |IL.opLADR_INCC, IL.opLADR_INCCB:
- Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1))
- |IL.opLADR_DECCB:
- Op2(opSUB + BW, imm(param2), LocalDst(param1))
- |IL.opLADR_INC, IL.opLADR_INCB:
- UnOp(reg1);
- Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2));
- drop
- |IL.opLADR_DEC, IL.opLADR_DECB:
- UnOp(reg1);
- Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2));
- drop
- |IL.opPUSHT:
- UnOp(reg1);
- Op2(opMOV, src_x(-2, reg1), GetAnyReg())
- |IL.opISREC:
- PushAll(2);
- PushImm(param2);
- CallRTL(RTL._guardrec, 3);
- GetRegA
- |IL.opIS:
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._is, 2);
- GetRegA
- |IL.opTYPEGR:
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._guardrec, 2);
- GetRegA
- |IL.opTYPEGP:
- UnOp(reg1);
- PushAll(0);
- Push(reg1);
- PushImm(param2);
- CallRTL(RTL._guard, 2);
- GetRegA
- |IL.opTYPEGD:
- UnOp(reg1);
- PushAll(0);
- Op1(opPUSH, reg1, sIDX);
- IncStk;
- EmitWord(-2);
- PushImm(param2);
- CallRTL(RTL._guardrec, 2);
- GetRegA
- |IL.opMULS:
- BinOp(reg1, reg2);
- Op2(opAND, reg2 * 256, reg1);
- drop
- |IL.opMULSC:
- UnOp(reg1);
- Op2(opAND, imm(param2), reg1)
- |IL.opDIVS:
- BinOp(reg1, reg2);
- Op2(opXOR, reg2 * 256, reg1);
- drop
- |IL.opDIVSC:
- UnOp(reg1);
- Op2(opXOR, imm(param2), reg1)
- |IL.opADDS:
- BinOp(reg1, reg2);
- Op2(opBIS, reg2 * 256, reg1);
- drop
- |IL.opSUBS:
- BinOp(reg1, reg2);
- Op2(opBIC, reg2 * 256, reg1);
- drop
- |IL.opADDSC:
- UnOp(reg1);
- Op2(opBIS, imm(param2), reg1)
- |IL.opSUBSL:
- UnOp(reg1);
- Op2(opXOR, imm(-1), reg1);
- Op2(opAND, imm(param2), reg1)
- |IL.opSUBSR:
- UnOp(reg1);
- Op2(opBIC, imm(param2), reg1)
- |IL.opUMINS:
- UnOp(reg1);
- Op2(opXOR, imm(-1), reg1)
- |IL.opLENGTH:
- PushAll(2);
- CallRTL(RTL._length, 2);
- GetRegA
- |IL.opMAX,IL.opMIN:
- BinOp(reg1, reg2);
- Op2(opCMP, reg2 * 256, reg1);
- IF opcode = IL.opMIN THEN
- cc := opJL + 1
- ELSE
- cc := opJGE + 1
- END;
- EmitWord(cc); (* jge/jl L *)
- MovRR(reg2, reg1);
- (* L: *)
- drop
- |IL.opMAXC, IL.opMINC:
- UnOp(reg1);
- Op2(opCMP, imm(param2), reg1);
- L := NewLabel();
- IF opcode = IL.opMINC THEN
- cc := jl
- ELSE
- cc := jge
- END;
- jcc(cc, L);
- Op2(opMOV, imm(param2), reg1);
- EmitLabel(L)
- |IL.opSWITCH:
- UnOp(reg1);
- IF param2 = 0 THEN
- reg2 := ACC
- ELSE
- reg2 := R5
- END;
- IF reg1 # reg2 THEN
- ASSERT(REG.GetReg(R, reg2));
- ASSERT(REG.Exchange(R, reg1, reg2));
- drop
- END;
- drop
- |IL.opENDSW:
- |IL.opCASEL:
- Op2(opCMP, imm(param1), ACC);
- jcc(jl, param2)
- |IL.opCASER:
- Op2(opCMP, imm(param1), ACC);
- jcc(jg, param2)
- |IL.opCASELR:
- Op2(opCMP, imm(param1), ACC);
- IF param2 = cmd.param3 THEN
- jcc(jne, param2)
- ELSE
- jcc(jl, param2);
- jcc(jg, cmd.param3)
- END
- |IL.opSBOOL:
- BinOp(reg2, reg1);
- Test(reg2);
- setcc(jne, reg2);
- Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
- drop;
- drop
- |IL.opSBOOLC:
- UnOp(reg1);
- Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
- drop
- |IL.opEQS .. IL.opGES:
- PushAll(4);
- PushImm((opcode - IL.opEQS) * 12);
- CallRTL(RTL._strcmp, 5);
- GetRegA
- |IL.opLEN:
- UnOp(reg1);
- drop;
- EXCL(R.regs, reg1);
- WHILE param2 > 0 DO
- UnOp(reg2);
- drop;
- DEC(param2)
- END;
- INCL(R.regs, reg1);
- ASSERT(REG.GetReg(R, reg1))
- |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR:
- PushAll(2);
- CASE opcode OF
- |IL.opLSL: CallRTL(RTL._lsl, 2)
- |IL.opASR: CallRTL(RTL._asr, 2)
- |IL.opROR: CallRTL(RTL._ror, 2)
- |IL.opLSR: CallRTL(RTL._lsr, 2)
- END;
- GetRegA
- |IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1:
- UnOp(reg1);
- PushAll_1;
- PushImm(param2);
- Push(reg1);
- drop;
- CASE opcode OF
- |IL.opLSL1: CallRTL(RTL._lsl, 2)
- |IL.opASR1: CallRTL(RTL._asr, 2)
- |IL.opROR1: CallRTL(RTL._ror, 2)
- |IL.opLSR1: CallRTL(RTL._lsr, 2)
- END;
- GetRegA
- |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
- param2 := param2 MOD 16;
- IF param2 # 0 THEN
- UnOp(reg1);
- Shift2(opcode, reg1, param2)
- END
- |IL.opMUL:
- PushAll(2);
- CallRTL(RTL._mul, 2);
- GetRegA
- |IL.opMULC:
- 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
- Clear(reg1)
- ELSE
- IF n > 0 THEN
- IF a < 0 THEN
- Neg(reg1)
- END;
- Shift2(IL.opLSL2, reg1, n)
- ELSE
- PushAll(1);
- PushImm(a);
- CallRTL(RTL._mul, 2);
- GetRegA
- END
- END
- |IL.opDIV:
- PushAll(2);
- CallRTL(RTL._divmod, 2);
- GetRegA
- |IL.opDIVR:
- ASSERT(param2 > 0);
- IF param2 > 1 THEN
- n := UTILS.Log2(param2);
- IF n > 0 THEN
- UnOp(reg1);
- Shift2(IL.opASR2, reg1, n)
- ELSE
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._divmod, 2);
- GetRegA
- END
- END
- |IL.opDIVL:
- UnOp(reg1);
- PushAll_1;
- PushImm(param2);
- Push(reg1);
- drop;
- CallRTL(RTL._divmod, 2);
- GetRegA
- |IL.opMOD:
- PushAll(2);
- CallRTL(RTL._divmod, 2);
- ASSERT(REG.GetReg(R, R5))
- |IL.opMODR:
- ASSERT(param2 > 0);
- IF param2 = 1 THEN
- UnOp(reg1);
- Clear(reg1)
- ELSE
- IF UTILS.Log2(param2) > 0 THEN
- UnOp(reg1);
- Op2(opAND, imm(param2 - 1), reg1)
- ELSE
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._divmod, 2);
- ASSERT(REG.GetReg(R, R5))
- END
- END
- |IL.opMODL:
- UnOp(reg1);
- PushAll_1;
- PushImm(param2);
- Push(reg1);
- drop;
- CallRTL(RTL._divmod, 2);
- ASSERT(REG.GetReg(R, R5))
- |IL.opCOPYS:
- ASSERT(R.top = 3);
- Push(R.stk[2]);
- Push(R.stk[0]);
- Op2(opCMP, R.stk[1] * 256, R.stk[3]);
- EmitWord(3801H); (* JL L1 *)
- MovRR(R.stk[1], R.stk[3]);
- (* L1: *)
- Push(R.stk[3]);
- drop;
- drop;
- drop;
- drop;
- CallRTL(RTL._move, 3)
- |IL.opCOPY:
- PushAll(2);
- PushImm(param2);
- CallRTL(RTL._move, 3)
- |IL.opMOVE:
- PushAll(3);
- CallRTL(RTL._move, 3)
- |IL.opCOPYA:
- PushAll(4);
- PushImm(param2);
- CallRTL(RTL._arrcpy, 5);
- GetRegA
- |IL.opROT:
- PushAll(0);
- MovRR(SP, ACC);
- Push(ACC);
- PushImm(param2);
- CallRTL(RTL._rot, 2)
- |IL.opSAVES:
- UnOp(reg1);
- PushAll_1;
- Op1(opPUSH, PC, sINCR);
- IncStk;
- EmitWord(param2);
- Reloc(RDATA);
- Push(reg1);
- drop;
- PushImm(param1);
- CallRTL(RTL._move, 3)
- |IL.opCASET:
- Push(R5);
- Push(R5);
- PushImm(param2);
- CallRTL(RTL._guardrec, 2);
- Pop(R5);
- Test(ACC);
- jcc(jne, param1)
- |IL.opABS:
- UnOp(reg1);
- Test(reg1);
- L := NewLabel();
- jcc(jge, L);
- Neg(reg1);
- EmitLabel(L)
- |IL.opEQB, IL.opNEB:
- BinOp(reg1, reg2);
- drop;
- Test(reg1);
- L := NewLabel();
- jcc(je, L);
- Op2(opMOV, imm(1), reg1);
- EmitLabel(L);
- Test(reg2);
- L := NewLabel();
- jcc(je, L);
- Op2(opMOV, imm(1), reg2);
- EmitLabel(L);
- Op2(opCMP, reg2 * 256, reg1);
- IF opcode = IL.opEQB THEN
- setcc(je, reg1)
- ELSE
- setcc(jne, reg1)
- END
- |IL.opSAVEP:
- UnOp(reg1);
- Op2(opMOV, incr(PC), reg1 + dIDX);
- EmitWord(param2);
- Reloc(RCODE);
- EmitWord(0);
- drop
- |IL.opPUSHP:
- Op2(opMOV, incr(PC), GetAnyReg());
- EmitWord(param2);
- Reloc(RCODE)
- |IL.opEQP, IL.opNEP:
- UnOp(reg1);
- Op2(opCMP, incr(PC), reg1);
- EmitWord(param1);
- Reloc(RCODE);
- drop;
- reg1 := GetAnyReg();
- IF opcode = IL.opEQP THEN
- setcc(je, reg1)
- ELSIF opcode = IL.opNEP THEN
- setcc(jne, reg1)
- END
- |IL.opVADR_PARAM:
- reg1 := GetAnyReg();
- Op2(opMOV, LocalSrc(param2), reg1);
- Push(reg1);
- drop
- |IL.opNEW:
- PushAll(1);
- n := param2 + 2;
- ASSERT(UTILS.Align(n, 2));
- PushImm(n);
- PushImm(param1);
- CallRTL(RTL._new, 3)
- |IL.opRSET:
- PushAll(2);
- CallRTL(RTL._set, 2);
- GetRegA
- |IL.opRSETR:
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._set, 2);
- GetRegA
- |IL.opRSETL:
- UnOp(reg1);
- PushAll_1;
- PushImm(param2);
- Push(reg1);
- drop;
- CallRTL(RTL._set, 2);
- GetRegA
- |IL.opRSET1:
- PushAll(1);
- CallRTL(RTL._set1, 1);
- GetRegA
- |IL.opINCLC:
- UnOp(reg1);
- Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1));
- drop
- |IL.opEXCLC:
- UnOp(reg1);
- Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1));
- drop
- |IL.opIN:
- PushAll(2);
- CallRTL(RTL._in, 2);
- GetRegA
- |IL.opINR:
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._in, 2);
- GetRegA
- |IL.opINL:
- PushAll(1);
- PushImm(param2);
- CallRTL(RTL._in2, 2);
- GetRegA
- |IL.opINCL:
- PushAll(2);
- CallRTL(RTL._incl, 2)
- |IL.opEXCL:
- PushAll(2);
- CallRTL(RTL._excl, 2)
- |IL.opLADR_INCL, IL.opLADR_EXCL:
- PushAll(1);
- MovRR(SP, ACC);
- n := LocalOffset(param2);
- IF n # 0 THEN
- Op2(opADD, imm(n), ACC)
- END;
- Push(ACC);
- IF opcode = IL.opLADR_INCL THEN
- CallRTL(RTL._incl, 2)
- ELSIF opcode = IL.opLADR_EXCL THEN
- CallRTL(RTL._excl, 2)
- END
- |IL.opLADR_INCLC:
- Op2(opBIS, imm(ORD({param2})), LocalDst(param1))
- |IL.opLADR_EXCLC:
- Op2(opBIC, imm(ORD({param2})), LocalDst(param1))
- END;
- cmd := cmd.next(COMMAND)
- END;
- ASSERT(R.pushed = 0);
- ASSERT(R.top = -1)
- END translate;
- PROCEDURE prolog;
- VAR
- i: INTEGER;
- BEGIN
- RTL.Init(EmitLabel, EmitWord, EmitCall);
- FOR i := 0 TO LEN(RTL.rtl) - 1 DO
- RTL.Set(i, NewLabel())
- END;
- IV[LEN(IV) - 1] := NewLabel();
- EmitLabel(IV[LEN(IV) - 1]);
- Op2(opMOV, incr(PC), SP);
- EmitWord(0);
- Op2(opMOV, incr(PC), HP);
- EmitWord(0);
- Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *)
- Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP));
- Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP));
- END prolog;
- PROCEDURE epilog;
- VAR
- L1, i, n: INTEGER;
- BEGIN
- Op2(opBIS, imm(10H), SR); (* CPUOFF *)
- L1 := NewLabel();
- FOR i := 0 TO LEN(IV) - 2 DO
- IV[i] := NewLabel();
- EmitLabel(IV[i]);
- PushImm(i);
- IF i # LEN(IV) - 2 THEN
- EmitJmp(opJMP, L1)
- END
- END;
- EmitLabel(L1);
- n := 0;
- FOR i := 0 TO 15 DO
- IF i IN R.regs THEN
- Push(i);
- INC(n)
- END
- END;
- MovRR(SP, R4);
- Op2(opADD, imm(n * 2), R4);
- Push(R4);
- Op1(opPUSH, R4, sINDIR);
- Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *)
- Op2(opADD, imm(4), SP);
- FOR i := 15 TO 0 BY -1 DO
- IF i IN R.regs THEN
- Pop(i)
- END
- END;
- Op2(opADD, imm(2), SP);
- Op1(opRETI, 0, 0);
- RTL.Gen
- END epilog;
- PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
- VAR
- i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER;
- Code, Data, Bss: RECORD address, size: INTEGER END;
- ram, rom: INTEGER;
- reloc: RELOC;
- BEGIN
- IdxWords.src := NOWORD;
- IdxWords.dst := NOWORD;
- ram := options.ram;
- rom := options.rom;
- IF ODD(ram) THEN DEC(ram) END;
- IF ODD(rom) THEN DEC(rom) END;
- ram := MIN(MAX(ram, minRAM), maxRAM);
- rom := MIN(MAX(rom, minROM), maxROM);
- IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN
- ERRORS.Error(204)
- END;
- Labels := CHL.CreateIntList();
- FOR i := 1 TO IL.codes.lcount DO
- CHL.PushInt(Labels, 0)
- END;
- CodeList := LISTS.create(NIL);
- RelList := LISTS.create(NIL);
- REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7});
- prolog;
- translate(chkSTK IN options.checking);
- epilog;
- TypesSize := CHL.Length(IL.codes.types) * 2;
- Data.size := CHL.Length(IL.codes.data);
- IF ODD(Data.size) THEN
- CHL.PushByte(IL.codes.data, 0);
- INC(Data.size)
- END;
- Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size);
- Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size);
- IF Code.address < 10000H - rom THEN
- ERRORS.Error(203)
- END;
- Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size);
- Data.address := Code.address + Code.size;
- TextSize := Code.size + Data.size;
- IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN
- ERRORS.Error(203)
- END;
- stack := RTL.ram + ram;
- Bss.size := IL.codes.bss + IL.codes.bss MOD 2;
- DEC(stack, Bss.size);
- Bss.address := stack;
- DEC(stack, RTL.VarSize);
- heap := RTL.ram;
- ASSERT(stack - heap >= StkReserve);
- adr := Code.address + 2;
- PutWord(stack, adr);
- adr := Code.address + 6;
- PutWord(heap, adr);
- reloc := RelList.first(RELOC);
- WHILE reloc # NIL DO
- adr := reloc.WordPtr.offset * 2;
- val := reloc.WordPtr.val;
- CASE reloc.section OF
- |RCODE: PutWord(LabelOffs(val) * 2, adr)
- |RDATA: PutWord(val + Data.address, adr)
- |RBSS: PutWord((val + Bss.address) MOD 65536, adr)
- END;
- reloc := reloc.next(RELOC)
- END;
- adr := Data.address;
- FOR i := 0 TO Data.size - 1 DO
- mem[adr] := CHL.GetByte(IL.codes.data, i);
- INC(adr)
- END;
- FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO
- PutWord(CHL.GetInt(IL.codes.types, i), adr)
- END;
- FOR i := 0 TO 15 DO
- PutWord((33 - i) * i, adr);
- END;
- FOR n := 0 TO 15 DO
- bits := ORD({0 .. n});
- FOR i := 0 TO 15 - n DO
- PutWord(bits, adr);
- bits := LSL(bits, 1)
- END
- END;
- PutWord(4130H, adr); (* RET *)
- PutWord(stack, adr);
- PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *)
- FOR i := 0 TO LEN(IV) - 1 DO
- PutWord(LabelOffs(IV[i]) * 2, adr)
- END;
- INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16);
- INC(Bss.size, StkReserve + RTL.VarSize);
- WR.Create(outname);
- HEX.Data(mem, Code.address - Code.address MOD 16, TextSize);
- HEX.End;
- WR.Close;
- C.Dashes;
- C.String(" rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)");
- C.Ln;
- C.String(" ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)")
- END CodeGen;
- END MSP430.
|