| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459 |
- (*
- BSD 2-Clause License
- Copyright (c) 2019-2022, Anton Krotov
- All rights reserved.
- *)
- MODULE THUMB;
- IMPORT PROG, LISTS, CHL := CHUNKLISTS, BIN, REG, IL, C := CONSOLE,
- UTILS, WR := WRITER, HEX, ERRORS, TARGETS;
- CONST
- R0 = 0; R1 = 1; R2 = 2; R3 = 3; R4 = 4;
- SP = 13; LR = 14; PC = 15;
- ACC = R0;
- je = 0; jne = 1; jnb = 2; jb = 3; jge = 10; jl = 11; jg = 12; jle = 13;
- inf = 7F800000H;
- minROM* = 16; maxROM* = 65536;
- minRAM* = 4; maxRAM* = 65536;
- maxIVT* = 1023;
- _THUMB2 = 0; _IT = 1; _SDIV = 2; _CBXZ = 3;
- CortexM0 = {};
- CortexM1 = {};
- CortexM3 = {_THUMB2, _IT, _SDIV, _CBXZ};
- CortexM23 = {_SDIV, _CBXZ};
- TYPE
- COMMAND = IL.COMMAND;
- ANYCODE = POINTER TO RECORD (LISTS.ITEM)
- offset: INTEGER
- END;
- CODE = POINTER TO RECORD (ANYCODE)
- code: INTEGER
- END;
- LABEL = POINTER TO RECORD (ANYCODE)
- label: INTEGER
- END;
- JUMP = POINTER TO RECORD (ANYCODE)
- label, diff, len, cond: INTEGER;
- short: BOOLEAN
- END;
- JMP = POINTER TO RECORD (JUMP)
- END;
- JCC = POINTER TO RECORD (JUMP)
- END;
- CBXZ = POINTER TO RECORD (JUMP)
- reg: INTEGER
- END;
- CALL = POINTER TO RECORD (JUMP)
- END;
- RELOC = POINTER TO RECORD (ANYCODE)
- reg, rel, value: INTEGER
- END;
- RELOCCODE = ARRAY 7 OF INTEGER;
- MEM = RECORD
- start, size, startReserve, endReserve: INTEGER
- END;
- VAR
- R: REG.REGS;
- tcount: INTEGER;
- CodeList: LISTS.LIST;
- program: BIN.PROGRAM;
- StkCount: INTEGER;
- Target: RECORD
- flash, sram: MEM;
- IVTLen,
- MinStkSize: INTEGER;
- InstrSet: SET;
- isNXP: BOOLEAN
- END;
- IVT: ARRAY maxIVT + 1 OF INTEGER;
- sdivProc, trap, genTrap, entry, emptyProc, int0, genInt: INTEGER;
- PROCEDURE Code (code: INTEGER);
- VAR
- c: CODE;
- BEGIN
- NEW(c);
- c.code := code;
- LISTS.push(CodeList, c)
- END Code;
- PROCEDURE Label (label: INTEGER);
- VAR
- L: LABEL;
- BEGIN
- NEW(L);
- L.label := label;
- LISTS.push(CodeList, L)
- END Label;
- PROCEDURE jcc (cond, label: INTEGER);
- VAR
- j: JCC;
- BEGIN
- NEW(j);
- j.label := label;
- j.cond := cond;
- j.short := FALSE;
- j.len := 3;
- LISTS.push(CodeList, j)
- END jcc;
- PROCEDURE cbxz (cond, reg, label: INTEGER);
- VAR
- j: CBXZ;
- BEGIN
- NEW(j);
- j.label := label;
- j.cond := cond;
- j.reg := reg;
- j.short := FALSE;
- j.len := 4;
- LISTS.push(CodeList, j)
- END cbxz;
- PROCEDURE jmp (label: INTEGER);
- VAR
- j: JMP;
- BEGIN
- NEW(j);
- j.label := label;
- j.short := FALSE;
- j.len := 2;
- LISTS.push(CodeList, j)
- END jmp;
- PROCEDURE call (label: INTEGER);
- VAR
- c: CALL;
- BEGIN
- NEW(c);
- c.label := label;
- c.short := FALSE;
- c.len := 2;
- LISTS.push(CodeList, c)
- END call;
- PROCEDURE reloc (reg, rel, value: INTEGER);
- VAR
- r: RELOC;
- BEGIN
- NEW(r);
- r.reg := reg;
- r.rel := rel;
- r.value := value;
- LISTS.push(CodeList, r)
- END reloc;
- PROCEDURE NewLabel (): INTEGER;
- BEGIN
- BIN.NewLabel(program)
- RETURN IL.NewLabel()
- END NewLabel;
- PROCEDURE range (x, n: INTEGER): BOOLEAN;
- RETURN (0 <= x) & (x < LSL(1, n))
- END range;
- PROCEDURE srange (x, n: INTEGER): BOOLEAN;
- RETURN (-LSL(1, n - 1) <= x) & (x < LSL(1, n - 1))
- END srange;
- PROCEDURE gen1 (op, imm, rs, rd: INTEGER);
- BEGIN
- ASSERT(op IN {0..2});
- ASSERT(range(imm, 5));
- ASSERT(range(rs, 3));
- ASSERT(range(rd, 3));
- Code(LSL(op, 11) + LSL(imm, 6) + LSL(rs, 3) + rd)
- END gen1;
- PROCEDURE gen2 (i, op: BOOLEAN; imm, rs, rd: INTEGER);
- BEGIN
- ASSERT(range(imm, 3));
- ASSERT(range(rs, 3));
- ASSERT(range(rd, 3));
- Code(1800H + LSL(ORD(i), 10) + LSL(ORD(op), 9) + LSL(imm, 6) + LSL(rs, 3) + rd)
- END gen2;
- PROCEDURE gen3 (op, rd, imm: INTEGER);
- BEGIN
- ASSERT(range(op, 2));
- ASSERT(range(rd, 3));
- ASSERT(range(imm, 8));
- Code(2000H + LSL(op, 11) + LSL(rd, 8) + imm)
- END gen3;
- PROCEDURE gen4 (op, rs, rd: INTEGER);
- BEGIN
- ASSERT(range(op, 4));
- ASSERT(range(rs, 3));
- ASSERT(range(rd, 3));
- Code(4000H + LSL(op, 6) + LSL(rs, 3) + rd)
- END gen4;
- PROCEDURE gen5 (op: INTEGER; h1, h2: BOOLEAN; rs, rd: INTEGER);
- BEGIN
- ASSERT(range(op, 2));
- ASSERT(range(rs, 3));
- ASSERT(range(rd, 3));
- Code(4400H + LSL(op, 8) + LSL(ORD(h1), 7) + LSL(ORD(h2), 6) + LSL(rs, 3) + rd)
- END gen5;
- PROCEDURE gen7 (l, b: BOOLEAN; ro, rb, rd: INTEGER);
- BEGIN
- ASSERT(range(ro, 3));
- ASSERT(range(rb, 3));
- ASSERT(range(rd, 3));
- Code(5000H + LSL(ORD(l), 11) + LSL(ORD(b), 10) + LSL(ro, 6) + LSL(rb, 3) + rd)
- END gen7;
- PROCEDURE gen8 (h, s: BOOLEAN; ro, rb, rd: INTEGER);
- BEGIN
- ASSERT(range(ro, 3));
- ASSERT(range(rb, 3));
- ASSERT(range(rd, 3));
- Code(5200H + LSL(ORD(h), 11) + LSL(ORD(s), 10) + LSL(ro, 6) + LSL(rb, 3) + rd)
- END gen8;
- PROCEDURE gen9 (b, l: BOOLEAN; imm, rb, rd: INTEGER);
- BEGIN
- ASSERT(range(imm, 5));
- ASSERT(range(rb, 3));
- ASSERT(range(rd, 3));
- Code(6000H + LSL(ORD(b), 12) + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd)
- END gen9;
- PROCEDURE gen10 (l: BOOLEAN; imm, rb, rd: INTEGER);
- BEGIN
- ASSERT(range(imm, 5));
- ASSERT(range(rb, 3));
- ASSERT(range(rd, 3));
- Code(8000H + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd)
- END gen10;
- PROCEDURE gen11 (l: BOOLEAN; rd, imm: INTEGER);
- BEGIN
- ASSERT(range(rd, 3));
- ASSERT(range(imm, 8));
- Code(9000H + LSL(ORD(l), 11) + LSL(rd, 8) + imm)
- END gen11;
- PROCEDURE gen12 (sp: BOOLEAN; rd, imm: INTEGER);
- BEGIN
- ASSERT(range(rd, 3));
- ASSERT(range(imm, 8));
- Code(0A000H + LSL(ORD(sp), 11) + LSL(rd, 8) + imm)
- END gen12;
- PROCEDURE gen14 (l, r: BOOLEAN; rlist: SET);
- VAR
- i, n: INTEGER;
- BEGIN
- ASSERT(range(ORD(rlist), 8));
- n := ORD(r);
- FOR i := 0 TO 7 DO
- IF i IN rlist THEN
- INC(n)
- END
- END;
- IF l THEN
- n := -n
- END;
- INC(StkCount, n);
- Code(0B400H + LSL(ORD(l), 11) + LSL(ORD(r), 8) + ORD(rlist))
- END gen14;
- PROCEDURE split16 (imm16: INTEGER; VAR imm4, imm1, imm3, imm8: INTEGER);
- BEGIN
- ASSERT(range(imm16, 16));
- imm8 := imm16 MOD 256;
- imm4 := LSR(imm16, 12);
- imm3 := LSR(imm16, 8) MOD 8;
- imm1 := LSR(imm16, 11) MOD 2;
- END split16;
- PROCEDURE LslImm (r, imm5: INTEGER);
- BEGIN
- gen1(0, imm5, r, r)
- END LslImm;
- PROCEDURE LsrImm (r, imm5: INTEGER);
- BEGIN
- gen1(1, imm5, r, r)
- END LsrImm;
- PROCEDURE AsrImm (r, imm5: INTEGER);
- BEGIN
- gen1(2, imm5, r, r)
- END AsrImm;
- PROCEDURE AddReg (rd, rs, rn: INTEGER);
- BEGIN
- gen2(FALSE, FALSE, rn, rs, rd)
- END AddReg;
- PROCEDURE SubReg (rd, rs, rn: INTEGER);
- BEGIN
- gen2(FALSE, TRUE, rn, rs, rd)
- END SubReg;
- PROCEDURE AddImm8 (rd, imm8: INTEGER);
- BEGIN
- IF imm8 # 0 THEN
- gen3(2, rd, imm8)
- END
- END AddImm8;
- PROCEDURE SubImm8 (rd, imm8: INTEGER);
- BEGIN
- IF imm8 # 0 THEN
- gen3(3, rd, imm8)
- END
- END SubImm8;
- PROCEDURE AddSubImm12 (r, imm12: INTEGER; sub: BOOLEAN);
- VAR
- imm4, imm1, imm3, imm8: INTEGER;
- BEGIN
- split16(imm12, imm4, imm1, imm3, imm8);
- Code(0F200H + LSL(imm1, 10) + r + 0A0H * ORD(sub)); (* addw/subw r, r, imm12 *)
- Code(LSL(imm3, 12) + LSL(r, 8) + imm8)
- END AddSubImm12;
- PROCEDURE MovImm8 (rd, imm8: INTEGER);
- BEGIN
- gen3(0, rd, imm8)
- END MovImm8;
- PROCEDURE CmpImm8 (rd, imm8: INTEGER);
- BEGIN
- gen3(1, rd, imm8)
- END CmpImm8;
- PROCEDURE Neg (r: INTEGER);
- BEGIN
- gen4(9, r, r)
- END Neg;
- PROCEDURE Mul (rd, rs: INTEGER);
- BEGIN
- gen4(13, rs, rd)
- END Mul;
- PROCEDURE Str32 (rs, rb: INTEGER);
- BEGIN
- gen9(FALSE, FALSE, 0, rb, rs)
- END Str32;
- PROCEDURE Ldr32 (rd, rb: INTEGER);
- BEGIN
- gen9(FALSE, TRUE, 0, rb, rd)
- END Ldr32;
- PROCEDURE Str16 (rs, rb: INTEGER);
- BEGIN
- gen10(FALSE, 0, rb, rs)
- END Str16;
- PROCEDURE Ldr16 (rd, rb: INTEGER);
- BEGIN
- gen10(TRUE, 0, rb, rd)
- END Ldr16;
- PROCEDURE Str8 (rs, rb: INTEGER);
- BEGIN
- gen9(TRUE, FALSE, 0, rb, rs)
- END Str8;
- PROCEDURE Ldr8 (rd, rb: INTEGER);
- BEGIN
- gen9(TRUE, TRUE, 0, rb, rd)
- END Ldr8;
- PROCEDURE Cmp (r1, r2: INTEGER);
- BEGIN
- gen4(10, r2, r1)
- END Cmp;
- PROCEDURE Tst (r: INTEGER);
- BEGIN
- gen3(1, r, 0) (* cmp r, 0 *)
- END Tst;
- PROCEDURE LdrSp (r, offset: INTEGER);
- BEGIN
- gen11(TRUE, r, offset)
- END LdrSp;
- PROCEDURE MovImm32 (r, imm32: INTEGER);
- BEGIN
- MovImm8(r, LSR(imm32, 24) MOD 256);
- LslImm(r, 8);
- AddImm8(r, LSR(imm32, 16) MOD 256);
- LslImm(r, 8);
- AddImm8(r, LSR(imm32, 8) MOD 256);
- LslImm(r, 8);
- AddImm8(r, imm32 MOD 256)
- END MovImm32;
- PROCEDURE low (x: INTEGER): INTEGER;
- RETURN x MOD 65536
- END low;
- PROCEDURE high (x: INTEGER): INTEGER;
- RETURN (x DIV 65536) MOD 65536
- END high;
- PROCEDURE movwt (r, imm16, t: INTEGER);
- VAR
- imm1, imm3, imm4, imm8: INTEGER;
- BEGIN
- ASSERT(range(r, 3));
- ASSERT(range(imm16, 16));
- ASSERT(range(t, 1));
- split16(imm16, imm4, imm1, imm3, imm8);
- Code(0F240H + imm1 * 1024 + t * 128 + imm4);
- Code(imm3 * 4096 + r * 256 + imm8);
- END movwt;
- PROCEDURE inv0 (cond: INTEGER): INTEGER;
- RETURN ORD(BITS(cond) / {0})
- END inv0;
- PROCEDURE fixup (CodeAdr, DataAdr, BssAdr: INTEGER);
- VAR
- code: ANYCODE;
- count: INTEGER;
- shorted: BOOLEAN;
- jump: JUMP;
- reloc, i, diff, len: INTEGER;
- RelocCode: RELOCCODE;
- PROCEDURE genjcc (cond, offset: INTEGER): INTEGER;
- BEGIN
- ASSERT(range(cond, 4));
- ASSERT(srange(offset, 8))
- RETURN 0D000H + cond * 256 + offset MOD 256
- END genjcc;
- PROCEDURE genjmp (offset: INTEGER): INTEGER;
- BEGIN
- ASSERT(srange(offset, 11))
- RETURN 0E000H + offset MOD 2048
- END genjmp;
- PROCEDURE movwt (r, imm16, t: INTEGER; VAR code: RELOCCODE);
- VAR
- imm1, imm3, imm4, imm8: INTEGER;
- BEGIN
- split16(imm16, imm4, imm1, imm3, imm8);
- code[t * 2] := 0F240H + imm1 * 1024 + t * 128 + imm4;
- code[t * 2 + 1] := imm3 * 4096 + r * 256 + imm8
- END movwt;
- PROCEDURE genmovimm32 (r, value: INTEGER; VAR code: RELOCCODE);
- BEGIN
- IF _THUMB2 IN Target.InstrSet THEN
- movwt(r, low(value), 0, code);
- movwt(r, high(value), 1, code)
- ELSE
- code[0] := 2000H + r * 256 + UTILS.Byte(value, 3); (* movs r, imm8 *)
- code[1] := 0200H + r * 9; (* lsls r, 8 *)
- code[2] := 3000H + r * 256 + UTILS.Byte(value, 2); (* adds r, imm8 *)
- code[3] := code[1]; (* lsls r, 8 *)
- code[4] := 3000H + r * 256 + UTILS.Byte(value, 1); (* adds r, imm8 *)
- code[5] := code[1]; (* lsls r, 8 *)
- code[6] := 3000H + r * 256 + UTILS.Byte(value, 0) (* adds r, imm8 *)
- END
- END genmovimm32;
- PROCEDURE PutCode (code: INTEGER);
- BEGIN
- BIN.PutCode16LE(program, code)
- END PutCode;
- PROCEDURE genlongjmp (offset: INTEGER);
- BEGIN
- ASSERT(srange(offset, 22));
- PutCode(0F000H + ASR(offset, 11) MOD 2048);
- PutCode(0F800H + offset MOD 2048)
- END genlongjmp;
- PROCEDURE genbc (code: JUMP);
- BEGIN
- CASE code.len OF
- |1: PutCode(genjcc(code.cond, code.diff))
- |2: PutCode(genjcc(inv0(code.cond), 0));
- PutCode(genjmp(code.diff))
- |3: PutCode(genjcc(inv0(code.cond), 1));
- genlongjmp(code.diff)
- END
- END genbc;
- PROCEDURE SetIV (idx, label, CodeAdr: INTEGER);
- VAR
- l, h: LISTS.ITEM;
- BEGIN
- l := CodeList.first;
- h := l.next;
- WHILE idx > 0 DO
- l := h.next;
- h := l.next;
- DEC(idx)
- END;
- label := BIN.GetLabel(program, label) * 2 + CodeAdr + 1;
- l(CODE).code := low(label);
- h(CODE).code := high(label)
- END SetIV;
- BEGIN
- REPEAT
- shorted := FALSE;
- count := 0;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- code.offset := count;
- CASE code OF
- |CODE: INC(count)
- |LABEL: BIN.SetLabel(program, code.label, count)
- |JUMP: INC(count, code.len); code.offset := count + ORD(code.short)
- |RELOC: INC(count, 7 - ORD(_THUMB2 IN Target.InstrSet) * 3 + code.rel MOD 2)
- END;
- code := code.next(ANYCODE)
- END;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- IF code IS JUMP THEN
- jump := code(JUMP);
- jump.diff := BIN.GetLabel(program, jump.label) - jump.offset;
- len := jump.len;
- diff := jump.diff;
- CASE jump OF
- |JMP:
- IF (len = 2) & srange(diff, 11) THEN
- len := 1
- END
- |JCC:
- CASE len OF
- |1:
- |2: IF srange(diff, 8) THEN DEC(len) END
- |3: IF srange(diff, 11) THEN DEC(len) END
- END
- |CBXZ:
- CASE len OF
- |1:
- |2: IF range(diff, 6) THEN DEC(len) END
- |3: IF srange(diff, 8) THEN DEC(len) END
- |4: IF srange(diff, 11) THEN DEC(len) END
- END
- |CALL:
- END;
- IF len # jump.len THEN
- jump.len := len;
- jump.short := TRUE;
- shorted := TRUE
- END
- END;
- code := code.next(ANYCODE)
- END
- UNTIL ~shorted;
- FOR i := 1 TO Target.IVTLen - 1 DO
- SetIV(i, IVT[i], CodeAdr)
- END;
- code := CodeList.first(ANYCODE);
- WHILE code # NIL DO
- CASE code OF
- |CODE: BIN.PutCode16LE(program, code.code)
- |LABEL:
- |JMP:
- IF code.len = 1 THEN
- PutCode(genjmp(code.diff))
- ELSE
- genlongjmp(code.diff)
- END
- |JCC: genbc(code)
- |CBXZ:
- IF code.len > 1 THEN
- PutCode(2800H + code.reg * 256); (* cmp code.reg, 0 *)
- DEC(code.len);
- genbc(code)
- ELSE
- (* cb(n)z code.reg, L *)
- PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * (code.diff DIV 32) + (code.diff MOD 32) * 8 + code.reg)
- END
- |CALL: genlongjmp(code.diff)
- |RELOC:
- CASE code.rel OF
- |BIN.RCODE, BIN.PICCODE: reloc := BIN.GetLabel(program, code.value) * 2 + CodeAdr
- |BIN.RDATA, BIN.PICDATA: reloc := code.value + DataAdr
- |BIN.RBSS, BIN.PICBSS: reloc := code.value + BssAdr
- END;
- IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN
- DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(_THUMB2 IN Target.InstrSet) + 9))
- END;
- genmovimm32(code.reg, reloc, RelocCode);
- FOR i := 0 TO 6 - 3 * ORD(_THUMB2 IN Target.InstrSet) DO
- PutCode(RelocCode[i])
- END;
- IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN
- PutCode(4478H + code.reg) (* add code.reg, pc *)
- END
- END;
- code := code.next(ANYCODE)
- END
- END fixup;
- PROCEDURE push (r: INTEGER);
- BEGIN
- gen14(FALSE, FALSE, {r})
- END push;
- PROCEDURE pop (r: INTEGER);
- BEGIN
- gen14(TRUE, FALSE, {r})
- END pop;
- PROCEDURE mov (r1, r2: INTEGER);
- BEGIN
- IF (r1 < 8) & (r2 < 8) THEN
- gen1(0, 0, r2, r1)
- ELSE
- gen5(2, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8)
- END
- END mov;
- PROCEDURE xchg (r1, r2: INTEGER);
- BEGIN
- push(r1);
- mov(r1, r2);
- pop(r2)
- END xchg;
- PROCEDURE drop;
- BEGIN
- REG.Drop(R)
- END drop;
- PROCEDURE GetAnyReg (): INTEGER;
- RETURN REG.GetAnyReg(R)
- END GetAnyReg;
- 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 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 GetRegA;
- BEGIN
- ASSERT(REG.GetReg(R, ACC))
- END GetRegA;
- PROCEDURE MovConst (r, c: INTEGER);
- BEGIN
- IF (0 <= c) & (c <= 255) THEN
- MovImm8(r, c)
- ELSIF (-255 <= c) & (c < 0) THEN
- MovImm8(r, -c);
- Neg(r)
- ELSIF UTILS.Log2(c) >= 0 THEN
- MovImm8(r, 1);
- LslImm(r, UTILS.Log2(c))
- ELSIF c = UTILS.min32 THEN
- MovImm8(r, 1);
- LslImm(r, 31)
- ELSE
- IF _THUMB2 IN Target.InstrSet THEN
- movwt(r, low(c), 0);
- IF (c < 0) OR (c > 65535) THEN
- movwt(r, high(c), 1)
- END
- ELSE
- MovImm32(r, c)
- END
- END
- END MovConst;
- PROCEDURE CmpConst (r, c: INTEGER);
- VAR
- r2: INTEGER;
- BEGIN
- IF (0 <= c) & (c <= 255) THEN
- CmpImm8(r, c)
- ELSE
- r2 := GetAnyReg();
- ASSERT(r2 # r);
- MovConst(r2, c);
- Cmp(r, r2);
- drop
- END
- END CmpConst;
- PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
- RETURN offset + StkCount - ORD(offset > 0)
- END LocalOffset;
- PROCEDURE SetCC (cc, r: INTEGER);
- VAR
- L1, L2: INTEGER;
- BEGIN
- IF _IT IN Target.InstrSet THEN
- Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *)
- MovConst(r, 1);
- MovConst(r, 0)
- ELSE
- L1 := NewLabel();
- L2 := NewLabel();
- jcc(cc, L1);
- MovConst(r, 0);
- jmp(L2);
- Label(L1);
- MovConst(r, 1);
- Label(L2)
- END
- END SetCC;
- PROCEDURE PushConst (n: INTEGER);
- VAR
- r: INTEGER;
- BEGIN
- r := GetAnyReg();
- MovConst(r, n);
- push(r);
- drop
- END PushConst;
- PROCEDURE AddConst (r, n: INTEGER);
- VAR
- r2: INTEGER;
- BEGIN
- IF n # 0 THEN
- IF (-255 <= n) & (n <= 255) THEN
- IF n > 0 THEN
- AddImm8(r, n)
- ELSE
- SubImm8(r, -n)
- END
- ELSIF (_THUMB2 IN Target.InstrSet) & (-4095 <= n) & (n <= 4095) THEN
- AddSubImm12(r, ABS(n), n < 0)
- ELSE
- r2 := GetAnyReg();
- ASSERT(r2 # r);
- IF n > 0 THEN
- MovConst(r2, n);
- AddReg(r, r, r2)
- ELSE
- MovConst(r2, -n);
- SubReg(r, r, r2)
- END;
- drop
- END
- END
- END AddConst;
- PROCEDURE AddHH (r1, r2: INTEGER);
- BEGIN
- ASSERT((r1 >= 8) OR (r2 >= 8));
- gen5(0, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8)
- END AddHH;
- PROCEDURE AddSP (n: INTEGER);
- BEGIN
- IF n > 0 THEN
- IF n < 127 THEN
- Code(0B000H + n) (* add sp, n*4 *)
- ELSE
- ASSERT(R2 IN R.regs);
- MovConst(R2, n * 4);
- AddHH(SP, R2)
- END;
- DEC(StkCount, n)
- END
- END AddSP;
- PROCEDURE cbxz2 (c, r, label: INTEGER);
- BEGIN
- IF _CBXZ IN Target.InstrSet THEN
- cbxz(c, r, label)
- ELSE
- Tst(r);
- jcc(c, label)
- END
- END cbxz2;
- PROCEDURE cbz (r, label: INTEGER);
- BEGIN
- cbxz2(je, r, label)
- END cbz;
- PROCEDURE cbnz (r, label: INTEGER);
- BEGIN
- cbxz2(jne, r, label)
- END cbnz;
- PROCEDURE Shift (op, r1, r2: INTEGER);
- VAR
- L: INTEGER;
- BEGIN
- LslImm(r2, 27);
- LsrImm(r2, 27);
- L := NewLabel();
- cbz(r2, L);
- CASE op OF
- |IL.opLSL, IL.opLSL1: gen4(2, r2, r1)
- |IL.opLSR, IL.opLSR1: gen4(3, r2, r1)
- |IL.opASR, IL.opASR1: gen4(4, r2, r1)
- |IL.opROR, IL.opROR1: gen4(7, r2, r1)
- END;
- Label(L)
- END Shift;
- PROCEDURE LocAdr (offs: INTEGER);
- VAR
- r1, n: INTEGER;
- BEGIN
- r1 := GetAnyReg();
- n := LocalOffset(offs);
- IF n <= 255 THEN
- gen12(TRUE, r1, n)
- ELSE
- MovConst(r1, n * 4);
- AddHH(r1, SP)
- END
- END LocAdr;
- PROCEDURE CallRTL (proc, par: INTEGER);
- BEGIN
- call(IL.codes.rtl[proc]);
- AddSP(par)
- END CallRTL;
- PROCEDURE divmod;
- BEGIN
- call(sdivProc);
- AddSP(2)
- END divmod;
- PROCEDURE cpsid_i;
- BEGIN
- Code(0B672H) (* cpsid i *)
- END cpsid_i;
- PROCEDURE cpsie_i;
- BEGIN
- Code(0B662H) (* cpsie i *)
- END cpsie_i;
- PROCEDURE translate (pic, stroffs: INTEGER);
- VAR
- cmd, next: COMMAND;
- opcode, param1, param2: INTEGER;
- r1, r2, r3: INTEGER;
- a, n, cc, L, L2: INTEGER;
- 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:
- jmp(param1)
- |IL.opLABEL:
- Label(param1)
- |IL.opHANDLER:
- IF param2 = 0 THEN
- int0 := param1
- ELSIF param2 = 1 THEN
- trap := param1
- ELSE
- IVT[param2] := param1
- END
- |IL.opCALL:
- call(param1)
- |IL.opCALLP:
- UnOp(r1);
- AddImm8(r1, 1); (* Thumb mode *)
- gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *)
- drop;
- ASSERT(R.top = -1)
- |IL.opENTER:
- ASSERT(R.top = -1);
- Label(param1);
- gen14(FALSE, TRUE, {}); (* push {lr} *)
- n := param2;
- IF n >= 5 THEN
- MovConst(ACC, 0);
- MovConst(R2, n);
- L := NewLabel();
- Label(L);
- push(ACC);
- SubImm8(R2, 1);
- Tst(R2);
- jcc(jne, L)
- ELSIF n > 0 THEN
- MovConst(ACC, 0);
- WHILE n > 0 DO
- push(ACC);
- DEC(n)
- END
- END;
- StkCount := param2
- |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);
- ASSERT(StkCount = param1);
- AddSP(param1);
- gen14(TRUE, TRUE, {}) (* pop {pc} *)
- |IL.opLEAVEC:
- gen5(3, FALSE, TRUE, 6, 0) (* bx lr *)
- |IL.opPRECALL:
- PushAll(0)
- |IL.opPARAM:
- IF param2 = 1 THEN
- UnOp(r1);
- push(r1);
- drop
- ELSE
- ASSERT(R.top + 1 <= param2);
- PushAll(param2)
- END
- |IL.opCLEANUP:
- AddSP(param2)
- |IL.opRES, IL.opRESF:
- ASSERT(R.top = -1);
- GetRegA
- |IL.opPUSHC:
- PushConst(param2)
- |IL.opONERR:
- cpsid_i;
- MovConst(R0, param2);
- push(R0);
- DEC(StkCount);
- jmp(param1)
- |IL.opERR:
- call(genTrap)
- |IL.opNOP, IL.opAND, IL.opOR:
- |IL.opSADR:
- reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2)
- |IL.opGADR:
- reloc(GetAnyReg(), BIN.RBSS + pic, param2)
- |IL.opLADR:
- LocAdr(param2)
- |IL.opGLOAD32:
- r1 := GetAnyReg();
- reloc(r1, BIN.RBSS + pic, param2);
- Ldr32(r1, r1)
- |IL.opGLOAD16:
- r1 := GetAnyReg();
- reloc(r1, BIN.RBSS + pic, param2);
- Ldr16(r1, r1)
- |IL.opGLOAD8:
- r1 := GetAnyReg();
- reloc(r1, BIN.RBSS + pic, param2);
- Ldr8(r1, r1)
- |IL.opLADR_SAVE:
- UnOp(r1);
- n := LocalOffset(param2);
- IF n <= 255 THEN
- gen11(FALSE, r1, n) (* str r1, [sp, n*4] *)
- ELSE
- LocAdr(param2);
- BinOp(r1, r2);
- Str32(r1, r2);
- drop
- END;
- drop
- |IL.opLADR_INCC:
- n := LocalOffset(param1);
- IF n <= 255 THEN
- r1 := GetAnyReg();
- LdrSp(r1, n);
- AddConst(r1, param2);
- gen11(FALSE, r1, n) (* str r1, [sp, n*4] *)
- ELSE
- LocAdr(param1);
- r1 := GetAnyReg();
- BinOp(r2, r1);
- Ldr32(r1, r2);
- AddConst(r1, param2);
- BinOp(r2, r1);
- Str32(r1, r2);
- drop
- END;
- drop
- |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32:
- r1 := GetAnyReg();
- n := LocalOffset(param2);
- IF n <= 255 THEN
- LdrSp(r1, n)
- ELSE
- drop;
- LocAdr(param2);
- UnOp(r1);
- Ldr32(r1, r1)
- END;
- IF opcode = IL.opVLOAD32 THEN
- Ldr32(r1, r1)
- END
- |IL.opLLOAD16:
- LocAdr(param2);
- UnOp(r1);
- Ldr16(r1, r1)
- |IL.opLLOAD8:
- LocAdr(param2);
- UnOp(r1);
- Ldr8(r1, r1)
- |IL.opLOAD32, IL.opLOADF:
- UnOp(r1);
- Ldr32(r1, r1)
- |IL.opLOAD16:
- UnOp(r1);
- Ldr16(r1, r1)
- |IL.opLOAD8:
- UnOp(r1);
- Ldr8(r1, r1)
- |IL.opVLOAD16:
- LocAdr(param2);
- UnOp(r1);
- Ldr32(r1, r1);
- Ldr16(r1, r1)
- |IL.opVLOAD8:
- LocAdr(param2);
- UnOp(r1);
- Ldr32(r1, r1);
- Ldr8(r1, r1)
- |IL.opSBOOL:
- BinOp(r2, r1);
- Tst(r2);
- SetCC(jne, r2);
- Str8(r2, r1);
- drop;
- drop
- |IL.opSBOOLC:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, ORD(param2 # 0));
- Str8(r2, r1);
- drop;
- drop
- |IL.opSAVEC:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, param2);
- Str32(r2, r1);
- drop;
- drop
- |IL.opSAVE16C:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, low(param2));
- Str16(r2, r1);
- drop;
- drop
- |IL.opSAVE8C:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, param2 MOD 256);
- Str8(r2, r1);
- drop;
- drop
- |IL.opSAVE, IL.opSAVE32, IL.opSAVEF:
- BinOp(r2, r1);
- Str32(r2, r1);
- drop;
- drop
- |IL.opSAVEFI:
- BinOp(r2, r1);
- Str32(r1, r2);
- drop;
- drop
- |IL.opSAVE16:
- BinOp(r2, r1);
- Str16(r2, r1);
- drop;
- drop
- |IL.opSAVE8:
- BinOp(r2, r1);
- Str8(r2, r1);
- drop;
- drop
- |IL.opSAVEP:
- UnOp(r1);
- r2 := GetAnyReg();
- reloc(r2, BIN.RCODE + pic, param2);
- Str32(r2, r1);
- drop;
- drop
- |IL.opPUSHP:
- reloc(GetAnyReg(), BIN.RCODE + pic, param2)
- |IL.opEQB, IL.opNEB:
- BinOp(r1, r2);
- drop;
- L := NewLabel();
- cbz(r1, L);
- MovConst(r1, 1);
- Label(L);
- L := NewLabel();
- cbz(r2, L);
- MovConst(r2, 1);
- Label(L);
- Cmp(r1, r2);
- IF opcode = IL.opEQB THEN
- SetCC(je, r1)
- ELSE
- SetCC(jne, r1)
- END
- |IL.opDROP:
- UnOp(r1);
- drop
- |IL.opJNZ1:
- UnOp(r1);
- cbnz(r1, param1)
- |IL.opJG:
- UnOp(r1);
- Tst(r1);
- jcc(jg, param1)
- |IL.opJNZ:
- UnOp(r1);
- cbnz(r1, param1);
- drop
- |IL.opJZ:
- UnOp(r1);
- cbz(r1, param1);
- drop
- |IL.opSWITCH:
- UnOp(r1);
- IF param2 = 0 THEN
- r2 := ACC
- ELSE
- r2 := R2
- END;
- IF r1 # r2 THEN
- ASSERT(REG.GetReg(R, r2));
- ASSERT(REG.Exchange(R, r1, r2));
- drop
- END;
- drop
- |IL.opENDSW:
- |IL.opCASEL:
- GetRegA;
- CmpConst(ACC, param1);
- jcc(jl, param2);
- drop
- |IL.opCASER:
- GetRegA;
- CmpConst(ACC, param1);
- jcc(jg, param2);
- drop
- |IL.opCASELR:
- GetRegA;
- CmpConst(ACC, param1);
- IF param2 = cmd.param3 THEN
- jcc(jne, param2)
- ELSE
- jcc(jl, param2);
- jcc(jg, cmd.param3)
- END;
- drop
- |IL.opCODE:
- Code(param2)
- |IL.opEQ..IL.opGE,
- IL.opEQC..IL.opGEC:
- IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
- BinOp(r1, r2);
- Cmp(r1, r2);
- drop
- ELSE
- UnOp(r1);
- CmpConst(r1, param2)
- END;
- drop;
- cc := cond(opcode);
- next := cmd.next(COMMAND);
- IF next.opcode = IL.opJNZ THEN
- jcc(cc, next.param1);
- cmd := next
- ELSIF next.opcode = IL.opJZ THEN
- jcc(inv0(cc), next.param1);
- cmd := next
- ELSE
- SetCC(cc, GetAnyReg())
- END
- |IL.opINCC:
- UnOp(r1);
- r2 := GetAnyReg();
- Ldr32(r2, r1);
- AddConst(r2, param2);
- Str32(r2, r1);
- drop;
- drop
- |IL.opINCCB, IL.opDECCB:
- IF opcode = IL.opDECCB THEN
- param2 := -param2
- END;
- UnOp(r1);
- r2 := GetAnyReg();
- Ldr8(r2, r1);
- AddConst(r2, param2);
- Str8(r2, r1);
- drop;
- drop
- |IL.opUMINUS:
- UnOp(r1);
- Neg(r1)
- |IL.opADD:
- BinOp(r1, r2);
- CASE cmd.next(COMMAND).opcode OF
- |IL.opLOAD32, IL.opLOADF:
- gen7(TRUE, FALSE, r2, r1, r1); (* ldr r1, [r1, r2] *)
- cmd := cmd.next(COMMAND)
- |IL.opLOAD8:
- gen7(TRUE, TRUE, r2, r1, r1); (* ldrb r1, [r1, r2] *)
- cmd := cmd.next(COMMAND)
- |IL.opLOAD16:
- gen8(TRUE, FALSE, r2, r1, r1); (* ldrh r1, [r1, r2] *)
- cmd := cmd.next(COMMAND)
- ELSE
- AddReg(r1, r1, r2)
- END;
- drop
- |IL.opADDC:
- UnOp(r1);
- AddConst(r1, param2)
- |IL.opSUB:
- BinOp(r1, r2);
- SubReg(r1, r1, r2);
- drop
- |IL.opSUBL, IL.opSUBR:
- UnOp(r1);
- AddConst(r1, -param2);
- IF opcode = IL.opSUBL THEN
- Neg(r1)
- END
- |IL.opMUL:
- BinOp(r1, r2);
- Mul(r1, r2);
- drop
- |IL.opMULC:
- UnOp(r1);
- 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(r1)
- ELSIF a = 0 THEN
- MovConst(r1, 0)
- ELSE
- IF n > 0 THEN
- IF a < 0 THEN
- Neg(r1)
- END;
- LslImm(r1, n)
- ELSE
- r2 := GetAnyReg();
- MovConst(r2, a);
- Mul(r1, r2);
- drop
- END
- END
- |IL.opABS:
- UnOp(r1);
- Tst(r1);
- L := NewLabel();
- jcc(jge, L);
- Neg(r1);
- Label(L)
- |IL.opNOT:
- UnOp(r1);
- Tst(r1);
- SetCC(je, r1)
- |IL.opORD:
- UnOp(r1);
- Tst(r1);
- SetCC(jne, r1)
- |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
- BinOp(r1, r2);
- Shift(opcode, r1, r2);
- drop
- |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
- MovConst(GetAnyReg(), param2);
- BinOp(r2, r1);
- Shift(opcode, r1, r2);
- INCL(R.regs, r2);
- DEC(R.top);
- R.stk[R.top] := r1
- |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
- n := param2 MOD 32;
- IF n # 0 THEN
- UnOp(r1);
- CASE opcode OF
- |IL.opASR2: AsrImm(r1, n)
- |IL.opROR2: r2 := GetAnyReg(); MovConst(r2, n); Shift(IL.opROR, r1, r2); drop
- |IL.opLSL2: LslImm(r1, n)
- |IL.opLSR2: LsrImm(r1, n)
- END
- END
- |IL.opCHKIDX:
- UnOp(r1);
- CmpConst(r1, param2);
- jcc(jb, param1)
- |IL.opCHKIDX2:
- BinOp(r1, r2);
- IF param2 # -1 THEN
- Cmp(r2, r1);
- jcc(jb, param1)
- END;
- INCL(R.regs, r1);
- DEC(R.top);
- R.stk[R.top] := r2
- |IL.opLEN:
- n := param2;
- UnOp(r1);
- drop;
- EXCL(R.regs, r1);
- WHILE n > 0 DO
- UnOp(r2);
- drop;
- DEC(n)
- END;
- INCL(R.regs, r1);
- ASSERT(REG.GetReg(R, r1))
- |IL.opINF:
- MovConst(GetAnyReg(), inf)
- |IL.opPUSHF:
- UnOp(r1);
- push(r1);
- drop
- |IL.opCONST:
- MovConst(GetAnyReg(), param2)
- |IL.opEQP, IL.opNEP:
- reloc(GetAnyReg(), BIN.RCODE + pic, param1);
- BinOp(r1, r2);
- Cmp(r1, r2);
- drop;
- IF opcode = IL.opEQP THEN
- SetCC(je, r1)
- ELSE
- SetCC(jne, r1)
- END
- |IL.opPUSHT:
- UnOp(r1);
- r2 := GetAnyReg();
- mov(r2, r1);
- SubImm8(r2, 4);
- Ldr32(r2, r2)
- |IL.opGET, IL.opGETC:
- IF opcode = IL.opGET THEN
- BinOp(r1, r2)
- ELSIF opcode = IL.opGETC THEN
- UnOp(r2);
- r1 := GetAnyReg();
- MovConst(r1, param1)
- END;
- drop;
- drop;
- CASE param2 OF
- |1: Ldr8(r1, r1); Str8(r1, r2)
- |2: Ldr16(r1, r1); Str16(r1, r2)
- |4: Ldr32(r1, r1); Str32(r1, r2)
- END
- |IL.opINC, IL.opDEC:
- BinOp(r2, r1);
- r3 := GetAnyReg();
- Ldr32(r3, r1);
- IF opcode = IL.opINC THEN
- AddReg(r3, r3, r2)
- ELSE
- SubReg(r3, r3, r2)
- END;
- Str32(r3, r1);
- drop;
- drop;
- drop
- |IL.opINCB, IL.opDECB:
- BinOp(r2, r1);
- r3 := GetAnyReg();
- Ldr8(r3, r1);
- IF opcode = IL.opINCB THEN
- AddReg(r3, r3, r2)
- ELSE
- SubReg(r3, r3, r2)
- END;
- Str8(r3, r1);
- drop;
- drop;
- drop
- |IL.opMIN, IL.opMAX:
- BinOp(r1, r2);
- Cmp(r1, r2);
- L := NewLabel();
- IF opcode = IL.opMIN THEN
- cc := jle
- ELSE
- cc := jge
- END;
- jcc(cc, L);
- mov(r1, r2);
- Label(L);
- drop
- |IL.opMINC, IL.opMAXC:
- UnOp(r1);
- CmpConst(r1, param2);
- L := NewLabel();
- IF opcode = IL.opMINC THEN
- cc := jle
- ELSE
- cc := jge
- END;
- jcc(cc, L);
- MovConst(r1, param2);
- Label(L)
- |IL.opMULS:
- BinOp(r1, r2);
- gen4(0, r2, r1); (* ands r1, r2 *)
- drop
- |IL.opMULSC:
- MovConst(GetAnyReg(), param2);
- BinOp(r1, r2);
- gen4(0, r2, r1); (* ands r1, r2 *)
- drop
- |IL.opDIVS:
- BinOp(r1, r2);
- gen4(1, r2, r1); (* eors r1, r2 *)
- drop
- |IL.opDIVSC:
- MovConst(GetAnyReg(), param2);
- BinOp(r1, r2);
- gen4(1, r2, r1); (* eors r1, r2 *)
- drop
- |IL.opADDS:
- BinOp(r1, r2);
- gen4(12, r2, r1); (* orrs r1, r2 *)
- drop
- |IL.opSUBS:
- BinOp(r1, r2);
- gen4(14, r2, r1); (* bics r1, r2 *)
- drop
- |IL.opADDSC:
- MovConst(GetAnyReg(), param2);
- BinOp(r1, r2);
- gen4(12, r2, r1); (* orrs r1, r2 *)
- drop
- |IL.opSUBSL:
- MovConst(GetAnyReg(), param2);
- BinOp(r1, r2);
- gen4(14, r1, r2); (* bics r2, r1 *)
- INCL(R.regs, r1);
- DEC(R.top);
- R.stk[R.top] := r2
- |IL.opSUBSR:
- MovConst(GetAnyReg(), param2);
- BinOp(r1, r2);
- gen4(14, r2, r1); (* bics r1, r2 *)
- drop
- |IL.opUMINS:
- UnOp(r1);
- gen4(15, r1, r1) (* mvns r1, r1 *)
- |IL.opINCL, IL.opEXCL:
- BinOp(r1, r2);
- r3 := GetAnyReg();
- MovConst(r3, 1);
- CmpConst(r1, 32);
- L := NewLabel();
- jcc(jnb, L);
- gen4(2, r1, r3); (* lsls r3, r1 *)
- Ldr32(r1, r2);
- IF opcode = IL.opINCL THEN
- gen4(12, r3, r1) (* orrs r1, r3 *)
- ELSE
- gen4(14, r3, r1) (* bics r1, r3 *)
- END;
- Str32(r1, r2);
- Label(L);
- drop;
- drop;
- drop
- |IL.opINCLC, IL.opEXCLC:
- UnOp(r2);
- r1 := GetAnyReg();
- r3 := GetAnyReg();
- MovConst(r3, 1);
- LslImm(r3, param2);
- Ldr32(r1, r2);
- IF opcode = IL.opINCLC THEN
- gen4(12, r3, r1) (* orrs r1, r3 *)
- ELSE
- gen4(14, r3, r1) (* bics r1, r3 *)
- END;
- Str32(r1, r2);
- drop;
- drop;
- drop
- |IL.opLENGTH:
- PushAll(2);
- CallRTL(IL._length, 2);
- GetRegA
- |IL.opLENGTHW:
- PushAll(2);
- CallRTL(IL._lengthw, 2);
- GetRegA
- |IL.opSAVES:
- UnOp(r2);
- REG.PushAll_1(R);
- r1 := GetAnyReg();
- reloc(r1, BIN.RDATA + pic, stroffs + param2);
- push(r1);
- drop;
- push(r2);
- drop;
- PushConst(param1);
- CallRTL(IL._move, 3)
- |IL.opEQS .. IL.opGES:
- PushAll(4);
- PushConst(opcode - IL.opEQS);
- CallRTL(IL._strcmp, 5);
- GetRegA
- |IL.opEQSW .. IL.opGESW:
- PushAll(4);
- PushConst(opcode - IL.opEQSW);
- CallRTL(IL._strcmpw, 5);
- GetRegA
- |IL.opCOPY:
- PushAll(2);
- PushConst(param2);
- CallRTL(IL._move, 3)
- |IL.opMOVE:
- PushAll(3);
- CallRTL(IL._move, 3)
- |IL.opCOPYA:
- PushAll(4);
- PushConst(param2);
- CallRTL(IL._arrcpy, 5);
- GetRegA
- |IL.opCOPYS:
- PushAll(4);
- PushConst(param2);
- CallRTL(IL._strcpy, 5)
- |IL.opDIV:
- PushAll(2);
- divmod;
- GetRegA
- |IL.opDIVL:
- UnOp(r1);
- REG.PushAll_1(R);
- PushConst(param2);
- push(r1);
- drop;
- divmod;
- GetRegA
- |IL.opDIVR:
- n := UTILS.Log2(param2);
- IF n > 0 THEN
- UnOp(r1);
- AsrImm(r1, n)
- ELSIF n < 0 THEN
- PushAll(1);
- PushConst(param2);
- divmod;
- GetRegA
- END
- |IL.opMOD:
- PushAll(2);
- divmod;
- mov(R0, R1);
- GetRegA
- |IL.opMODR:
- n := UTILS.Log2(param2);
- IF n > 0 THEN
- UnOp(r1);
- IF n = 8 THEN
- Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *)
- ELSIF n = 16 THEN
- Code(0B280H + r1 * 9) (* uxth r1, r1 *)
- ELSE
- LslImm(r1, 32 - n);
- LsrImm(r1, 32 - n)
- END
- ELSIF n < 0 THEN
- PushAll(1);
- PushConst(param2);
- divmod;
- mov(R0, R1);
- GetRegA
- ELSE
- UnOp(r1);
- MovConst(r1, 0)
- END
- |IL.opMODL:
- UnOp(r1);
- REG.PushAll_1(R);
- PushConst(param2);
- push(r1);
- drop;
- divmod;
- mov(R0, R1);
- GetRegA
- |IL.opIN, IL.opINR:
- IF opcode = IL.opINR THEN
- r2 := GetAnyReg();
- MovConst(r2, param2)
- END;
- L := NewLabel();
- L2 := NewLabel();
- BinOp(r1, r2);
- r3 := GetAnyReg();
- CmpConst(r1, 32);
- jcc(jb, L);
- MovConst(r1, 0);
- jmp(L2);
- Label(L);
- MovConst(r3, 1);
- Shift(IL.opLSL, r3, r1);
- gen4(0, r3, r2); (* ands r2, r3 *)
- SetCC(jne, r1);
- Label(L2);
- drop;
- drop
- |IL.opINL:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, LSL(1, param2));
- gen4(0, r2, r1); (* ands r1, r2 *)
- SetCC(jne, r1);
- drop
- |IL.opRSET:
- PushAll(2);
- CallRTL(IL._set, 2);
- GetRegA
- |IL.opRSETR:
- PushAll(1);
- PushConst(param2);
- CallRTL(IL._set, 2);
- GetRegA
- |IL.opRSETL:
- UnOp(r1);
- REG.PushAll_1(R);
- PushConst(param2);
- push(r1);
- drop;
- CallRTL(IL._set, 2);
- GetRegA
- |IL.opRSET1:
- PushAll(1);
- CallRTL(IL._set1, 1);
- GetRegA
- |IL.opCONSTF:
- MovConst(GetAnyReg(), UTILS.d2s(cmd.float))
- |IL.opMULF:
- PushAll(2);
- CallRTL(IL._fmul, 2);
- GetRegA
- |IL.opDIVF:
- PushAll(2);
- CallRTL(IL._fdiv, 2);
- GetRegA
- |IL.opDIVFI:
- PushAll(2);
- CallRTL(IL._fdivi, 2);
- GetRegA
- |IL.opADDF:
- PushAll(2);
- CallRTL(IL._fadd, 2);
- GetRegA
- |IL.opSUBFI:
- PushAll(2);
- CallRTL(IL._fsubi, 2);
- GetRegA
- |IL.opSUBF:
- PushAll(2);
- CallRTL(IL._fsub, 2);
- GetRegA
- |IL.opEQF..IL.opGEF:
- PushAll(2);
- PushConst(opcode - IL.opEQF);
- CallRTL(IL._fcmp, 3);
- GetRegA
- |IL.opFLOOR:
- PushAll(1);
- CallRTL(IL._floor, 1);
- GetRegA
- |IL.opFLT:
- PushAll(1);
- CallRTL(IL._flt, 1);
- GetRegA
- |IL.opUMINF:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, 1);
- LslImm(r2, 31);
- gen4(1, r2, r1); (* eors r1, r2 *)
- drop
- |IL.opFABS:
- UnOp(r1);
- r2 := GetAnyReg();
- MovConst(r2, 1);
- LslImm(r2, 31);
- gen4(14, r2, r1); (* bics r1, r2 *)
- drop
- |IL.opNEW:
- cpsid_i;
- PushAll(1);
- n := param2 + 4;
- ASSERT(UTILS.Align(n, 4));
- PushConst(n);
- PushConst(param1);
- CallRTL(IL._new, 3);
- cpsie_i
- |IL.opTYPEGP:
- UnOp(r1);
- PushAll(0);
- push(r1);
- PushConst(param2);
- CallRTL(IL._guard, 2);
- GetRegA
- |IL.opIS:
- PushAll(1);
- PushConst(param2);
- CallRTL(IL._is, 2);
- GetRegA
- |IL.opISREC:
- PushAll(2);
- PushConst(param2);
- CallRTL(IL._guardrec, 3);
- GetRegA
- |IL.opTYPEGR:
- PushAll(1);
- PushConst(param2);
- CallRTL(IL._guardrec, 2);
- GetRegA
- |IL.opTYPEGD:
- UnOp(r1);
- PushAll(0);
- SubImm8(r1, 4);
- Ldr32(r1, r1);
- push(r1);
- PushConst(param2);
- CallRTL(IL._guardrec, 2);
- GetRegA
- |IL.opCASET:
- push(R2);
- push(R2);
- PushConst(param2);
- CallRTL(IL._guardrec, 2);
- pop(R2);
- cbnz(ACC, param1)
- |IL.opROT:
- PushAll(0);
- mov(R2, SP);
- push(R2);
- PushConst(param2);
- CallRTL(IL._rot, 2)
- |IL.opPACK:
- PushAll(2);
- CallRTL(IL._pack, 2)
- |IL.opPACKC:
- PushAll(1);
- PushConst(param2);
- CallRTL(IL._pack, 2)
- |IL.opUNPK:
- PushAll(2);
- CallRTL(IL._unpk, 2)
- END;
- cmd := cmd.next(COMMAND)
- END;
- ASSERT(R.pushed = 0);
- ASSERT(R.top = -1)
- END translate;
- PROCEDURE prolog (GlobSize, tcount, pic, sp, ivt_len: INTEGER);
- VAR
- r1, r2, i, dcount: INTEGER;
- BEGIN
- entry := NewLabel();
- emptyProc := NewLabel();
- genInt := NewLabel();
- genTrap := NewLabel();
- sdivProc := NewLabel();
- trap := emptyProc;
- int0 := emptyProc;
- IVT[0] := sp;
- IVT[1] := entry;
- FOR i := 2 TO ivt_len - 1 DO
- IVT[i] := genInt
- END;
- FOR i := 0 TO ivt_len - 1 DO
- Code(low(IVT[i]));
- Code(high(IVT[i]))
- END;
- Label(entry);
- cpsie_i;
- r1 := GetAnyReg();
- r2 := GetAnyReg();
- reloc(r1, BIN.RDATA + pic, 0);
- FOR i := 0 TO tcount - 1 DO
- MovConst(r2, CHL.GetInt(IL.codes.types, i));
- Str32(r2, r1);
- AddImm8(r1, 4)
- END;
- dcount := CHL.Length(IL.codes.data);
- FOR i := 0 TO dcount - 1 BY 4 DO
- MovConst(r2, BIN.get32le(IL.codes.data, i));
- Str32(r2, r1);
- AddImm8(r1, 4)
- END;
- drop;
- drop;
- r1 := GetAnyReg();
- MovConst(r1, sp);
- mov(SP, r1);
- reloc(r1, BIN.RDATA + pic, 0);
- push(r1);
- reloc(r1, BIN.RBSS + pic, 0);
- r2 := GetAnyReg();
- MovConst(r2, GlobSize);
- AddReg(r1, r1, r2);
- drop;
- push(r1);
- drop;
- PushConst(tcount);
- CallRTL(IL._init, 3)
- END prolog;
- PROCEDURE epilog;
- VAR
- L1, L2, L3, L4: INTEGER;
- BEGIN
- (* L2: *)
- Code(0E7FEH); (* b L2 *)
- Label(genInt);
- Code(0F3EFH); Code(08005H); (* mrs r0, ipsr *)
- gen14(FALSE, TRUE, {R0}); (* push {lr, r0} *)
- call(int0);
- gen14(TRUE, TRUE, {R0}); (* pop {pc, r0} *)
- Label(emptyProc);
- Code(04770H); (* bx lr *)
- Label(genTrap);
- call(trap);
- call(entry);
- Label(sdivProc);
- IF _SDIV IN Target.InstrSet THEN
- Code(09800H); (* ldr r0, [sp] *)
- Code(09901H); (* ldr r1, [sp, 4] *)
- Code(0FB91H); (* sdiv r2, r1, r0 *)
- Code(0F2F0H);
- Code(00013H); (* movs r3, r2 *)
- Code(04343H); (* muls r3, r0, r3 *)
- Code(01AC9H); (* subs r1, r1, r3 *)
- Code(0DA01H); (* bge L *)
- Code(01809H); (* adds r1, r1, r0 *)
- Code(03A01H); (* subs r2, 1 *)
- (* L: *)
- Code(00010H); (* movs r0, r2 *)
- Code(04770H); (* bx lr *)
- ELSE
- (* a / b; a >= 0 *)
- L1 := NewLabel();
- L2 := NewLabel();
- L3 := NewLabel();
- L4 := NewLabel();
- LdrSp(R1, 1);
- LdrSp(R2, 0);
- MovConst(R0, 0);
- push(R4);
- Label(L4);
- Cmp(R1, R2);
- jcc(jl, L1);
- MovConst(R3, 2);
- mov(R4, R2);
- LslImm(R4, 1);
- Label(L3);
- Cmp(R1, R4);
- jcc(jl, L2);
- CmpConst(R4, 0);
- jcc(jle, L2);
- LslImm(R4, 1);
- LslImm(R3, 1);
- jmp(L3);
- Label(L2);
- LsrImm(R4, 1);
- LsrImm(R3, 1);
- SubReg(R1, R1, R4);
- AddReg(R0, R0, R3);
- jmp(L4);
- Label(L1);
- (* a / b; a < 0 *)
- L1 := NewLabel();
- L2 := NewLabel();
- L3 := NewLabel();
- L4 := NewLabel();
- Label(L4);
- CmpConst(R1, 0);
- jcc(jge, L1);
- MovConst(R3, 2);
- mov(R4, R2);
- LslImm(R4, 1);
- Neg(R1);
- Label(L3);
- Cmp(R1, R4);
- jcc(jl, L2);
- CmpConst(R4, 0);
- jcc(jle, L2);
- LslImm(R4, 1);
- LslImm(R3, 1);
- jmp(L3);
- Label(L2);
- Neg(R1);
- LsrImm(R4, 1);
- LsrImm(R3, 1);
- AddReg(R1, R1, R4);
- SubReg(R0, R0, R3);
- jmp(L4);
- Label(L1);
- pop(R4);
- Code(04770H); (* bx lr *)
- END
- END epilog;
- PROCEDURE SetTarget (FlashStart, FlashSize, FlashReserve, SRAMStart, SRAMSize, SRAMReserve: INTEGER; InstrSet: SET; isNXP: BOOLEAN);
- BEGIN
- Target.flash.start := FlashStart;
- Target.flash.size := FlashSize;
- (*Target.flash.startReserve := 0;*)
- Target.flash.endReserve := FlashReserve;
- Target.sram.start := SRAMStart;
- Target.sram.size := SRAMSize;
- Target.sram.startReserve := 0;
- Target.sram.endReserve := SRAMReserve;
- Target.InstrSet := InstrSet;
- Target.isNXP := isNXP;
- Target.IVTLen := 256; (* >= 192 *)
- Target.MinStkSize := 256;
- END SetTarget;
- PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
- VAR
- opt: PROG.OPTIONS;
- i, j, DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER;
- BEGIN
- IF target = TARGETS.STM32CM3 THEN
- SetTarget(08000000H, MIN(MAX(options.rom, minROM), maxROM) * 1024, 0,
- 20000000H, MIN(MAX(options.ram, minRAM), maxRAM) * 1024, 0,
- CortexM3, FALSE)
- END;
- tcount := CHL.Length(IL.codes.types);
- opt := options;
- CodeList := LISTS.create(NIL);
- program := BIN.create(IL.codes.lcount);
- REG.Init(R, push, pop, mov, xchg, {R0, R1, R2, R3});
- StkCount := 0;
- DataAdr := Target.sram.start + Target.sram.startReserve;
- DataSize := CHL.Length(IL.codes.data) + tcount * 4 + Target.sram.startReserve;
- WHILE DataSize MOD 4 # 0 DO
- CHL.PushByte(IL.codes.data, 0);
- INC(DataSize)
- END;
- BssAdr := DataAdr + DataSize - Target.sram.startReserve;
- IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
- BssSize := IL.codes.bss;
- ASSERT(UTILS.Align(BssSize, 4));
- prolog(BssSize, tcount, ORD(opt.pic), Target.sram.start + Target.sram.size - Target.sram.endReserve, Target.IVTLen);
- translate(ORD(opt.pic), tcount * 4);
- epilog;
- fixup(Target.flash.start, DataAdr, BssAdr);
- INC(DataSize, BssSize);
- CodeSize := CHL.Length(program.code);
- IF CodeSize > Target.flash.size - Target.flash.endReserve THEN
- ERRORS.Error(203)
- END;
- IF DataSize > Target.sram.size - Target.MinStkSize - Target.sram.endReserve THEN
- ERRORS.Error(204)
- END;
- IF Target.isNXP THEN
- BIN.put32le(program.code, 2FCH, 0H); (* code read protection (CRP) *)
- (* NXP checksum *)
- j := 0;
- FOR i := 0 TO 6 DO
- INC(j, BIN.get32le(program.code, i * 4))
- END;
- BIN.put32le(program.code, 1CH, -j)
- END;
- WR.Create(outname);
- HEX.Data2(program.code, 0, CodeSize, high(Target.flash.start));
- HEX.End;
- WR.Close;
- C.Dashes;
- C.String( " rom: "); C.Int(CodeSize); C.String(" of "); C.Int(Target.flash.size - Target.flash.endReserve);
- C.String(" ("); C.Int(CodeSize * 100 DIV (Target.flash.size - Target.flash.endReserve)); C.StringLn("%)");
- C.Ln;
- C.String( " ram: "); C.Int(DataSize); C.String(" of "); C.Int(Target.sram.size - Target.sram.endReserve);
- C.String(" ("); C.Int(DataSize * 100 DIV (Target.sram.size - Target.sram.endReserve)); C.StringLn("%)")
- END CodeGen;
- PROCEDURE SetIV* (idx: INTEGER): BOOLEAN;
- VAR
- res: BOOLEAN;
- BEGIN
- res := IVT[idx] = 0;
- IVT[idx] := 1
- RETURN res
- END SetIV;
- PROCEDURE init;
- VAR
- i: INTEGER;
- BEGIN
- FOR i := 0 TO LEN(IVT) - 1 DO
- IVT[i] := 0
- END
- END init;
- BEGIN
- init
- END THUMB.
|