12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531 |
- /*
- Copyright (c) 2021-2022, b4rt-dev
- Copyright (c) 2012-2015, Alexey Frunze
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /*****************************************************************************/
- /* */
- /* BCC (B32P C Compiler) */
- /* */
- /* C compiler for B32P */
- /* */
- /* Based on SmallerC: */
- /* A simple and small single-pass C compiler */
- /* */
- /* B32P code generator */
- /* Modified from the MIPS code generator */
- /* */
- /*****************************************************************************/
- // NOTE: Pretty inefficient generated code, because of the direct-ish translation from MIPS to B32P
- /* MAIN TODOs:
- - Improve using new B32P instructions
- - Remove all MIPS code leftovers
- - Do optimizations (like size stuff)
- */
- /* WORDSIZE issue tags (to look into if I will ever try to fix it)
- //WORDSIZE
- //CurFxnLocalOfs (gcc.c)
- */
- STATIC
- void GenInit(void)
- {
- // initialization of target-specific code generator
- // Assembler should move all .data and .rdata parts away from the code
- SizeOfWord = 4;
- OutputFormat = FormatSegmented;
- CodeHeaderFooter[0] = ".code";
- DataHeaderFooter[0] = ".data";
- RoDataHeaderFooter[0] = ".rdata";
- BssHeaderFooter[0] = ".bss"; // object data
- UseLeadingUnderscores = 0;
- }
- STATIC
- int GenInitParams(int argc, char** argv, int* idx)
- {
- return 0;
- }
- STATIC
- void GenInitFinalize(void)
- {
- // finalization of initialization of target-specific code generator
- // Put all C specific wrapper code (start) here
- if (compileUserBDOS)
- {
- printf2(
- ".code\n"
- "; Setup stack and return function before jumping to Main of BDOS user program\n"
- "; BDOS user programs have their stack to keep the other stacks intact\n"
- "Main:\n"
- " load32 0 r14 ; initialize base pointer address\n"
- " load32 0x73FFFF r13 ; initialize user main stack address\n"
- " addr2reg Return_BDOS r1 ; get address of return function\n"
- " or r0 r1 r15 ; copy return addr to r15\n"
- " jump main ; jump to main of C program\n"
- " halt ; should not get here\n"
- "\n"
- "; Function that is called after Main of C user program has returned\n"
- "; Here we do some post processing before jumping back to BDOS\n"
- "; Its adrress should be on top of the hardware stack\n"
- "Return_BDOS:\n"
- " ; notify program has ended\n"
- " load32 0x100300 r1\n"
- " write 0 r1 r0\n"
- "\n"
- " pop r1\n"
- " jumpr 3 r1\n"
- " halt ; should not get here\n"
- "\n"
- "; COMPILED C CODE HERE\n");
- }
- else
- {
- printf2(
- ".code\n"
- "; Setup stack and return function before jumping to Main of C program\n"
- "Main:\n"
- " load32 0 r14 ; initialize base pointer address\n"
- " load32 0x77FFFF r13 ; initialize main stack address\n"
- " addr2reg Return_UART r1 ; get address of return function\n"
- " or r0 r1 r15 ; copy return addr to r15\n"
- " jump main ; jump to main of C program\n"
- " ; should return to the address in r15\n"
- " halt ; should not get here\n"
- "\n"
- "; Function that is called after Main of C program has returned\n"
- "; Return value should be in R1\n"
- "; Send it over UART and halt afterwards\n"
- "Return_UART:\n"
- " load32 0xC02723 r1 ; r1 = 0xC02723 | UART tx\n"
- " write 0 r1 r2 ; write r2 over UART\n"
- " halt ; halt\n"
- "\n"
- "; COMPILED C CODE HERE\n");
- }
- }
- STATIC
- void GenStartCommentLine(void)
- {
- printf2(" ; ");
- }
- // No alignment needed on B32P
- STATIC
- void GenWordAlignment(int bss)
- {
- (void)bss;
- printf2("; .align 2\n");
- }
- STATIC
- void GenLabel(char* Label, int Static)
- {
- {
- if (!Static && GenExterns)
- printf2("; .globl %s\n", Label);
- printf2("%s:\n", Label);
- }
- }
- STATIC
- void GenPrintLabel(char* Label)
- {
- {
- if (isdigit(*Label))
- printf2("Label_%s", Label);
- else
- printf2("%s", Label);
- }
- }
- STATIC
- void GenNumLabel(int Label)
- {
- printf2("Label_%d:\n", Label);
- }
- STATIC
- void GenPrintNumLabel(int label)
- {
- printf2("Label_%d", label);
- }
- STATIC
- void GenZeroData(unsigned Size, int bss)
- {
- (void)bss;
- printf2("; .space %u\n", truncUint(Size));
- // B32P implementation of .space:
- if (Size > 0)
- {
- printf2(".dw");
- int i;
- for (i = 0; i < Size; i++)
- {
- printf2(" 0");
- }
- printf2("\n");
- }
- }
- STATIC
- void GenIntData(int Size, int Val)
- {
- Val = truncInt(Val);
- // Print multiple times, since the compiler does not know yet B32P is word addressable
- if (Size == 1)
- printf2(" .dw %d\n", Val);
- else if (Size == 2)
- printf2(" .dw %d %d\n", Val, Val);
- else if (Size == 4)
- printf2(" .dw %d %d %d %d\n", Val, Val, Val, Val);
-
- }
- STATIC
- void GenStartAsciiString(void)
- {
- printf2(".dw "); // String should be converted into 1 character per word
- }
- STATIC
- void GenAddrData(int Size, char* Label, int ofs)
- {
- ofs = truncInt(ofs);
- int i;
- for (i = 0; i < 4; i++) // label is 4 "bytes", hotfix since the compiler does not know yet B32P is word addressable
- {
- printf2(".dl ");
- GenPrintLabel(Label);
- // Still not sure if this ever gets called (and probably will not work until an Assembler update)
- if (ofs)
- printf2(" %+d", ofs);
- puts2("");
- }
- }
- STATIC
- int GenFxnSizeNeeded(void)
- {
- return 0;
- }
- STATIC
- void GenRecordFxnSize(char* startLabelName, int endLabelNo)
- {
- (void)startLabelName;
- (void)endLabelNo;
- }
- #define B32PInstrHalt 0x30
- #define B32PInstrRead 0x31
- #define B32PInstrWrite 0x32
- #define B32PInstrIntID 0x33
- #define B32PInstrPush 0x34
- #define B32PInstrPop 0x35
- #define B32PInstrJump 0x36
- #define B32PInstrJumpo 0x37
- #define B32PInstrJumpr 0x38
- #define B32PInstrJumpro 0x39
- #define B32PInstrBEQ 0x3A
- #define B32PInstrBGT 0x3B
- #define B32PInstrBGTS 0x3C
- #define B32PInstrBGE 0x3D
- #define B32PInstrBGES 0x3E
- #define B32PInstrBNE 0x3F
- #define B32PInstrBLT 0x40
- #define B32PInstrBLTS 0x41
- #define B32PInstrBLE 0x42
- #define B32PInstrBLES 0x43
- #define B32PInstrSavPC 0x44
- #define B32PInstrReti 0x45
- #define B32PInstrOR 0x46
- #define B32PInstrAND 0x47
- #define B32PInstrXOR 0x48
- #define B32PInstrADD 0x49
- #define B32PInstrSUB 0x4A
- #define B32PInstrSHIFTL 0x4B
- #define B32PInstrSHIFTR 0x4C
- #define B32PInstrNOT 0x4D
- #define B32PInstrMULTS 0x4E
- #define B32PInstrMULTU 0x4F
- #define B32PInstrSLT 0x50
- #define B32PInstrSLTU 0x51
- #define B32PInstrLoad 0x52
- #define B32PInstrLoadHi 0x53
- #define B32PInstrAddr2reg 0x54
- #define B32PInstrLoad32 0x55
- #define B32PInstrNOP 0x56
- STATIC
- void GenPrintInstr(int instr, int val)
- {
- char* p = "";
- (void)val;
- switch (instr)
- {
- case B32PInstrHalt : p = "halt"; break;
- case B32PInstrRead : p = "read"; break;
- case B32PInstrWrite : p = "write"; break;
- case B32PInstrIntID : p = "readintid"; break;
- case B32PInstrPush : p = "push"; break;
- case B32PInstrPop : p = "pop"; break;
- case B32PInstrJump : p = "jump"; break;
- case B32PInstrJumpo : p = "jumpo"; break;
- case B32PInstrJumpr : p = "jumpr"; break;
- case B32PInstrJumpro : p = "jumpro"; break;
- case B32PInstrBEQ : p = "beq"; break;
- case B32PInstrBGT : p = "bgts"; break; // HACK: Default signed comparison, because of MIPS
- case B32PInstrBGTS : p = "bgts"; break;
- case B32PInstrBGE : p = "bges"; break; // HACK: Default signed comparison, because of MIPS
- case B32PInstrBGES : p = "bges"; break;
- case B32PInstrBNE : p = "bne"; break;
- case B32PInstrBLT : p = "blts"; break; // HACK: Default signed comparison, because of MIPS
- case B32PInstrBLTS : p = "blts"; break;
- case B32PInstrBLE : p = "bles"; break; // HACK: Default signed comparison, because of MIPS
- case B32PInstrBLES : p = "bles"; break;
- case B32PInstrSavPC : p = "savpc"; break;
- case B32PInstrReti : p = "reti"; break;
- case B32PInstrOR : p = "or"; break;
- case B32PInstrAND : p = "and"; break;
- case B32PInstrXOR : p = "xor"; break;
- case B32PInstrADD : p = "add"; break;
- case B32PInstrSUB : p = "sub"; break;
- case B32PInstrSHIFTL : p = "shiftl"; break;
- case B32PInstrSHIFTR : p = "shiftr"; break;
- case B32PInstrNOT : p = "not"; break;
- case B32PInstrMULTS : p = "mults"; break;
- case B32PInstrMULTU : p = "multu"; break;
- case B32PInstrSLT : p = "slt"; break;
- case B32PInstrSLTU : p = "sltu"; break;
- case B32PInstrLoad : p = "load32"; break;
- case B32PInstrLoadHi : p = "loadhi"; break;
- case B32PInstrAddr2reg : p = "addr2reg"; break;
- case B32PInstrLoad32 : p = "load32"; break;
- }
- printf2(" %s ", p);
- }
- #define B32POpRegZero 0x00 //0 0
- #define B32POpRegAt 0x01 //1 at
- #define B32POpRegV0 0x02 //2 ret0
- #define B32POpRegV1 0x03 //3 ret1
- #define B32POpRegA0 0x04 //4 arg0
- #define B32POpRegA1 0x05 //5 arg1
- #define B32POpRegA2 0x06 //6 arg2
- #define B32POpRegA3 0x07 //7 arg3
- #define B32POpRegT0 0x08 //8 gp0
- #define B32POpRegT1 0x09 //9 gp1
- #define B32POpRegT2 0x0A //10 gp2
- #define B32POpRegT8 0x0B //11 tempa
- #define B32POpRegT9 0x0C //12 tempb
- #define B32POpRegSp 0x0D //13 sp
- #define B32POpRegFp 0x0E //14 fp
- #define B32POpRegRa 0x0F //15 retaddr
- #define B32POpIndRegZero 0x20
- #define B32POpIndRegAt 0x21
- #define B32POpIndRegV0 0x22
- #define B32POpIndRegV1 0x23
- #define B32POpIndRegA0 0x24
- #define B32POpIndRegA1 0x25
- #define B32POpIndRegA2 0x26
- #define B32POpIndRegA3 0x27
- #define B32POpIndRegT0 0x28
- #define B32POpIndRegT1 0x29
- #define B32POpIndRegSp 0x2D
- #define B32POpIndRegFp 0x2E
- #define B32POpIndRegRa 0x2F
- #define B32POpConst 0x80
- #define B32POpLabel 0x81
- #define B32POpNumLabel 0x82
- #define B32POpLabelLo 0x83
- #define B32POpIndLocal B32POpIndRegFp
- #define MAX_TEMP_REGS 3 // this many temp registers used beginning with T0 to hold subexpression results
- #define TEMP_REG_A B32POpRegT8 // two temporary registers used for momentary operations, similarly to the AT register
- #define TEMP_REG_B B32POpRegT9
- STATIC
- void GenPrintOperand(int op, int val)
- {
- if (op >= B32POpRegZero && op <= B32POpRegRa)
- {
- printf2("r%d", op);
- }
- else if (op >= B32POpIndRegZero && op <= B32POpIndRegRa)
- {
- printf2("%d r%d", truncInt(val), op - B32POpIndRegZero);
- }
- else
- {
- switch (op)
- {
- case B32POpConst: printf2("%d", truncInt(val)); break;
- case B32POpLabelLo:
- printf2("%%lo(");
- GenPrintLabel(IdentTable + val);
- printf2(")(r1)");
- break;
- case B32POpLabel: GenPrintLabel(IdentTable + val); break;
- case B32POpNumLabel: GenPrintNumLabel(val); break;
- default:
- errorInternal(100);
- break;
- }
- }
- }
- STATIC
- void GenPrintOperandSeparator(void)
- {
- printf2(" ");
- }
- STATIC
- void GenPrintNewLine(void)
- {
- puts2("");
- }
- STATIC
- void GenPrintInstr1Operand(int instr, int instrval, int operand, int operandval)
- {
- GenPrintInstr(instr, instrval);
- GenPrintOperand(operand, operandval);
- GenPrintNewLine();
- }
- STATIC
- void GenPrintInstr2Operands(int instr, int instrval, int operand1, int operand1val, int operand2, int operand2val)
- {
- // TODO: figure out if this ever happens because ADD and SUB need 3 args
- if (operand2 == B32POpConst && operand2val == 0 &&
- (instr == B32PInstrADD || instr == B32PInstrSUB))
- return;
- GenPrintInstr(instr, instrval);
- GenPrintOperand(operand1, operand1val);
- GenPrintOperandSeparator();
- GenPrintOperand(operand2, operand2val);
- GenPrintNewLine();
- }
- STATIC
- void GenPrintInstr3Operands(int instr, int instrval,
- int operand1, int operand1val,
- int operand2, int operand2val,
- int operand3, int operand3val)
- {
- if (operand3 == B32POpConst && operand3val == 0 &&
- (instr == B32PInstrADD || instr == B32PInstrSUB) &&
- operand1 == operand2)
- return;
- // If constant is negative, swap B32PInstrADD for B32PInstrSUB and vice versa
- // and flip sign of constant
- if (operand2 == B32POpConst && operand2val < 0)
- {
- if (instr == B32PInstrADD)
- {
- instr = B32PInstrSUB;
- operand2val = -operand2val;
- }
- else if (instr == B32PInstrSUB)
- {
- instr = B32PInstrADD;
- operand2val = -operand2val;
- }
- }
- GenPrintInstr(instr, instrval);
- GenPrintOperand(operand1, operand1val);
- GenPrintOperandSeparator();
- GenPrintOperand(operand2, operand2val);
- GenPrintOperandSeparator();
- GenPrintOperand(operand3, operand3val);
- GenPrintNewLine();
- }
- // Currently we do not want to "extend" any reg
- STATIC
- void GenExtendRegIfNeeded(int reg, int opSz)
- {
-
- }
- STATIC
- void GenJumpUncond(int label)
- {
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- }
- extern int GenWreg; // GenWreg is defined below
- STATIC
- void GenJumpIfEqual(int val, int label)
- {
- GenPrintInstr2Operands(B32PInstrLoad, 0,
- B32POpConst, val,
- TEMP_REG_B, 0);
- /*
- GenPrintInstr3Operands(MipsInstrBEQ, 0,
- GenWreg, 0,
- TEMP_REG_B, 0,
- B32POpNumLabel, label);
- */
- GenPrintInstr3Operands(B32PInstrBNE, 0,
- GenWreg, 0,
- TEMP_REG_B, 0,
- B32POpConst, 2);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- }
- STATIC
- void GenJumpIfZero(int label)
- {
- #ifndef NO_ANNOTATIONS
- printf2(" ; JumpIfZero\n");
- #endif
- /* if Wreg == 0, jump to label
- GenPrintInstr3Operands(MipsInstrBEQ, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpNumLabel, label);
- */
- GenPrintInstr3Operands(B32PInstrBNE, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpConst, 2);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- }
- STATIC
- void GenJumpIfNotZero(int label)
- {
- #ifndef NO_ANNOTATIONS
- printf2(" ; JumpIfNotZero\n");
- #endif
- /* if Wreg != 0, jump to label
- GenPrintInstr3Operands(MipsInstrBNE, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpNumLabel, label);
- */
- GenPrintInstr3Operands(B32PInstrBEQ, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpConst, 2);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- }
- fpos_t GenPrologPos;
- int GenLeaf;
- STATIC
- void GenWriteFrameSize(void) //WORDSIZE
- {
- unsigned size = 8/*RA + FP*/ - CurFxnMinLocalOfs;
- //printf2(" subu r13, r13, %10u\n", size); // 10 chars are enough for 32-bit unsigned ints
- printf2(" sub r13 %10u r13\n", size); // r13 = r13 - size
- //printf2(" sw r14, %10u r13\n", size - 8);
- printf2(" write %10u r13 r14\n", size - 8); // write r14 to memory[r13+(size-8)]
-
- //printf2(" addu r14, r13, %10u\n", size - 8);
- printf2(" add r13 %10u r14\n", size - 8); // r14 = r13 + (size-8)
- //printf2(" %csw r15, 4 r14\n", GenLeaf ? ';' : ' ');
- printf2(" %c write 4 r14 r15\n", GenLeaf ? ';' : ' '); // write r15 to memory[r14+4]
- }
- STATIC
- void GenUpdateFrameSize(void)
- {
- fpos_t pos;
- fgetpos(OutFile, &pos);
- fsetpos(OutFile, &GenPrologPos);
- GenWriteFrameSize();
- fsetpos(OutFile, &pos);
- }
- STATIC
- void GenFxnProlog(void)
- {
- if (CurFxnParamCntMin && CurFxnParamCntMax)
- {
- int i, cnt = CurFxnParamCntMax;
- if (cnt > 4)
- cnt = 4; //WORDSIZE?
- // TBD!!! for structure passing use the cumulative parameter size
- // instead of the number of parameters. Currently this bug is masked
- // by the subroutine that pushes structures on the stack (it copies
- // all words except the first to the stack). But passing structures
- // in registers from assembly code won't always work.
- for (i = 0; i < cnt; i++)
- GenPrintInstr2Operands(B32PInstrWrite, 0,
- B32POpIndRegSp, 4 * i, //WORDSIZE
- B32POpRegA0 + i, 0);
- }
- GenLeaf = 1; // will be reset to 0 if a call is generated
- fgetpos(OutFile, &GenPrologPos);
- GenWriteFrameSize();
- }
- STATIC
- void GenGrowStack(int size) //WORDSIZE
- {
- if (!size)
- return;
- if (size > 0)
- {
- GenPrintInstr3Operands(B32PInstrSUB, 0,
- B32POpRegSp, 0,
- B32POpConst, size,
- B32POpRegSp, 0);
- }
- else
- {
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegSp, 0,
- B32POpConst, -size,
- B32POpRegSp, 0);
- }
- }
- STATIC
- void GenFxnEpilog(void)
- {
- GenUpdateFrameSize();
- if (!GenLeaf)
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegFp, 4, //WORDSIZE
- B32POpRegRa, 0);
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegFp, 0,
- B32POpRegFp, 0);
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegSp, 0,
- B32POpConst, 8/*RA + FP*/ - CurFxnMinLocalOfs, //WORDSIZE
- B32POpRegSp, 0);
- GenPrintInstr2Operands(B32PInstrJumpr, 0,
- B32POpConst, 0,
- B32POpRegRa, 0);
- }
- STATIC
- int GenMaxLocalsSize(void)
- {
- return 0x7FFFFFFF;
- }
- STATIC
- int GenGetBinaryOperatorInstr(int tok)
- {
- switch (tok)
- {
- case tokPostAdd:
- case tokAssignAdd:
- case '+':
- return B32PInstrADD;
- case tokPostSub:
- case tokAssignSub:
- case '-':
- return B32PInstrSUB;
- case '&':
- case tokAssignAnd:
- return B32PInstrAND;
- case '^':
- case tokAssignXor:
- return B32PInstrXOR;
- case '|':
- case tokAssignOr:
- return B32PInstrOR;
- case '<':
- case '>':
- case tokLEQ:
- case tokGEQ:
- case tokEQ:
- case tokNEQ:
- case tokULess:
- case tokUGreater:
- case tokULEQ:
- case tokUGEQ:
- return B32PInstrNOP;
- case '*':
- case tokAssignMul:
- return B32PInstrMULTS;
- case '/':
- case '%':
- case tokAssignDiv:
- case tokAssignMod:
- printf("DIVISION/MOD is not supported!\n");
- return B32PInstrHalt;
- case tokUDiv:
- case tokUMod:
- case tokAssignUDiv:
- case tokAssignUMod:
- printf("DIVISION/MOD is not supported!\n");
- return B32PInstrHalt;
- case tokLShift:
- case tokAssignLSh:
- return B32PInstrSHIFTL;
- case tokRShift:
- case tokAssignRSh:
- return B32PInstrSHIFTR; // B32P does not know about signed, so normal shiftr is done instead
- case tokURShift:
- case tokAssignURSh:
- return B32PInstrSHIFTR;
- default:
- //error("Error: Invalid operator\n");
- errorInternal(101);
- return 0;
- }
- }
- // Should not be needed, AT register is not used by B32P assembler
- // Although the lui instruction probably should stay?
- STATIC
- void GenPreIdentAccess(int label)
- {
- printf2("; .set noat\n lui r1, %%hi(");
- GenPrintLabel(IdentTable + label);
- puts2(")");
- }
- // Should not be needed, AT register is not used by B32P assembler
- STATIC
- void GenPostIdentAccess(void)
- {
- puts2("; .set at");
- }
- STATIC
- void GenReadIdent(int regDst, int opSz, int label)
- {
- GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
- B32POpLabel, label,
- B32POpRegAt, 0);
- GenPrintInstr3Operands(B32PInstrRead, 0,
- B32POpConst, 0,
- B32POpRegAt, 0,
- regDst, 0);
- }
- STATIC
- void GenReadLocal(int regDst, int opSz, int ofs)
- {
- int instr = B32PInstrRead;
- GenPrintInstr2Operands(instr, 0,
- B32POpIndRegFp, ofs,
- regDst, 0);
- }
- STATIC
- void GenReadIndirect(int regDst, int regSrc, int opSz)
- {
- int instr = B32PInstrRead;
- GenPrintInstr2Operands(instr, 0,
- regSrc + B32POpIndRegZero, 0,
- regDst, 0);
- }
- STATIC
- void GenWriteIdent(int regSrc, int opSz, int label)
- {
- GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
- B32POpLabel, label,
- B32POpRegAt, 0);
- GenPrintInstr3Operands(B32PInstrWrite, 0,
- B32POpConst, 0,
- B32POpRegAt, 0,
- regSrc, 0);
- }
- STATIC
- void GenWriteLocal(int regSrc, int opSz, int ofs)
- {
- int instr = B32PInstrWrite;
- GenPrintInstr2Operands(instr, 0,
- B32POpIndRegFp, ofs,
- regSrc, 0);
- }
- STATIC
- void GenWriteIndirect(int regDst, int regSrc, int opSz)
- {
- int instr = B32PInstrWrite;
- GenPrintInstr2Operands(instr, 0,
- regDst + B32POpIndRegZero, 0,
- regSrc, 0);
- }
- STATIC
- void GenIncDecIdent(int regDst, int opSz, int label, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokInc)
- instr = B32PInstrSUB;
- GenReadIdent(regDst, opSz, label);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteIdent(regDst, opSz, label);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- STATIC
- void GenIncDecLocal(int regDst, int opSz, int ofs, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokInc)
- instr = B32PInstrSUB;
- GenReadLocal(regDst, opSz, ofs);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteLocal(regDst, opSz, ofs);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- STATIC
- void GenIncDecIndirect(int regDst, int regSrc, int opSz, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokInc)
- instr = B32PInstrSUB;
- GenReadIndirect(regDst, regSrc, opSz);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteIndirect(regSrc, regDst, opSz);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- STATIC
- void GenPostIncDecIdent(int regDst, int opSz, int label, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokPostInc)
- instr = B32PInstrSUB;
- GenReadIdent(regDst, opSz, label);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteIdent(regDst, opSz, label);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, -1,
- regDst, 0);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- STATIC
- void GenPostIncDecLocal(int regDst, int opSz, int ofs, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokPostInc)
- instr = B32PInstrSUB;
- GenReadLocal(regDst, opSz, ofs);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteLocal(regDst, opSz, ofs);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, -1,
- regDst, 0);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- STATIC
- void GenPostIncDecIndirect(int regDst, int regSrc, int opSz, int tok)
- {
- int instr = B32PInstrADD;
- if (tok != tokPostInc)
- instr = B32PInstrSUB;
- GenReadIndirect(regDst, regSrc, opSz);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, 1,
- regDst, 0);
- GenWriteIndirect(regSrc, regDst, opSz);
- GenPrintInstr3Operands(instr, 0,
- regDst, 0,
- B32POpConst, -1,
- regDst, 0);
- GenExtendRegIfNeeded(regDst, opSz);
- }
- int CanUseTempRegs;
- int TempsUsed;
- int GenWreg = B32POpRegV0; // current working register (V0 or Tn or An)
- int GenLreg, GenRreg; // left operand register and right operand register after GenPopReg()
- /*
- General idea behind GenWreg, GenLreg, GenRreg:
- - In expressions w/o function calls:
- Subexpressions are evaluated in V0, T0, T1, ..., T<MAX_TEMP_REGS-1>. If those registers
- aren't enough, the stack is used additionally.
- The expression result ends up in V0, which is handy for returning from
- functions.
- In the process, GenWreg is the current working register and is one of: V0, T0, T1, ... .
- All unary operators are evaluated in the current working register.
- GenPushReg() and GenPopReg() advance GenWreg as needed when handling binary operators.
- GenPopReg() sets GenWreg, GenLreg and GenRreg. GenLreg and GenRreg are the registers
- where the left and right operands of a binary operator are.
- When the exression runs out of the temporary registers, the stack is used. While it is being
- used, GenWreg remains equal to the last temporary register, and GenPopReg() sets GenLreg = TEMP_REG_A.
- Hence, after GenPopReg() the operands of the binary operator are always in registers and can be
- directly manipulated with.
- Following GenPopReg(), binary operator evaluation must take the left and right operands from
- GenLreg and GenRreg and write the evaluated result into GenWreg. Care must be taken as GenWreg
- will be the same as either GenLreg (when the popped operand comes from T0-T<MAX_TEMP_REGS-1>)
- or GenRreg (when the popped operand comes from the stack in TEMP_REG_A).
- - In expressions with function calls:
- GenWreg is always V0 in subexpressions that aren't function parameters. These subexpressions
- get automatically pushed onto the stack as necessary.
- GenWreg is always V0 in expressions, where return values from function calls are used as parameters
- into other called functions. IOW, this is the case when the function call depth is greater than 1.
- Subexpressions in such expressions get automatically pushed onto the stack as necessary.
- GenWreg is A0-A3 in subexpressions that are function parameters when the function call depth is 1.
- Basically, while a function parameter is evaluated, it's evaluated in the register from where
- the called function will take it. This avoids some of unnecessary register copies and stack
- manipulations in the most simple and very common cases of function calls.
- */
- STATIC
- void GenWregInc(int inc)
- {
- if (inc > 0)
- {
- // Advance the current working register to the next available temporary register
- if (GenWreg == B32POpRegV0)
- GenWreg = B32POpRegT0;
- else
- GenWreg++;
- }
- else
- {
- // Return to the previous current working register
- if (GenWreg == B32POpRegT0)
- GenWreg = B32POpRegV0;
- else
- GenWreg--;
- }
- }
- STATIC
- void GenPushReg(void)
- {
- if (CanUseTempRegs && TempsUsed < MAX_TEMP_REGS)
- {
- GenWregInc(1);
- TempsUsed++;
- return;
- }
- GenPrintInstr3Operands(B32PInstrSUB, 0,
- B32POpRegSp, 0,
- B32POpConst, 4, //WORDSIZE
- B32POpRegSp, 0);
- GenPrintInstr2Operands(B32PInstrWrite, 0,
- B32POpIndRegSp, 0,
- GenWreg, 0);
- TempsUsed++;
- }
- STATIC
- void GenPopReg(void)
- {
- TempsUsed--;
- if (CanUseTempRegs && TempsUsed < MAX_TEMP_REGS)
- {
- GenRreg = GenWreg;
- GenWregInc(-1);
- GenLreg = GenWreg;
- return;
- }
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegSp, 0,
- TEMP_REG_A, 0);
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegSp, 0,
- B32POpConst, 4, //WORDSIZE
- B32POpRegSp, 0);
- GenLreg = TEMP_REG_A;
- GenRreg = GenWreg;
- }
- #define tokRevIdent 0x100
- #define tokRevLocalOfs 0x101
- #define tokAssign0 0x102
- #define tokNum0 0x103
- STATIC
- void GenPrep(int* idx)
- {
- int tok;
- int oldIdxRight, oldIdxLeft, t0, t1;
- if (*idx < 0)
- //error("GenFuse(): idx < 0\n");
- errorInternal(100);
- tok = stack[*idx][0];
- oldIdxRight = --*idx;
- switch (tok)
- {
- case tokUDiv:
- case tokUMod:
- case tokAssignUDiv:
- case tokAssignUMod:
- if (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint)
- {
- // Change unsigned division to right shift and unsigned modulo to bitwise and
- unsigned m = truncUint(stack[oldIdxRight][1]);
- if (m && !(m & (m - 1)))
- {
- if (tok == tokUMod || tok == tokAssignUMod)
- {
- stack[oldIdxRight][1] = (int)(m - 1);
- tok = (tok == tokUMod) ? '&' : tokAssignAnd;
- }
- else
- {
- t1 = 0;
- while (m >>= 1) t1++;
- stack[oldIdxRight][1] = t1;
- tok = (tok == tokUDiv) ? tokURShift : tokAssignURSh;
- }
- stack[oldIdxRight + 1][0] = tok;
- }
- }
- }
- switch (tok)
- {
- case tokNumUint:
- stack[oldIdxRight + 1][0] = tokNumInt; // reduce the number of cases since tokNumInt and tokNumUint are handled the same way
- // fallthrough
- case tokNumInt:
- case tokNum0:
- case tokIdent:
- case tokLocalOfs:
- break;
- case tokPostAdd:
- case tokPostSub:
- case '-':
- case '/':
- case '%':
- case tokUDiv:
- case tokUMod:
- case tokLShift:
- case tokRShift:
- case tokURShift:
- case tokLogAnd:
- case tokLogOr:
- case tokComma:
- GenPrep(idx);
- // fallthrough
- case tokShortCirc:
- case tokGoto:
- case tokUnaryStar:
- case tokInc:
- case tokDec:
- case tokPostInc:
- case tokPostDec:
- case '~':
- case tokUnaryPlus:
- case tokUnaryMinus:
- case tok_Bool:
- case tokVoid:
- case tokUChar:
- case tokSChar:
- case tokShort:
- case tokUShort:
- GenPrep(idx);
- break;
- case '=':
- if (oldIdxRight + 1 == sp - 1 &&
- (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint) &&
- truncUint(stack[oldIdxRight][1]) == 0)
- {
- // Special case for assigning 0 while throwing away the expression result value
- // TBD??? ,
- stack[oldIdxRight][0] = tokNum0; // this zero constant will not be loaded into a register
- stack[oldIdxRight + 1][0] = tokAssign0; // change '=' to tokAssign0
- }
- // fallthrough
- case tokAssignAdd:
- case tokAssignSub:
- case tokAssignMul:
- case tokAssignDiv:
- case tokAssignUDiv:
- case tokAssignMod:
- case tokAssignUMod:
- case tokAssignLSh:
- case tokAssignRSh:
- case tokAssignURSh:
- case tokAssignAnd:
- case tokAssignXor:
- case tokAssignOr:
- GenPrep(idx);
- oldIdxLeft = *idx;
- GenPrep(idx);
- // If the left operand is an identifier (with static or auto storage), swap it with the right operand
- // and mark it specially, so it can be used directly
- if ((t0 = stack[oldIdxLeft][0]) == tokIdent || t0 == tokLocalOfs)
- {
- t1 = stack[oldIdxLeft][1];
- memmove(stack[oldIdxLeft], stack[oldIdxLeft + 1], (oldIdxRight - oldIdxLeft) * sizeof(stack[0]));
- stack[oldIdxRight][0] = (t0 == tokIdent) ? tokRevIdent : tokRevLocalOfs;
- stack[oldIdxRight][1] = t1;
- }
- break;
- case '+':
- case '*':
- case '&':
- case '^':
- case '|':
- case tokEQ:
- case tokNEQ:
- case '<':
- case '>':
- case tokLEQ:
- case tokGEQ:
- case tokULess:
- case tokUGreater:
- case tokULEQ:
- case tokUGEQ:
- GenPrep(idx);
- oldIdxLeft = *idx;
- GenPrep(idx);
- // If the right operand isn't a constant, but the left operand is, swap the operands
- // so the constant can become an immediate right operand in the instruction
- t1 = stack[oldIdxRight][0];
- t0 = stack[oldIdxLeft][0];
- if (t1 != tokNumInt && t0 == tokNumInt)
- {
- int xor;
- t1 = stack[oldIdxLeft][1];
- memmove(stack[oldIdxLeft], stack[oldIdxLeft + 1], (oldIdxRight - oldIdxLeft) * sizeof(stack[0]));
- stack[oldIdxRight][0] = t0;
- stack[oldIdxRight][1] = t1;
- switch (tok)
- {
- case '<':
- case '>':
- xor = '<' ^ '>'; break;
- case tokLEQ:
- case tokGEQ:
- xor = tokLEQ ^ tokGEQ; break;
- case tokULess:
- case tokUGreater:
- xor = tokULess ^ tokUGreater; break;
- case tokULEQ:
- case tokUGEQ:
- xor = tokULEQ ^ tokUGEQ; break;
- default:
- xor = 0; break;
- }
- tok ^= xor;
- }
- // Handle a few special cases and transform the instruction
- if (stack[oldIdxRight][0] == tokNumInt)
- {
- unsigned m = truncUint(stack[oldIdxRight][1]);
- switch (tok)
- {
- case '*':
- // Change multiplication to left shift, this helps indexing arrays of ints/pointers/etc
- if (m && !(m & (m - 1)))
- {
- t1 = 0;
- while (m >>= 1) t1++;
- stack[oldIdxRight][1] = t1;
- tok = tokLShift;
- }
- break;
- case tokLEQ:
- // left <= const will later change to left < const+1, but const+1 must be <=0x7FFFFFFF
- if (m == 0x7FFFFFFF)
- {
- // left <= 0x7FFFFFFF is always true, change to the equivalent left >= 0u
- stack[oldIdxRight][1] = 0;
- tok = tokUGEQ;
- }
- break;
- case tokULEQ:
- // left <= const will later change to left < const+1, but const+1 must be <=0xFFFFFFFFu
- if (m == 0xFFFFFFFF)
- {
- // left <= 0xFFFFFFFFu is always true, change to the equivalent left >= 0u
- stack[oldIdxRight][1] = 0;
- tok = tokUGEQ;
- }
- break;
- case '>':
- // left > const will later change to !(left < const+1), but const+1 must be <=0x7FFFFFFF
- if (m == 0x7FFFFFFF)
- {
- // left > 0x7FFFFFFF is always false, change to the equivalent left & 0
- stack[oldIdxRight][1] = 0;
- tok = '&';
- }
- break;
- case tokUGreater:
- // left > const will later change to !(left < const+1), but const+1 must be <=0xFFFFFFFFu
- if (m == 0xFFFFFFFF)
- {
- // left > 0xFFFFFFFFu is always false, change to the equivalent left & 0
- stack[oldIdxRight][1] = 0;
- tok = '&';
- }
- break;
- }
- }
- stack[oldIdxRight + 1][0] = tok;
- break;
- case ')':
- while (stack[*idx][0] != '(')
- {
- GenPrep(idx);
- if (stack[*idx][0] == ',')
- --*idx;
- }
- --*idx;
- break;
- default:
- //error("GenPrep: unexpected token %s\n", GetTokenName(tok));
- errorInternal(101);
- }
- }
- /*
- ; l <[u] 0 // slt[u] w, w, 0 "k"
- l <[u] const // slt[u] w, w, const "m"
- l <[u] r // slt[u] w, l, r "i"
- * if (l < 0) // bgez w, Lskip "f"
- if (l <[u] const) // slt[u] w, w, const; beq w, r0, Lskip "mc"
- if (l <[u] r) // slt[u] w, l, r; beq w, r0, Lskip "ic"
- ; l <=[u] 0 // slt[u] w, w, 1 "l"
- l <=[u] const // slt[u] w, w, const + 1 "n"
- l <=[u] r // slt[u] w, r, l; xor w, w, 1 "js"
- * if (l <= 0) // bgtz w, Lskip "g"
- if (l <=[u] const) // slt[u] w, w, const + 1; beq w, r0, Lskip "nc"
- if (l <=[u] r) // slt[u] w, r, l; bne w, r0, Lskip "jd"
- l >[u] 0 // slt[u] w, r0, w "o"
- l >[u] const // slt[u] w, w, const + 1; xor w, w, 1 "ns"
- l >[u] r // slt[u] w, r, l "j"
- * if (l > 0) // blez w, Lskip "h"
- **if (l >u 0) // beq w, r0, Lskip
- if (l >[u] const) // slt[u] w, w, const + 1; bne w, r0, Lskip "nd"
- if (l >[u] r) // slt[u] w, r, l; beq w, r0, Lskip "jc"
- ; l >=[u] 0 // slt[u] w, w, 0; xor w, w, 1 "ks"
- l >=[u] const // slt[u] w, w, const; xor w, w, 1 "ms"
- l >=[u] r // slt[u] w, l, r; xor w, w, 1 "is"
- * if (l >= 0) // bltz w, Lskip "e"
- if (l >=[u] const) // slt[u] w, w, const; bne w, r0, Lskip "md"
- if (l >=[u] r) // slt[u] w, l, r; bne w, r0, Lskip "id"
- l == 0 // sltu w, w, 1 "q"
- l == const // xor w, w, const; sltu w, w, 1 "tq"
- l == r // xor w, l, r; sltu w, w, 1 "rq"
- if (l == 0) // bne w, r0, Lskip "d"
- if (l == const) // xor w, w, const; bne w, r0, Lskip "td"
- if (l == r) // bne l, r, Lskip "b"
- l != 0 // sltu w, r0, w "p"
- l != const // xor w, w, const; sltu w, r0, w "tp"
- l != r // xor w, l, r; sltu w, r0, w "rp"
- if (l != 0) // beq w, r0, Lskip "c"
- if (l != const) // xor w, w, const; beq w, r0, Lskip "tc"
- if (l != r) // beq l, r, Lskip "a"
- */
- char CmpBlocks[6/*op*/][2/*condbranch*/][3/*constness*/][2] =
- {
- {
- { "k", "m", "i" },
- { "f", "mc", "ic" }
- },
- {
- { "l", "n", "js" },
- { "g", "nc", "jd" }
- },
- {
- { "o", "ns", "j" },
- { "h", "nd", "jc" }
- },
- {
- { "ks", "ms", "is" },
- { "e", "md", "id" }
- },
- {
- { "q", "tq", "rq" },
- { "d", "td", "b" }
- },
- {
- { "p", "tp", "rp" },
- { "c", "tc", "a" }
- }
- };
- STATIC
- void GenCmp(int* idx, int op)
- {
- // TODO:
- /*
- For B322 (not B32P!): direct conversion from MIPS to B322 is very inefficient, these notes help:
- MIPS:
- slt reg, s < t (reg := 1, else reg := 0)
- B322 equivalent:
- bge s >= t 2
- load 1 reg
- load 0 reg
- */
- /*
- Inverses:
- BEQ a b BNE a b
- BNE a b BEQ a b
- BLTZ a (a < 0) BGE a r0 (a >= 0)
- BGEZ a (a >=0) BGT r0 a (a < 0) == (0 > a)
- BGTZ a (a > 0) BGE r0 a (a <= 0) == (0 >= a)
- BLEZ a (a <=0) BGT a r0 (a > 0)
- */
- // constness: 0 = zero const, 1 = non-zero const, 2 = non-const
- int constness = (stack[*idx - 1][0] == tokNumInt) ? (stack[*idx - 1][1] != 0) : 2;
- int constval = (constness == 1) ? truncInt(stack[*idx - 1][1]) : 0;
- // condbranch: 0 = no conditional branch, 1 = branch if true, 2 = branch if false
- int condbranch = (*idx + 1 < sp) ? (stack[*idx + 1][0] == tokIf) + (stack[*idx + 1][0] == tokIfNot) * 2 : 0;
- int unsign = op >> 4;
- int slt = unsign ? B32PInstrSLTU : B32PInstrSLT;
- int label = condbranch ? stack[*idx + 1][1] : 0;
- char* p;
- int i;
- op &= 0xF;
- if (constness == 2)
- GenPopReg();
- // bltz, blez, bgez, bgtz are for signed comparison with 0 only,
- // so for conditional branches on <0u, <=0u, >0u, >=0u use the general method instead
- if (condbranch && op < 4 && constness == 0 && unsign)
- {
- // Except, >0u is more optimal as !=0
- if (op == 2)
- op = 5;
- else
- constness = 1;
- }
- p = CmpBlocks[op][condbranch != 0][constness];
- for (i = 0; i < 2; i++)
- {
- switch (p[i])
- {
- case 'a':
- condbranch ^= 3;
- // fallthrough
- case 'b':
- GenPrintInstr3Operands((condbranch == 1) ? B32PInstrBNE : B32PInstrBEQ, 0,
- GenLreg, 0,
- GenRreg, 0,
- B32POpConst, 2);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- break;
- case 'c':
- condbranch ^= 3;
- // fallthrough
- case 'd':
- GenPrintInstr3Operands((condbranch == 1) ? B32PInstrBNE : B32PInstrBEQ, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpConst, 2);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- break;
- case 'e':
- condbranch ^= 3;
- // fallthrough
- case 'f':
- /*
- BLTZ a (a < 0) BGE a r0 (a >= 0)
- BGEZ a (a >=0) BGT r0 a (a < 0) == (0 > a)
- */
- if (condbranch == 1)
- {
- GenPrintInstr3Operands(B32PInstrBGE, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpConst, 2);
- }
- else
- {
- GenPrintInstr3Operands(B32PInstrBGT, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- B32POpConst, 2);
- }
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- break;
- case 'g':
- condbranch ^= 3;
- // fallthrough
- case 'h':
- /*
- BGTZ a (a > 0) BGE r0 a (a <= 0) == (0 >= a)
- BLEZ a (a <=0) BGT a r0 (a > 0)
- */
- if (condbranch == 1)
- {
- GenPrintInstr3Operands(B32PInstrBGE, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- B32POpConst, 2);
- }
- else
- {
- GenPrintInstr3Operands(B32PInstrBGT, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- B32POpConst, 2);
- }
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpNumLabel, label);
- break;
- case 'i':
- GenPrintInstr3Operands(slt, 0,
- GenLreg, 0,
- GenRreg, 0,
- GenWreg, 0);
- break;
- case 'j':
- GenPrintInstr3Operands(slt, 0,
- GenRreg, 0,
- GenLreg, 0,
- GenWreg, 0);
- break;
- case 'k':
- GenPrintInstr3Operands(slt, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- GenWreg, 0);
- break;
- case 'l':
- GenPrintInstr3Operands(slt, 0,
- GenWreg, 0,
- B32POpConst, 1,
- GenWreg, 0);
- break;
- case 'n':
- constval++;
- // fallthrough
- case 'm':
- if (constval < 0x8000)
- {
- GenPrintInstr3Operands(slt, 0,
- GenWreg, 0,
- B32POpConst, constval,
- GenWreg, 0);
- }
- else
- {
- GenPrintInstr2Operands(B32PInstrLoad, 0,
- B32POpConst, constval,
- TEMP_REG_A, 0);
- GenPrintInstr3Operands(slt, 0,
- GenWreg, 0,
- TEMP_REG_A, 0,
- GenWreg, 0);
- }
-
- break;
- case 'o':
- GenPrintInstr3Operands(slt, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- GenWreg, 0);
- break;
- case 'p':
- GenPrintInstr3Operands(B32PInstrSLTU, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- GenWreg, 0);
- break;
- case 'q':
- GenPrintInstr3Operands(B32PInstrSLTU, 0,
- GenWreg, 0,
- B32POpConst, 1,
- GenWreg, 0);
- break;
- case 'r':
- GenPrintInstr3Operands(B32PInstrXOR, 0,
- GenLreg, 0,
- GenRreg, 0,
- GenWreg, 0);
- break;
- case 's':
- GenPrintInstr3Operands(B32PInstrXOR, 0,
- GenWreg, 0,
- B32POpConst, 1,
- GenWreg, 0);
- break;
- case 't':
- if (constval < 0x8000)
- {
- GenPrintInstr3Operands(B32PInstrXOR, 0,
- GenWreg, 0,
- B32POpConst, constval,
- GenWreg, 0);
- }
- else
- {
- GenPrintInstr2Operands(B32PInstrLoad, 0,
- B32POpConst, constval,
- TEMP_REG_A, 0);
- GenPrintInstr3Operands(B32PInstrXOR, 0,
- GenWreg, 0,
- TEMP_REG_A, 0,
- GenWreg, 0);
- }
- break;
- }
- }
- *idx += condbranch != 0;
- }
- STATIC
- int GenIsCmp(int t)
- {
- return
- t == '<' ||
- t == '>' ||
- t == tokGEQ ||
- t == tokLEQ ||
- t == tokULess ||
- t == tokUGreater ||
- t == tokUGEQ ||
- t == tokULEQ ||
- t == tokEQ ||
- t == tokNEQ;
- }
- // Improved register/stack-based code generator
- // DONE: test 32-bit code generation
- STATIC
- void GenExpr0(void)
- {
- int i;
- int gotUnary = 0;
- int maxCallDepth = 0;
- int callDepth = 0;
- int paramOfs = 0;
- int t = sp - 1;
- if (stack[t][0] == tokIf || stack[t][0] == tokIfNot || stack[t][0] == tokReturn)
- t--;
- GenPrep(&t);
- for (i = 0; i < sp; i++)
- if (stack[i][0] == '(')
- {
- if (++callDepth > maxCallDepth)
- maxCallDepth = callDepth;
- }
- else if (stack[i][0] == ')')
- {
- callDepth--;
- }
- CanUseTempRegs = maxCallDepth == 0;
- TempsUsed = 0;
- if (GenWreg != B32POpRegV0)
- errorInternal(102);
- for (i = 0; i < sp; i++)
- {
- int tok = stack[i][0];
- int v = stack[i][1];
- #ifndef NO_ANNOTATIONS
- switch (tok)
- {
- case tokNumInt: printf2(" ; %d\n", truncInt(v)); break;
- //case tokNumUint: printf2(" ; %uu\n", truncUint(v)); break;
- case tokIdent: case tokRevIdent: printf2(" ; %s\n", IdentTable + v); break;
- case tokLocalOfs: case tokRevLocalOfs: printf2(" ; local ofs\n"); break;
- case ')': printf2(" ; ) fxn call\n"); break;
- case tokUnaryStar: printf2(" ; * (read dereference)\n"); break;
- case '=': printf2(" ; = (write dereference)\n"); break;
- case tokShortCirc: printf2(" ; short-circuit "); break;
- case tokGoto: printf2(" ; sh-circ-goto "); break;
- case tokLogAnd: printf2(" ; short-circuit && target\n"); break;
- case tokLogOr: printf2(" ; short-circuit || target\n"); break;
- case tokIf: case tokIfNot: case tokReturn: break;
- case tokNum0: printf2(" ; 0\n"); break;
- case tokAssign0: printf2(" ; =\n"); break;
- default: printf2(" ; %s\n", GetTokenName(tok)); break;
- }
- #endif
- switch (tok)
- {
- case tokNumInt:
- if (!(i + 1 < sp && ((t = stack[i + 1][0]) == '+' ||
- t == '-' ||
- t == '&' ||
- t == '^' ||
- t == '|' ||
- t == tokLShift ||
- t == tokRShift ||
- t == tokURShift ||
- GenIsCmp(t))))
- {
- if (gotUnary)
- GenPushReg();
- GenPrintInstr2Operands(B32PInstrLoad, 0,
- B32POpConst, v,
- GenWreg, 0);
- }
- gotUnary = 1;
- break;
- case tokIdent:
- if (gotUnary)
- GenPushReg();
- if (!(i + 1 < sp && ((t = stack[i + 1][0]) == ')' ||
- t == tokUnaryStar ||
- t == tokInc ||
- t == tokDec ||
- t == tokPostInc ||
- t == tokPostDec)))
- {
- GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
- B32POpLabel, v,
- GenWreg, 0);
- }
- gotUnary = 1;
- break;
- case tokLocalOfs:
- if (gotUnary)
- GenPushReg();
- if (!(i + 1 < sp && ((t = stack[i + 1][0]) == tokUnaryStar ||
- t == tokInc ||
- t == tokDec ||
- t == tokPostInc ||
- t == tokPostDec)))
- {
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegFp, 0,
- B32POpConst, v,
- GenWreg, 0);
- }
- gotUnary = 1;
- break;
- case '(':
- if (gotUnary)
- GenPushReg();
- gotUnary = 0;
- if (maxCallDepth != 1 && v < 16)
- GenGrowStack(16 - v);
- paramOfs = v - 4;
- if (maxCallDepth == 1 && paramOfs >= 0 && paramOfs <= 12)
- {
- // Work directly in A0-A3 instead of working in V0 and avoid copying V0 to A0-A3
- GenWreg = B32POpRegA0 + division(paramOfs, 4); //(paramOfs >> 2); //division(paramOfs, 4);
- }
- break;
- case ',':
- if (maxCallDepth == 1)
- {
- if (paramOfs == 16)
- {
- // Got the last on-stack parameter, the rest will go in A0-A3
- GenPushReg();
- gotUnary = 0;
- GenWreg = B32POpRegA3;
- }
- if (paramOfs >= 0 && paramOfs <= 12)
- {
- // Advance to the next An reg or revert to V0
- if (paramOfs)
- GenWreg--;
- else
- GenWreg = B32POpRegV0;
- gotUnary = 0;
- }
- paramOfs -= 4;
- }
- break;
- case ')':
- GenLeaf = 0;
- if (maxCallDepth != 1)
- {
- if (v >= 4)
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegSp, 0,
- B32POpRegA0, 0);
- if (v >= 8)
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegSp, 4,
- B32POpRegA1, 0);
- if (v >= 12)
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegSp, 8,
- B32POpRegA2, 0);
- if (v >= 16)
- GenPrintInstr2Operands(B32PInstrRead, 0,
- B32POpIndRegSp, 12,
- B32POpRegA3, 0);
- }
- else
- {
- GenGrowStack(16);
- }
- if (stack[i - 1][0] == tokIdent)
- {
- GenPrintInstr1Operand(B32PInstrSavPC, 0,
- B32POpRegRa, 0);
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegRa, 0,
- B32POpConst, 3,
- B32POpRegRa, 0);
- GenPrintInstr1Operand(B32PInstrJump, 0,
- B32POpLabel, stack[i - 1][1]);
- }
- else
- {
- GenPrintInstr1Operand(B32PInstrSavPC, 0,
- B32POpRegRa, 0);
- GenPrintInstr3Operands(B32PInstrADD, 0,
- B32POpRegRa, 0,
- B32POpConst, 3,
- B32POpRegRa, 0);
- GenPrintInstr2Operands(B32PInstrJumpr, 0,
- B32POpConst, 0,
- GenWreg, 0);
- }
- if (v < 16)
- v = 16;
- GenGrowStack(-v);
- break;
- case tokUnaryStar:
- if (stack[i - 1][0] == tokIdent)
- GenReadIdent(GenWreg, v, stack[i - 1][1]);
- else if (stack[i - 1][0] == tokLocalOfs)
- GenReadLocal(GenWreg, v, stack[i - 1][1]);
- else
- GenReadIndirect(GenWreg, GenWreg, v);
- break;
- case tokUnaryPlus:
- break;
- case '~': //nor
- GenPrintInstr3Operands(B32PInstrOR, 0,
- GenWreg, 0,
- GenWreg, 0,
- GenWreg, 0);
- GenPrintInstr2Operands(B32PInstrNOT, 0,
- GenWreg, 0,
- GenWreg, 0);
- break;
- case tokUnaryMinus:
- GenPrintInstr3Operands(B32PInstrSUB, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- GenWreg, 0);
- break;
- case '+':
- case '-':
- case '*':
- case '&':
- case '^':
- case '|':
- case tokLShift:
- case tokRShift:
- case tokURShift:
- if (stack[i - 1][0] == tokNumInt && tok != '*')
- {
- int instr = GenGetBinaryOperatorInstr(tok);
- GenPrintInstr3Operands(instr, 0,
- GenWreg, 0,
- B32POpConst, stack[i - 1][1],
- GenWreg, 0);
- }
- else
- {
- int instr = GenGetBinaryOperatorInstr(tok);
- GenPopReg();
- GenPrintInstr3Operands(instr, 0,
- GenLreg, 0,
- GenRreg, 0,
- GenWreg, 0);
- }
- break;
- case '/':
- case tokUDiv:
- case '%':
- case tokUMod:
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPopReg();
- if (tok == '/' || tok == '%')
- GenPrintInstr3Operands(MipsInstrDiv, 0,
- B32POpRegZero, 0,
- GenLreg, 0,
- GenRreg, 0);
- else
- GenPrintInstr3Operands(MipsInstrDivU, 0,
- B32POpRegZero, 0,
- GenLreg, 0,
- GenRreg, 0);
- if (tok == '%' || tok == tokUMod)
- GenPrintInstr1Operand(MipsInstrMfHi, 0,
- GenWreg, 0);
- else
- GenPrintInstr1Operand(MipsInstrMfLo, 0,
- GenWreg, 0);
- */
- }
- break;
- case tokInc:
- case tokDec:
- if (stack[i - 1][0] == tokIdent)
- {
- GenIncDecIdent(GenWreg, v, stack[i - 1][1], tok);
- }
- else if (stack[i - 1][0] == tokLocalOfs)
- {
- GenIncDecLocal(GenWreg, v, stack[i - 1][1], tok);
- }
- else
- {
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- TEMP_REG_A, 0);
- GenIncDecIndirect(GenWreg, TEMP_REG_A, v, tok);
- }
- break;
- case tokPostInc:
- case tokPostDec:
- if (stack[i - 1][0] == tokIdent)
- {
- GenPostIncDecIdent(GenWreg, v, stack[i - 1][1], tok);
- }
- else if (stack[i - 1][0] == tokLocalOfs)
- {
- GenPostIncDecLocal(GenWreg, v, stack[i - 1][1], tok);
- }
- else
- {
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- TEMP_REG_A, 0);
- GenPostIncDecIndirect(GenWreg, TEMP_REG_A, v, tok);
- }
- break;
- case tokPostAdd:
- case tokPostSub:
- {
- int instr = GenGetBinaryOperatorInstr(tok);
- GenPopReg();
- if (GenWreg == GenLreg)
- {
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenLreg, 0,
- TEMP_REG_B, 0);
- GenReadIndirect(GenWreg, TEMP_REG_B, v);
- GenPrintInstr3Operands(instr, 0,
- GenWreg, 0,
- GenRreg, 0,
- TEMP_REG_A, 0);
- GenWriteIndirect(TEMP_REG_B, TEMP_REG_A, v);
- }
- else
- {
- // GenWreg == GenRreg here
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenRreg, 0,
- TEMP_REG_B, 0);
- GenReadIndirect(GenWreg, GenLreg, v);
- GenPrintInstr3Operands(instr, 0,
- GenWreg, 0,
- TEMP_REG_B, 0,
- TEMP_REG_B, 0);
- GenWriteIndirect(GenLreg, TEMP_REG_B, v);
- }
- }
- break;
- case tokAssignAdd:
- case tokAssignSub:
- case tokAssignMul:
- case tokAssignAnd:
- case tokAssignXor:
- case tokAssignOr:
- case tokAssignLSh:
- case tokAssignRSh:
- case tokAssignURSh:
- if (stack[i - 1][0] == tokRevLocalOfs || stack[i - 1][0] == tokRevIdent)
- {
- int instr = GenGetBinaryOperatorInstr(tok);
- if (stack[i - 1][0] == tokRevLocalOfs)
- GenReadLocal(TEMP_REG_B, v, stack[i - 1][1]);
- else
- GenReadIdent(TEMP_REG_B, v, stack[i - 1][1]);
- GenPrintInstr3Operands(instr, 0,
- TEMP_REG_B, 0,
- GenWreg, 0,
- GenWreg, 0);
- if (stack[i - 1][0] == tokRevLocalOfs)
- GenWriteLocal(GenWreg, v, stack[i - 1][1]);
- else
- GenWriteIdent(GenWreg, v, stack[i - 1][1]);
- }
- else
- {
- int instr = GenGetBinaryOperatorInstr(tok);
- int lsaved, rsaved;
- GenPopReg();
- if (GenWreg == GenLreg)
- {
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenLreg, 0,
- TEMP_REG_B, 0);
- lsaved = TEMP_REG_B;
- rsaved = GenRreg;
- }
- else
- {
- // GenWreg == GenRreg here
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenRreg, 0,
- TEMP_REG_B, 0);
- rsaved = TEMP_REG_B;
- lsaved = GenLreg;
- }
- GenReadIndirect(GenWreg, GenLreg, v); // destroys either GenLreg or GenRreg because GenWreg coincides with one of them
- GenPrintInstr3Operands(instr, 0,
- GenWreg, 0,
- rsaved, 0,
- GenWreg, 0);
- GenWriteIndirect(lsaved, GenWreg, v);
- }
- GenExtendRegIfNeeded(GenWreg, v);
- break;
- case tokAssignDiv:
- case tokAssignUDiv:
- case tokAssignMod:
- case tokAssignUMod:
- if (stack[i - 1][0] == tokRevLocalOfs || stack[i - 1][0] == tokRevIdent)
- {
- if (stack[i - 1][0] == tokRevLocalOfs)
- GenReadLocal(TEMP_REG_B, v, stack[i - 1][1]);
- else
- GenReadIdent(TEMP_REG_B, v, stack[i - 1][1]);
- if (tok == tokAssignDiv || tok == tokAssignMod)
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr3Operands(MipsInstrDiv, 0,
- B32POpRegZero, 0,
- TEMP_REG_B, 0,
- GenWreg, 0);*/
- }
- else
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr3Operands(MipsInstrDivU, 0,
- B32POpRegZero, 0,
- TEMP_REG_B, 0,
- GenWreg, 0);*/
- }
- if (tok == tokAssignMod || tok == tokAssignUMod)
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr1Operand(MipsInstrMfHi, 0,
- GenWreg, 0);*/
- }
- else
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr1Operand(MipsInstrMfLo, 0,
- GenWreg, 0);*/
- }
- if (stack[i - 1][0] == tokRevLocalOfs)
- GenWriteLocal(GenWreg, v, stack[i - 1][1]);
- else
- GenWriteIdent(GenWreg, v, stack[i - 1][1]);
- }
- else
- {
- int lsaved, rsaved;
- GenPopReg();
- if (GenWreg == GenLreg)
- {
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenLreg, 0,
- TEMP_REG_B, 0);
- lsaved = TEMP_REG_B;
- rsaved = GenRreg;
- }
- else
- {
- // GenWreg == GenRreg here
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenRreg, 0,
- TEMP_REG_B, 0);
- rsaved = TEMP_REG_B;
- lsaved = GenLreg;
- }
- GenReadIndirect(GenWreg, GenLreg, v); // destroys either GenLreg or GenRreg because GenWreg coincides with one of them
- if (tok == tokAssignDiv || tok == tokAssignMod)
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr3Operands(MipsInstrDiv, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- rsaved, 0);*/
- }
- else
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr3Operands(MipsInstrDivU, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- rsaved, 0);*/
- }
- if (tok == tokAssignMod || tok == tokAssignUMod)
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr1Operand(MipsInstrMfHi, 0,
- GenWreg, 0);*/
- }
- else
- {
- printf("DIVISION/MOD is not supported!\n");
- /*
- GenPrintInstr1Operand(MipsInstrMfLo, 0,
- GenWreg, 0);*/
- }
- GenWriteIndirect(lsaved, GenWreg, v);
- }
- GenExtendRegIfNeeded(GenWreg, v);
- break;
- case '=':
- if (stack[i - 1][0] == tokRevLocalOfs)
- {
- GenWriteLocal(GenWreg, v, stack[i - 1][1]);
- }
- else if (stack[i - 1][0] == tokRevIdent)
- {
- GenWriteIdent(GenWreg, v, stack[i - 1][1]);
- }
- else
- {
- GenPopReg();
- GenWriteIndirect(GenLreg, GenRreg, v);
- if (GenWreg != GenRreg)
- GenPrintInstr3Operands(B32PInstrOR, 0,
- B32POpRegZero, 0,
- GenRreg, 0,
- GenWreg, 0);
- }
- GenExtendRegIfNeeded(GenWreg, v);
- break;
- case tokAssign0: // assignment of 0, while throwing away the expression result value
- if (stack[i - 1][0] == tokRevLocalOfs)
- {
- GenWriteLocal(B32POpRegZero, v, stack[i - 1][1]);
- }
- else if (stack[i - 1][0] == tokRevIdent)
- {
- GenWriteIdent(B32POpRegZero, v, stack[i - 1][1]);
- }
- else
- {
- GenWriteIndirect(GenWreg, B32POpRegZero, v);
- }
- break;
- case '<': GenCmp(&i, 0x00); break;
- case tokLEQ: GenCmp(&i, 0x01); break;
- case '>': GenCmp(&i, 0x02); break;
- case tokGEQ: GenCmp(&i, 0x03); break;
- case tokULess: GenCmp(&i, 0x10); break;
- case tokULEQ: GenCmp(&i, 0x11); break;
- case tokUGreater: GenCmp(&i, 0x12); break;
- case tokUGEQ: GenCmp(&i, 0x13); break;
- case tokEQ: GenCmp(&i, 0x04); break;
- case tokNEQ: GenCmp(&i, 0x05); break;
- case tok_Bool:
- /* if 0 < wreg (if wreg > 0)
- wreg = 1
- else
- wreg = 0
- GenPrintInstr3Operands(MipsInstrSLTU, 0,
- GenWreg, 0,
- B32POpRegZero, 0,
- GenWreg, 0);
- */
- GenPrintInstr3Operands(B32PInstrSLTU, 0,
- B32POpRegZero, 0,
- GenWreg, 0,
- GenWreg, 0);
- break;
- case tokSChar:
- /* just use as an int for now
- GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
- GenWreg, 0,
- B32POpConst, 24,
- GenWreg, 0);
- GenPrintInstr3Operands(B32PInstrSHIFTR, 0, //TODO this should have also replicated the sign bit (SRA)
- GenWreg, 0,
- B32POpConst, 24,
- GenWreg, 0);
- */
- break;
- case tokUChar:
- /* just use as an int for now
- GenPrintInstr3Operands(B32PInstrAND, 0,
- GenWreg, 0,
- B32POpConst, 0xFF,
- GenWreg, 0);
- */
- break;
- case tokShort:
- /* just use as an int for now
- GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
- GenWreg, 0,
- B32POpConst, 16,
- GenWreg, 0);
- GenPrintInstr3Operands(B32PInstrSHIFTR, 0, //TODO this should have also replicated the sign bit (SRA)
- GenWreg, 0,
- B32POpConst, 16,
- GenWreg, 0);
- */
- break;
- case tokUShort:
- /*
- GenPrintInstr3Operands(MipsInstrAnd, 0,
- GenWreg, 0,
- GenWreg, 0,
- B32POpConst, 0xFFFF);*/
- /* just use as an int for now
- GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
- GenWreg, 0,
- B32POpConst, 16,
- GenWreg, 0);
- GenPrintInstr3Operands(B32PInstrSHIFTR, 0,
- GenWreg, 0,
- B32POpConst, 16,
- GenWreg, 0);
- */
- break;
- case tokShortCirc:
- #ifndef NO_ANNOTATIONS
- if (v >= 0)
- printf2("&&\n");
- else
- printf2("||\n");
- #endif
- if (v >= 0)
- GenJumpIfZero(v); // &&
- else
- GenJumpIfNotZero(-v); // ||
- gotUnary = 0;
- break;
- case tokGoto:
- #ifndef NO_ANNOTATIONS
- printf2("goto\n");
- #endif
- GenJumpUncond(v);
- gotUnary = 0;
- break;
- case tokLogAnd:
- case tokLogOr:
- GenNumLabel(v);
- break;
- case tokVoid:
- gotUnary = 0;
- break;
- case tokRevIdent:
- case tokRevLocalOfs:
- case tokComma:
- case tokReturn:
- case tokNum0:
- break;
- case tokIf:
- GenJumpIfNotZero(stack[i][1]);
- break;
- case tokIfNot:
- GenJumpIfZero(stack[i][1]);
- break;
- default:
- //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok));
- errorInternal(103);
- break;
- }
- }
- if (GenWreg != B32POpRegV0)
- errorInternal(104);
- }
- STATIC
- void GenDumpChar(int ch)
- {
- if (ch < 0)
- {
- if (TokenStringLen)
- printf2("\n");
- return;
- }
- if (TokenStringLen == 0)
- {
- GenStartAsciiString();
- //printf2("\"");
- }
- // Just print as ascii value
- printf2("%d ", ch);
- }
- STATIC
- void GenExpr(void)
- {
- GenExpr0();
- }
- STATIC
- void GenFin(void)
- {
- // No idea what this does (something with structs??), so I just literally converted it to B32P asm
- if (StructCpyLabel)
- {
- int lbl = LabelCnt++;
- puts2(CodeHeaderFooter[0]);
- GenNumLabel(StructCpyLabel);
- //puts2(" move r2, r6\n" //r2 := r6
- // " move r3, r6"); //r3 := r3
- puts2(" or r0 r6 r2\n"
- " or r0 r6 r3");
- GenNumLabel(lbl);
- //puts2(" lbu r6, 0 r5\n" // r6:=mem[r5]
- // " addiu r5, r5, 1\n" // r5:= r5+1
- // " addiu r4, r4, -1\n" // r4:= r4-1
- // " sb r6, 0 r3\n" // mem[r3]:=r6
- // " addiu r3, r3, 1"); // r3:= r3+1
- puts2(" read 0 r5 r6\n"
- " add r5 1 r5\n"
- " sub r4 1 r4\n"
- " write 0 r3 r6\n"
- " add r3 1 r3");
- //printf2(" bne r4, r0, "); GenPrintNumLabel(lbl); // if r4 != 0, jump to lbl
- printf2("beq r4 r0 2\n");
- printf2("jump ");GenPrintNumLabel(lbl);
- puts2("");
- puts2(" jumpr 0 r15");
- puts2(CodeHeaderFooter[1]);
- }
- // Put all ending C specific wrapper code here
- if (compileUserBDOS)
- {
- printf2(
- ".code\n"
- "; END OF COMPILED C CODE\n"
- "\n"
- "; Interrupt handlers for BDOS user program\n"
- "; Has some administration before jumping to Label_int[ID]\n"
- "; To prevent interfering with other stacks, they have their own stack\n"
- "; Because this is a BDOS user program, the interrupts are called from the BDOS interrupt handlers\n"
- "; Therefore, it should return to that interrupt handler and not use reti\n"
- "\n"
- "Int:\n"
- "\n"
- " load32 0x7BFFFF r13 ; initialize user int stack address\n"
- " load32 0 r14 ; initialize base pointer address\n"
- " addr2reg Return_Interrupt r1 ; get address of return function\n"
- " or r0 r1 r15 ; copy return addr to r15\n"
- " jump interrupt ; jump to interrupt handler of C program\n"
- " ; should return to the address we just put on the stack\n"
- " halt ; should not get here\n"
- "\n"
- "\n"
- "; Function that is called after any interrupt handler from C has returned\n"
- "; Rreturns to BDOS interrupt handler\n"
- "Return_Interrupt:\n"
- "\n"
- " ; RETURN\n"
- " pop r1\n"
- " jumpr 3 r1\n"
- "\n"
- " halt ; should not get here\n"
- );
- }
- else
- {
- printf2(
- ".code\n"
- "; END OF COMPILED C CODE\n"
- "\n"
- "; Interrupt handlers\n"
- "; Has some administration before jumping to Label_int[ID]\n"
- "; To prevent interfering with other stacks, they have their own stack\n"
- "; Also, all registers have to be backed up and restored to hardware stack\n"
- "; A return function has to be put on the stack as wel that the C code interrupt handler\n"
- "; will jump to when it is done\n"
- "\n"
- "Int:\n"
- " push r1\n"
- " push r2\n"
- " push r3\n"
- " push r4\n"
- " push r5\n"
- " push r6\n"
- " push r7\n"
- " push r8\n"
- " push r9\n"
- " push r10\n"
- " push r11\n"
- " push r12\n"
- " push r13\n"
- " push r14\n"
- " push r15\n"
- "\n"
- " load32 0x7FFFFF r13 ; initialize (BDOS) int stack address\n"
- " load32 0 r14 ; initialize base pointer address\n"
- " addr2reg Return_Interrupt r1 ; get address of return function\n"
- " or r0 r1 r15 ; copy return addr to r15\n"
- " jump interrupt ; jump to interrupt handler of C program\n"
- " ; should return to the address we just put on the stack\n"
- " halt ; should not get here\n"
- "\n"
- "\n"
- "; Function that is called after any interrupt handler from C has returned\n"
- "; Restores all registers and issues RETI instruction to continue from original code\n"
- "Return_Interrupt:\n"
- " pop r15\n"
- " pop r14\n"
- " pop r13\n"
- " pop r12\n"
- " pop r11\n"
- " pop r10\n"
- " pop r9\n"
- " pop r8\n"
- " pop r7\n"
- " pop r6\n"
- " pop r5\n"
- " pop r4\n"
- " pop r3\n"
- " pop r2\n"
- " pop r1\n"
- "\n"
- " reti ; return from interrrupt\n"
- "\n"
- " halt ; should not get here\n");
- }
- if (compileOS)
- {
- printf2(
- ".code\n"
- "\n; Syscall handler for OS\n"
- "; Because this is not called during an interrupt, we use a different stack\n"
- "; located at the end of BDOS heap\n"
- "\n"
- "Syscall:\n"
- " load32 0x3FFFFF r13 ; initialize syscall stack address\n"
- " load32 0 r14 ; initialize base pointer address\n"
- " addr2reg Return_Syscall r1 ; get address of return function\n"
- " or r0 r1 r15 ; copy return addr to r15\n"
- " jump syscall ; jump to syscall handler of C program\n"
- " ; should return to the address we just put on the stack\n"
- " halt ; should not get here\n"
- "\n"
- "Return_Syscall:\n"
- " pop r1\n"
- " jumpr 3 r1\n"
- "\n"
- " halt ; should not get here\n"
- );
- }
-
- }
|