| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764 |
- MODULE MSP430;
- IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX,
- UTILS IN "./utils/UTILS.ob07", 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.
|