1
0

backend.c 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525
  1. /*
  2. Copyright (c) 2021-2022, b4rt-dev
  3. Copyright (c) 2012-2015, Alexey Frunze
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7. 1. Redistributions of source code must retain the above copyright notice, this
  8. list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright notice,
  10. this list of conditions and the following disclaimer in the documentation
  11. and/or other materials provided with the distribution.
  12. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  13. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  16. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. /*****************************************************************************/
  24. /* */
  25. /* BCC (B32P C Compiler) */
  26. /* */
  27. /* C compiler for B32P */
  28. /* Modified version intended to run on FPGC */
  29. /* */
  30. /* Based on SmallerC: */
  31. /* A simple and small single-pass C compiler */
  32. /* */
  33. /* B32P code generator */
  34. /* Modified from the MIPS code generator */
  35. /* */
  36. /*****************************************************************************/
  37. // NOTE: Pretty inefficient generated code, because of the direct-ish translation from MIPS to B32P
  38. /* MAIN TODOs:
  39. - Improve using new B32P instructions
  40. - Remove all MIPS code leftovers
  41. - Do optimizations (like size stuff)
  42. */
  43. /* WORDSIZE issue tags (to look into if I will ever try to fix it)
  44. //WORDSIZE
  45. //CurFxnLocalOfs (gcc.c)
  46. */
  47. void GenInit(void)
  48. {
  49. // initialization of target-specific code generator
  50. // Assembler should move all .data and .rdata parts away from the code
  51. SizeOfWord = 4;
  52. OutputFormat = FormatSegmented;
  53. CodeHeaderFooter[0] = ".code";
  54. DataHeaderFooter[0] = ".data";
  55. RoDataHeaderFooter[0] = ".rdata";
  56. BssHeaderFooter[0] = ".bss"; // object data
  57. UseLeadingUnderscores = 0;
  58. }
  59. void GenInitFinalize(void)
  60. {
  61. // finalization of initialization of target-specific code generator
  62. // Put all C specific wrapper code (start) here
  63. if (compileUserBDOS)
  64. {
  65. printf2(
  66. ".code\n"
  67. "Main:\n"
  68. " load32 0 r14\n"
  69. " load32 0x73FFFF r13\n"
  70. " addr2reg Return_BDOS r1\n"
  71. " or r0 r1 r15\n"
  72. " jump main\n"
  73. " halt\n"
  74. "Return_BDOS:\n"
  75. " load32 0x100300 r1\n"
  76. " write 0 r1 r0\n"
  77. " pop r1\n"
  78. " jumpr 3 r1\n"
  79. " halt\n"
  80. );
  81. }
  82. else
  83. {
  84. printf2(
  85. ".code\n"
  86. "Main:\n"
  87. " load32 0 r14\n"
  88. " load32 0x77FFFF r13\n"
  89. " addr2reg Return_UART r1\n"
  90. " or r0 r1 r15\n"
  91. " jump main\n"
  92. " halt\n"
  93. "Return_UART:\n"
  94. " load32 0xC02723 r1\n"
  95. " write 0 r1 r2\n"
  96. " halt\n"
  97. );
  98. }
  99. }
  100. void GenStartCommentLine(void)
  101. {
  102. printf2(" ; ");
  103. }
  104. // No alignment needed on B32P
  105. void GenWordAlignment(word bss)
  106. {
  107. (void)bss;
  108. if (doAnnotations)
  109. {
  110. printf2("; .align 2\n");
  111. }
  112. }
  113. void GenLabel(char* Label, word Static)
  114. {
  115. {
  116. if (!Static && GenExterns && doAnnotations)
  117. {
  118. printf2("; .globl ");
  119. printf2(Label);
  120. printf2("\n");
  121. }
  122. printf2(Label);
  123. printf2(":\n");
  124. }
  125. }
  126. void GenPrintLabel(char* Label)
  127. {
  128. {
  129. if (isdigit(*Label))
  130. {
  131. printf2("Label_");
  132. printf2(Label);
  133. }
  134. else
  135. {
  136. printf2(Label);
  137. }
  138. }
  139. }
  140. void GenNumLabel(word Label)
  141. {
  142. printf2("Label_");
  143. printd2(Label);
  144. printf2(":\n");
  145. }
  146. void GenPrintNumLabel(word label)
  147. {
  148. printf2("Label_");
  149. printd2(label);
  150. }
  151. void GenZeroData(unsigned Size, word bss)
  152. {
  153. (void)bss;
  154. if (doAnnotations)
  155. {
  156. printf2("; .space ");
  157. printd2(truncUint(Size));
  158. printf2("\n");
  159. }
  160. // B32P implementation of .space:
  161. if (Size > 0)
  162. {
  163. word i;
  164. for (i = 0; i < Size; i++)
  165. {
  166. if (MATH_modU(i, 100) == 0)
  167. {
  168. if (i == 0)
  169. {
  170. printf2(".dw");
  171. }
  172. else
  173. {
  174. printf2("\n.dw");
  175. }
  176. }
  177. printf2(" 0");
  178. }
  179. printf2("\n");
  180. }
  181. }
  182. void GenIntData(word Size, word Val)
  183. {
  184. Val = truncInt(Val);
  185. // Print multiple times, since the compiler does not know yet B32P is word addressable
  186. if (Size == 1)
  187. {
  188. printf2(" .dw ");
  189. printd2(Val);
  190. printf2("\n");
  191. }
  192. else if (Size == 2)
  193. {
  194. printf2(" .dw ");
  195. printd2(Val);
  196. printf2(" ");
  197. printd2(Val);
  198. printf2("\n");
  199. }
  200. else if (Size == 4)
  201. {
  202. printf2(" .dw ");
  203. printd2(Val);
  204. printf2(" ");
  205. printd2(Val);
  206. printf2(" ");
  207. printd2(Val);
  208. printf2(" ");
  209. printd2(Val);
  210. printf2("\n");
  211. }
  212. }
  213. void GenStartAsciiString(void)
  214. {
  215. printf2(".dw "); // String should be converted into 1 character per word
  216. }
  217. void GenAddrData(word Size, char* Label, word ofs)
  218. {
  219. ofs = truncInt(ofs);
  220. word i;
  221. for (i = 0; i < 4; i++) // label is 4 "bytes", hotfix since the compiler does not know yet B32P is word addressable
  222. {
  223. printf2(".dl ");
  224. GenPrintLabel(Label);
  225. // Still not sure if this ever gets called (and probably will not work until an Assembler update)
  226. if (ofs)
  227. {
  228. printf2(" +");
  229. printd2(ofs);
  230. }
  231. puts2("");
  232. }
  233. }
  234. word GenFxnSizeNeeded(void)
  235. {
  236. return 0;
  237. }
  238. void GenRecordFxnSize(char* startLabelName, word endLabelNo)
  239. {
  240. (void)startLabelName;
  241. (void)endLabelNo;
  242. }
  243. #define B32PInstrHalt 0x30
  244. #define B32PInstrRead 0x31
  245. #define B32PInstrWrite 0x32
  246. #define B32PInstrIntID 0x33
  247. #define B32PInstrPush 0x34
  248. #define B32PInstrPop 0x35
  249. #define B32PInstrJump 0x36
  250. #define B32PInstrJumpo 0x37
  251. #define B32PInstrJumpr 0x38
  252. #define B32PInstrJumpro 0x39
  253. #define B32PInstrBEQ 0x3A
  254. #define B32PInstrBGT 0x3B
  255. #define B32PInstrBGTS 0x3C
  256. #define B32PInstrBGE 0x3D
  257. #define B32PInstrBGES 0x3E
  258. #define B32PInstrBNE 0x3F
  259. #define B32PInstrBLT 0x40
  260. #define B32PInstrBLTS 0x41
  261. #define B32PInstrBLE 0x42
  262. #define B32PInstrBLES 0x43
  263. #define B32PInstrSavPC 0x44
  264. #define B32PInstrReti 0x45
  265. #define B32PInstrOR 0x46
  266. #define B32PInstrAND 0x47
  267. #define B32PInstrXOR 0x48
  268. #define B32PInstrADD 0x49
  269. #define B32PInstrSUB 0x4A
  270. #define B32PInstrSHIFTL 0x4B
  271. #define B32PInstrSHIFTR 0x4C
  272. #define B32PInstrNOT 0x4D
  273. #define B32PInstrMULTS 0x4E
  274. #define B32PInstrMULTU 0x4F
  275. #define B32PInstrSLT 0x50
  276. #define B32PInstrSLTU 0x51
  277. #define B32PInstrLoad 0x52
  278. #define B32PInstrLoadHi 0x53
  279. #define B32PInstrAddr2reg 0x54
  280. #define B32PInstrLoad32 0x55
  281. #define B32PInstrNOP 0x56
  282. #define B32PInstrSHIFTRS 0x57
  283. void GenPrintInstr(word instr, word val)
  284. {
  285. char* p = "";
  286. (void)val;
  287. switch (instr)
  288. {
  289. case B32PInstrHalt : p = "halt"; break;
  290. case B32PInstrRead : p = "read"; break;
  291. case B32PInstrWrite : p = "write"; break;
  292. case B32PInstrIntID : p = "readintid"; break;
  293. case B32PInstrPush : p = "push"; break;
  294. case B32PInstrPop : p = "pop"; break;
  295. case B32PInstrJump : p = "jump"; break;
  296. case B32PInstrJumpo : p = "jumpo"; break;
  297. case B32PInstrJumpr : p = "jumpr"; break;
  298. case B32PInstrJumpro : p = "jumpro"; break;
  299. case B32PInstrBEQ : p = "beq"; break;
  300. case B32PInstrBGT : p = "bgts"; break; // HACK: Default signed comparison, because of MIPS
  301. case B32PInstrBGTS : p = "bgts"; break;
  302. case B32PInstrBGE : p = "bges"; break; // HACK: Default signed comparison, because of MIPS
  303. case B32PInstrBGES : p = "bges"; break;
  304. case B32PInstrBNE : p = "bne"; break;
  305. case B32PInstrBLT : p = "blts"; break; // HACK: Default signed comparison, because of MIPS
  306. case B32PInstrBLTS : p = "blts"; break;
  307. case B32PInstrBLE : p = "bles"; break; // HACK: Default signed comparison, because of MIPS
  308. case B32PInstrBLES : p = "bles"; break;
  309. case B32PInstrSavPC : p = "savpc"; break;
  310. case B32PInstrReti : p = "reti"; break;
  311. case B32PInstrOR : p = "or"; break;
  312. case B32PInstrAND : p = "and"; break;
  313. case B32PInstrXOR : p = "xor"; break;
  314. case B32PInstrADD : p = "add"; break;
  315. case B32PInstrSUB : p = "sub"; break;
  316. case B32PInstrSHIFTL : p = "shiftl"; break;
  317. case B32PInstrSHIFTR : p = "shiftr"; break;
  318. case B32PInstrSHIFTRS : p = "shiftrs"; break;
  319. case B32PInstrNOT : p = "not"; break;
  320. case B32PInstrMULTS : p = "mults"; break;
  321. case B32PInstrMULTU : p = "multu"; break;
  322. case B32PInstrSLT : p = "slt"; break;
  323. case B32PInstrSLTU : p = "sltu"; break;
  324. case B32PInstrLoad : p = "load32"; break;
  325. case B32PInstrLoadHi : p = "loadhi"; break;
  326. case B32PInstrAddr2reg : p = "addr2reg"; break;
  327. case B32PInstrLoad32 : p = "load32"; break;
  328. }
  329. printf2(" ");
  330. printf2(p);
  331. printf2(" ");
  332. }
  333. #define B32POpRegZero 0x00 //0 0
  334. #define B32POpRegAt 0x01 //1 at
  335. #define B32POpRegV0 0x02 //2 ret0
  336. #define B32POpRegV1 0x03 //3 ret1
  337. #define B32POpRegA0 0x04 //4 arg0
  338. #define B32POpRegA1 0x05 //5 arg1
  339. #define B32POpRegA2 0x06 //6 arg2
  340. #define B32POpRegA3 0x07 //7 arg3
  341. #define B32POpRegT0 0x08 //8 gp0
  342. #define B32POpRegT1 0x09 //9 gp1
  343. #define B32POpRegT2 0x0A //10 gp2
  344. #define B32POpRegT8 0x0B //11 tempa
  345. #define B32POpRegT9 0x0C //12 tempb
  346. #define B32POpRegSp 0x0D //13 sp
  347. #define B32POpRegFp 0x0E //14 fp
  348. #define B32POpRegRa 0x0F //15 retaddr
  349. #define B32POpIndRegZero 0x20
  350. #define B32POpIndRegAt 0x21
  351. #define B32POpIndRegV0 0x22
  352. #define B32POpIndRegV1 0x23
  353. #define B32POpIndRegA0 0x24
  354. #define B32POpIndRegA1 0x25
  355. #define B32POpIndRegA2 0x26
  356. #define B32POpIndRegA3 0x27
  357. #define B32POpIndRegT0 0x28
  358. #define B32POpIndRegT1 0x29
  359. #define B32POpIndRegSp 0x2D
  360. #define B32POpIndRegFp 0x2E
  361. #define B32POpIndRegRa 0x2F
  362. #define B32POpConst 0x80
  363. #define B32POpLabel 0x81
  364. #define B32POpNumLabel 0x82
  365. #define B32POpLabelLo 0x83
  366. #define B32POpIndLocal B32POpIndRegFp
  367. #define MAX_TEMP_REGS 3 // this many temp registers used beginning with T0 to hold subexpression results
  368. #define TEMP_REG_A B32POpRegT8 // two temporary registers used for momentary operations, similarly to the AT register
  369. #define TEMP_REG_B B32POpRegT9
  370. void GenPrintOperand(word op, word val)
  371. {
  372. if (op >= B32POpRegZero && op <= B32POpRegRa)
  373. {
  374. printf2("r");
  375. printd2(op);
  376. }
  377. else if (op >= B32POpIndRegZero && op <= B32POpIndRegRa)
  378. {
  379. printd2(truncInt(val));
  380. printf2(" r");
  381. printd2(op - B32POpIndRegZero);
  382. }
  383. else
  384. {
  385. switch (op)
  386. {
  387. case B32POpConst: printd2(truncInt(val)); break;
  388. case B32POpLabelLo:
  389. // should not be called anymore
  390. printf("LABELLO WHOOPS!\n");
  391. /*
  392. printf2("%%lo(");
  393. GenPrintLabel(IdentTable + val);
  394. printf2(")(r1)");
  395. */
  396. break;
  397. case B32POpLabel: GenPrintLabel(IdentTable + val); break;
  398. case B32POpNumLabel: GenPrintNumLabel(val); break;
  399. default:
  400. errorInternal(100);
  401. break;
  402. }
  403. }
  404. }
  405. void GenPrintOperandSeparator(void)
  406. {
  407. printf2(" ");
  408. }
  409. void GenPrintNewLine(void)
  410. {
  411. puts2("");
  412. }
  413. void GenPrintInstr1Operand(word instr, word instrval, word operand, word operandval)
  414. {
  415. GenPrintInstr(instr, instrval);
  416. GenPrintOperand(operand, operandval);
  417. GenPrintNewLine();
  418. }
  419. void GenPrintInstr2Operands(word instr, word instrval, word operand1, word operand1val, word operand2, word operand2val)
  420. {
  421. // TODO: figure out if this ever happens because ADD and SUB need 3 args
  422. if (operand2 == B32POpConst && operand2val == 0 &&
  423. (instr == B32PInstrADD || instr == B32PInstrSUB))
  424. return;
  425. GenPrintInstr(instr, instrval);
  426. GenPrintOperand(operand1, operand1val);
  427. GenPrintOperandSeparator();
  428. GenPrintOperand(operand2, operand2val);
  429. GenPrintNewLine();
  430. }
  431. void GenPrintInstr3Operands(word instr, word instrval,
  432. word operand1, word operand1val,
  433. word operand2, word operand2val,
  434. word operand3, word operand3val)
  435. {
  436. if (operand3 == B32POpConst && operand3val == 0 &&
  437. (instr == B32PInstrADD || instr == B32PInstrSUB) &&
  438. operand1 == operand2)
  439. return;
  440. // If constant is negative, swap B32PInstrADD for B32PInstrSUB and vice versa
  441. // and flip sign of constant
  442. if (operand2 == B32POpConst && operand2val < 0)
  443. {
  444. if (instr == B32PInstrADD)
  445. {
  446. instr = B32PInstrSUB;
  447. operand2val = -operand2val;
  448. }
  449. else if (instr == B32PInstrSUB)
  450. {
  451. instr = B32PInstrADD;
  452. operand2val = -operand2val;
  453. }
  454. }
  455. GenPrintInstr(instr, instrval);
  456. GenPrintOperand(operand1, operand1val);
  457. GenPrintOperandSeparator();
  458. GenPrintOperand(operand2, operand2val);
  459. GenPrintOperandSeparator();
  460. GenPrintOperand(operand3, operand3val);
  461. GenPrintNewLine();
  462. }
  463. // Currently we do not want to "extend" any reg
  464. void GenExtendRegIfNeeded(word reg, word opSz)
  465. {
  466. }
  467. void GenJumpUncond(word label)
  468. {
  469. GenPrintInstr1Operand(B32PInstrJump, 0,
  470. B32POpNumLabel, label);
  471. }
  472. extern word GenWreg; // GenWreg is defined below
  473. void GenJumpIfEqual(word val, word label)
  474. {
  475. GenPrintInstr2Operands(B32PInstrLoad, 0,
  476. B32POpConst, val,
  477. TEMP_REG_B, 0);
  478. /*
  479. GenPrintInstr3Operands(MipsInstrBEQ, 0,
  480. GenWreg, 0,
  481. TEMP_REG_B, 0,
  482. B32POpNumLabel, label);
  483. */
  484. GenPrintInstr3Operands(B32PInstrBNE, 0,
  485. GenWreg, 0,
  486. TEMP_REG_B, 0,
  487. B32POpConst, 2);
  488. GenPrintInstr1Operand(B32PInstrJump, 0,
  489. B32POpNumLabel, label);
  490. }
  491. void GenJumpIfZero(word label)
  492. {
  493. if (doAnnotations)
  494. {
  495. printf2(" ; JumpIfZero\n");
  496. }
  497. /* if Wreg == 0, jump to label
  498. GenPrintInstr3Operands(MipsInstrBEQ, 0,
  499. GenWreg, 0,
  500. B32POpRegZero, 0,
  501. B32POpNumLabel, label);
  502. */
  503. GenPrintInstr3Operands(B32PInstrBNE, 0,
  504. GenWreg, 0,
  505. B32POpRegZero, 0,
  506. B32POpConst, 2);
  507. GenPrintInstr1Operand(B32PInstrJump, 0,
  508. B32POpNumLabel, label);
  509. }
  510. void GenJumpIfNotZero(word label)
  511. {
  512. if (doAnnotations)
  513. {
  514. printf2(" ; JumpIfNotZero\n");
  515. }
  516. /* if Wreg != 0, jump to label
  517. GenPrintInstr3Operands(MipsInstrBNE, 0,
  518. GenWreg, 0,
  519. B32POpRegZero, 0,
  520. B32POpNumLabel, label);
  521. */
  522. GenPrintInstr3Operands(B32PInstrBEQ, 0,
  523. GenWreg, 0,
  524. B32POpRegZero, 0,
  525. B32POpConst, 2);
  526. GenPrintInstr1Operand(B32PInstrJump, 0,
  527. B32POpNumLabel, label);
  528. }
  529. word GenPrologPos = 0;
  530. word GenLeaf;
  531. void GenWriteFrameSize(void) //WORDSIZE
  532. {
  533. unsigned size = 8/*RA + FP*/ - CurFxnMinLocalOfs;
  534. //printf2(" subu r13, r13, %10u\n", size); // 10 chars are enough for 32-bit unsigned ints
  535. printf2(" sub r13 "); // r13 = r13 - size
  536. printd2(size); // r13 = r13 - size
  537. printf2(" r13\n"); // r13 = r13 - size
  538. //printf2(" sw r14, %10u r13\n", size - 8);
  539. printf2(" write "); // write r14 to memory[r13+(size-8)]
  540. printd2(size - 8); // write r14 to memory[r13+(size-8)]
  541. printf2(" r13 r14\n"); // write r14 to memory[r13+(size-8)]
  542. //printf2(" addu r14, r13, %10u\n", size - 8);
  543. printf2(" add r13 "); // r14 = r13 + (size-8)
  544. printd2(size - 8); // r14 = r13 + (size-8)
  545. printf2(" r14\n"); // r14 = r13 + (size-8)
  546. //printf2(" %csw r15, 4 r14\n", GenLeaf ? ';' : ' ');
  547. if (GenLeaf)
  548. {
  549. printf2(" ");
  550. }
  551. else
  552. {
  553. printf2(" write 4 r14 r15\n"); // write r15 to memory[r14+4]
  554. }
  555. }
  556. void GenUpdateFrameSize(void)
  557. {
  558. word curpos = 0;
  559. curpos = fgetpos(OutFile);
  560. //printf("cur: ");
  561. //printd(curpos);
  562. //printf("\ngoto: ");
  563. //printd(GenPrologPos);
  564. //printf("\n");
  565. fsetpos(OutFile, GenPrologPos);
  566. GenWriteFrameSize();
  567. //printf("back to cur: ");
  568. //printd(curpos);
  569. //printf("\n");
  570. //printf("\n");
  571. fsetpos(OutFile, curpos);
  572. }
  573. void GenFxnProlog(void)
  574. {
  575. if (CurFxnParamCntMin && CurFxnParamCntMax)
  576. {
  577. word i, cnt = CurFxnParamCntMax;
  578. if (cnt > 4)
  579. cnt = 4; //WORDSIZE?
  580. // TBD!!! for structure passing use the cumulative parameter size
  581. // instead of the number of parameters. Currently this bug is masked
  582. // by the subroutine that pushes structures on the stack (it copies
  583. // all words except the first to the stack). But passing structures
  584. // in registers from assembly code won't always work.
  585. for (i = 0; i < cnt; i++)
  586. GenPrintInstr2Operands(B32PInstrWrite, 0,
  587. B32POpIndRegSp, 4 * i, //WORDSIZE
  588. B32POpRegA0 + i, 0);
  589. }
  590. GenLeaf = 1; // will be reset to 0 if a call is generated
  591. GenPrologPos = fgetpos(OutFile);
  592. // write an empty space for the frame size
  593. word x;
  594. for(x = 0; x < 100; x++)
  595. {
  596. printf2(" ");
  597. }
  598. printf2("\n");
  599. }
  600. void GenGrowStack(word size) //WORDSIZE
  601. {
  602. if (!size)
  603. return;
  604. if (size > 0)
  605. {
  606. GenPrintInstr3Operands(B32PInstrSUB, 0,
  607. B32POpRegSp, 0,
  608. B32POpConst, size,
  609. B32POpRegSp, 0);
  610. }
  611. else
  612. {
  613. GenPrintInstr3Operands(B32PInstrADD, 0,
  614. B32POpRegSp, 0,
  615. B32POpConst, -size,
  616. B32POpRegSp, 0);
  617. }
  618. }
  619. void GenFxnEpilog(void)
  620. {
  621. //printf("DONE with function\n");
  622. GenUpdateFrameSize();
  623. //printf("BackToEnd\n");
  624. if (!GenLeaf)
  625. GenPrintInstr2Operands(B32PInstrRead, 0,
  626. B32POpIndRegFp, 4, //WORDSIZE
  627. B32POpRegRa, 0);
  628. GenPrintInstr2Operands(B32PInstrRead, 0,
  629. B32POpIndRegFp, 0,
  630. B32POpRegFp, 0);
  631. GenPrintInstr3Operands(B32PInstrADD, 0,
  632. B32POpRegSp, 0,
  633. B32POpConst, 8/*RA + FP*/ - CurFxnMinLocalOfs, //WORDSIZE
  634. B32POpRegSp, 0);
  635. GenPrintInstr2Operands(B32PInstrJumpr, 0,
  636. B32POpConst, 0,
  637. B32POpRegRa, 0);
  638. }
  639. word GenMaxLocalsSize(void)
  640. {
  641. return 0x7FFFFFFF;
  642. }
  643. word GenGetBinaryOperatorInstr(word tok)
  644. {
  645. switch (tok)
  646. {
  647. case tokPostAdd:
  648. case tokAssignAdd:
  649. case '+':
  650. return B32PInstrADD;
  651. case tokPostSub:
  652. case tokAssignSub:
  653. case '-':
  654. return B32PInstrSUB;
  655. case '&':
  656. case tokAssignAnd:
  657. return B32PInstrAND;
  658. case '^':
  659. case tokAssignXor:
  660. return B32PInstrXOR;
  661. case '|':
  662. case tokAssignOr:
  663. return B32PInstrOR;
  664. case '<':
  665. case '>':
  666. case tokLEQ:
  667. case tokGEQ:
  668. case tokEQ:
  669. case tokNEQ:
  670. case tokULess:
  671. case tokUGreater:
  672. case tokULEQ:
  673. case tokUGEQ:
  674. return B32PInstrNOP;
  675. case '*':
  676. case tokAssignMul:
  677. return B32PInstrMULTS;
  678. case '/':
  679. case '%':
  680. case tokAssignDiv:
  681. case tokAssignMod:
  682. printf("DIVISION/MOD is not supported!\n");
  683. return B32PInstrHalt;
  684. case tokUDiv:
  685. case tokUMod:
  686. case tokAssignUDiv:
  687. case tokAssignUMod:
  688. printf("DIVISION/MOD is not supported!\n");
  689. return B32PInstrHalt;
  690. case tokLShift:
  691. case tokAssignLSh:
  692. return B32PInstrSHIFTL;
  693. case tokRShift:
  694. case tokAssignRSh:
  695. return B32PInstrSHIFTRS;
  696. case tokURShift:
  697. case tokAssignURSh:
  698. return B32PInstrSHIFTR;
  699. default:
  700. //error("Error: Invalid operator\n");
  701. errorInternal(101);
  702. return 0;
  703. }
  704. }
  705. void GenReadIdent(word regDst, word opSz, word label)
  706. {
  707. GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
  708. B32POpLabel, label,
  709. B32POpRegAt, 0);
  710. GenPrintInstr3Operands(B32PInstrRead, 0,
  711. B32POpConst, 0,
  712. B32POpRegAt, 0,
  713. regDst, 0);
  714. }
  715. void GenReadLocal(word regDst, word opSz, word ofs)
  716. {
  717. word instr = B32PInstrRead;
  718. GenPrintInstr2Operands(instr, 0,
  719. B32POpIndRegFp, ofs,
  720. regDst, 0);
  721. }
  722. void GenReadIndirect(word regDst, word regSrc, word opSz)
  723. {
  724. word instr = B32PInstrRead;
  725. GenPrintInstr2Operands(instr, 0,
  726. regSrc + B32POpIndRegZero, 0,
  727. regDst, 0);
  728. }
  729. void GenWriteIdent(word regSrc, word opSz, word label)
  730. {
  731. GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
  732. B32POpLabel, label,
  733. B32POpRegAt, 0);
  734. GenPrintInstr3Operands(B32PInstrWrite, 0,
  735. B32POpConst, 0,
  736. B32POpRegAt, 0,
  737. regSrc, 0);
  738. }
  739. void GenWriteLocal(word regSrc, word opSz, word ofs)
  740. {
  741. word instr = B32PInstrWrite;
  742. GenPrintInstr2Operands(instr, 0,
  743. B32POpIndRegFp, ofs,
  744. regSrc, 0);
  745. }
  746. void GenWriteIndirect(word regDst, word regSrc, word opSz)
  747. {
  748. word instr = B32PInstrWrite;
  749. GenPrintInstr2Operands(instr, 0,
  750. regDst + B32POpIndRegZero, 0,
  751. regSrc, 0);
  752. }
  753. void GenIncDecIdent(word regDst, word opSz, word label, word tok)
  754. {
  755. word instr = B32PInstrADD;
  756. if (tok != tokInc)
  757. instr = B32PInstrSUB;
  758. GenReadIdent(regDst, opSz, label);
  759. GenPrintInstr3Operands(instr, 0,
  760. regDst, 0,
  761. B32POpConst, 1,
  762. regDst, 0);
  763. GenWriteIdent(regDst, opSz, label);
  764. GenExtendRegIfNeeded(regDst, opSz);
  765. }
  766. void GenIncDecLocal(word regDst, word opSz, word ofs, word tok)
  767. {
  768. word instr = B32PInstrADD;
  769. if (tok != tokInc)
  770. instr = B32PInstrSUB;
  771. GenReadLocal(regDst, opSz, ofs);
  772. GenPrintInstr3Operands(instr, 0,
  773. regDst, 0,
  774. B32POpConst, 1,
  775. regDst, 0);
  776. GenWriteLocal(regDst, opSz, ofs);
  777. GenExtendRegIfNeeded(regDst, opSz);
  778. }
  779. void GenIncDecIndirect(word regDst, word regSrc, word opSz, word tok)
  780. {
  781. word instr = B32PInstrADD;
  782. if (tok != tokInc)
  783. instr = B32PInstrSUB;
  784. GenReadIndirect(regDst, regSrc, opSz);
  785. GenPrintInstr3Operands(instr, 0,
  786. regDst, 0,
  787. B32POpConst, 1,
  788. regDst, 0);
  789. GenWriteIndirect(regSrc, regDst, opSz);
  790. GenExtendRegIfNeeded(regDst, opSz);
  791. }
  792. void GenPostIncDecIdent(word regDst, word opSz, word label, word tok)
  793. {
  794. word instr = B32PInstrADD;
  795. if (tok != tokPostInc)
  796. instr = B32PInstrSUB;
  797. GenReadIdent(regDst, opSz, label);
  798. GenPrintInstr3Operands(instr, 0,
  799. regDst, 0,
  800. B32POpConst, 1,
  801. regDst, 0);
  802. GenWriteIdent(regDst, opSz, label);
  803. GenPrintInstr3Operands(instr, 0,
  804. regDst, 0,
  805. B32POpConst, -1,
  806. regDst, 0);
  807. GenExtendRegIfNeeded(regDst, opSz);
  808. }
  809. void GenPostIncDecLocal(word regDst, word opSz, word ofs, word tok)
  810. {
  811. word instr = B32PInstrADD;
  812. if (tok != tokPostInc)
  813. instr = B32PInstrSUB;
  814. GenReadLocal(regDst, opSz, ofs);
  815. GenPrintInstr3Operands(instr, 0,
  816. regDst, 0,
  817. B32POpConst, 1,
  818. regDst, 0);
  819. GenWriteLocal(regDst, opSz, ofs);
  820. GenPrintInstr3Operands(instr, 0,
  821. regDst, 0,
  822. B32POpConst, -1,
  823. regDst, 0);
  824. GenExtendRegIfNeeded(regDst, opSz);
  825. }
  826. void GenPostIncDecIndirect(word regDst, word regSrc, word opSz, word tok)
  827. {
  828. word instr = B32PInstrADD;
  829. if (tok != tokPostInc)
  830. instr = B32PInstrSUB;
  831. GenReadIndirect(regDst, regSrc, opSz);
  832. GenPrintInstr3Operands(instr, 0,
  833. regDst, 0,
  834. B32POpConst, 1,
  835. regDst, 0);
  836. GenWriteIndirect(regSrc, regDst, opSz);
  837. GenPrintInstr3Operands(instr, 0,
  838. regDst, 0,
  839. B32POpConst, -1,
  840. regDst, 0);
  841. GenExtendRegIfNeeded(regDst, opSz);
  842. }
  843. word CanUseTempRegs;
  844. word TempsUsed;
  845. word GenWreg = B32POpRegV0; // current working register (V0 or Tn or An)
  846. word GenLreg, GenRreg; // left operand register and right operand register after GenPopReg()
  847. /*
  848. General idea behind GenWreg, GenLreg, GenRreg:
  849. - In expressions w/o function calls:
  850. Subexpressions are evaluated in V0, T0, T1, ..., T<MAX_TEMP_REGS-1>. If those registers
  851. aren't enough, the stack is used additionally.
  852. The expression result ends up in V0, which is handy for returning from
  853. functions.
  854. In the process, GenWreg is the current working register and is one of: V0, T0, T1, ... .
  855. All unary operators are evaluated in the current working register.
  856. GenPushReg() and GenPopReg() advance GenWreg as needed when handling binary operators.
  857. GenPopReg() sets GenWreg, GenLreg and GenRreg. GenLreg and GenRreg are the registers
  858. where the left and right operands of a binary operator are.
  859. When the exression runs out of the temporary registers, the stack is used. While it is being
  860. used, GenWreg remains equal to the last temporary register, and GenPopReg() sets GenLreg = TEMP_REG_A.
  861. Hence, after GenPopReg() the operands of the binary operator are always in registers and can be
  862. directly manipulated with.
  863. Following GenPopReg(), binary operator evaluation must take the left and right operands from
  864. GenLreg and GenRreg and write the evaluated result into GenWreg. Care must be taken as GenWreg
  865. will be the same as either GenLreg (when the popped operand comes from T0-T<MAX_TEMP_REGS-1>)
  866. or GenRreg (when the popped operand comes from the stack in TEMP_REG_A).
  867. - In expressions with function calls:
  868. GenWreg is always V0 in subexpressions that aren't function parameters. These subexpressions
  869. get automatically pushed onto the stack as necessary.
  870. GenWreg is always V0 in expressions, where return values from function calls are used as parameters
  871. into other called functions. IOW, this is the case when the function call depth is greater than 1.
  872. Subexpressions in such expressions get automatically pushed onto the stack as necessary.
  873. GenWreg is A0-A3 in subexpressions that are function parameters when the function call depth is 1.
  874. Basically, while a function parameter is evaluated, it's evaluated in the register from where
  875. the called function will take it. This avoids some of unnecessary register copies and stack
  876. manipulations in the most simple and very common cases of function calls.
  877. */
  878. void GenWregInc(word inc)
  879. {
  880. if (inc > 0)
  881. {
  882. // Advance the current working register to the next available temporary register
  883. if (GenWreg == B32POpRegV0)
  884. GenWreg = B32POpRegT0;
  885. else
  886. GenWreg++;
  887. }
  888. else
  889. {
  890. // Return to the previous current working register
  891. if (GenWreg == B32POpRegT0)
  892. GenWreg = B32POpRegV0;
  893. else
  894. GenWreg--;
  895. }
  896. }
  897. void GenPushReg(void)
  898. {
  899. if (CanUseTempRegs && TempsUsed < MAX_TEMP_REGS)
  900. {
  901. GenWregInc(1);
  902. TempsUsed++;
  903. return;
  904. }
  905. GenPrintInstr3Operands(B32PInstrSUB, 0,
  906. B32POpRegSp, 0,
  907. B32POpConst, 4, //WORDSIZE
  908. B32POpRegSp, 0);
  909. GenPrintInstr2Operands(B32PInstrWrite, 0,
  910. B32POpIndRegSp, 0,
  911. GenWreg, 0);
  912. TempsUsed++;
  913. }
  914. void GenPopReg(void)
  915. {
  916. TempsUsed--;
  917. if (CanUseTempRegs && TempsUsed < MAX_TEMP_REGS)
  918. {
  919. GenRreg = GenWreg;
  920. GenWregInc(-1);
  921. GenLreg = GenWreg;
  922. return;
  923. }
  924. GenPrintInstr2Operands(B32PInstrRead, 0,
  925. B32POpIndRegSp, 0,
  926. TEMP_REG_A, 0);
  927. GenPrintInstr3Operands(B32PInstrADD, 0,
  928. B32POpRegSp, 0,
  929. B32POpConst, 4, //WORDSIZE
  930. B32POpRegSp, 0);
  931. GenLreg = TEMP_REG_A;
  932. GenRreg = GenWreg;
  933. }
  934. #define tokRevIdent 0x100
  935. #define tokRevLocalOfs 0x101
  936. #define tokAssign0 0x102
  937. #define tokNum0 0x103
  938. void GenPrep(word* idx)
  939. {
  940. word tok;
  941. word oldIdxRight, oldIdxLeft, t0, t1;
  942. if (*idx < 0)
  943. //error("GenFuse(): idx < 0\n");
  944. errorInternal(100);
  945. tok = stack[*idx][0];
  946. oldIdxRight = --*idx;
  947. switch (tok)
  948. {
  949. case tokUDiv:
  950. case tokUMod:
  951. case tokAssignUDiv:
  952. case tokAssignUMod:
  953. if (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint)
  954. {
  955. // Change unsigned division to right shift and unsigned modulo to bitwise and
  956. unsigned m = truncUint(stack[oldIdxRight][1]);
  957. if (m && !(m & (m - 1)))
  958. {
  959. if (tok == tokUMod || tok == tokAssignUMod)
  960. {
  961. stack[oldIdxRight][1] = (word)(m - 1);
  962. tok = (tok == tokUMod) ? '&' : tokAssignAnd;
  963. }
  964. else
  965. {
  966. t1 = 0;
  967. while (m >>= 1) t1++;
  968. stack[oldIdxRight][1] = t1;
  969. tok = (tok == tokUDiv) ? tokURShift : tokAssignURSh;
  970. }
  971. stack[oldIdxRight + 1][0] = tok;
  972. }
  973. }
  974. }
  975. switch (tok)
  976. {
  977. case tokNumUint:
  978. stack[oldIdxRight + 1][0] = tokNumInt; // reduce the number of cases since tokNumInt and tokNumUint are handled the same way
  979. // fallthrough
  980. case tokNumInt:
  981. case tokNum0:
  982. case tokIdent:
  983. case tokLocalOfs:
  984. break;
  985. case tokPostAdd:
  986. case tokPostSub:
  987. case '-':
  988. case '/':
  989. case '%':
  990. case tokUDiv:
  991. case tokUMod:
  992. case tokLShift:
  993. case tokRShift:
  994. case tokURShift:
  995. case tokLogAnd:
  996. case tokLogOr:
  997. case tokComma:
  998. GenPrep(idx);
  999. // fallthrough
  1000. case tokShortCirc:
  1001. case tokGoto:
  1002. case tokUnaryStar:
  1003. case tokInc:
  1004. case tokDec:
  1005. case tokPostInc:
  1006. case tokPostDec:
  1007. case '~':
  1008. case tokUnaryPlus:
  1009. case tokUnaryMinus:
  1010. case tok_Bool:
  1011. case tokVoid:
  1012. case tokUChar:
  1013. case tokSChar:
  1014. case tokShort:
  1015. case tokUShort:
  1016. GenPrep(idx);
  1017. break;
  1018. case '=':
  1019. if (oldIdxRight + 1 == sp - 1 &&
  1020. (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint) &&
  1021. truncUint(stack[oldIdxRight][1]) == 0)
  1022. {
  1023. // Special case for assigning 0 while throwing away the expression result value
  1024. // TBD??? ,
  1025. stack[oldIdxRight][0] = tokNum0; // this zero constant will not be loaded into a register
  1026. stack[oldIdxRight + 1][0] = tokAssign0; // change '=' to tokAssign0
  1027. }
  1028. // fallthrough
  1029. case tokAssignAdd:
  1030. case tokAssignSub:
  1031. case tokAssignMul:
  1032. case tokAssignDiv:
  1033. case tokAssignUDiv:
  1034. case tokAssignMod:
  1035. case tokAssignUMod:
  1036. case tokAssignLSh:
  1037. case tokAssignRSh:
  1038. case tokAssignURSh:
  1039. case tokAssignAnd:
  1040. case tokAssignXor:
  1041. case tokAssignOr:
  1042. GenPrep(idx);
  1043. oldIdxLeft = *idx;
  1044. GenPrep(idx);
  1045. // If the left operand is an identifier (with static or auto storage), swap it with the right operand
  1046. // and mark it specially, so it can be used directly
  1047. if ((t0 = stack[oldIdxLeft][0]) == tokIdent || t0 == tokLocalOfs)
  1048. {
  1049. t1 = stack[oldIdxLeft][1];
  1050. memmove(stack[oldIdxLeft], stack[oldIdxLeft + 1], (oldIdxRight - oldIdxLeft) * sizeof(stack[0]));
  1051. stack[oldIdxRight][0] = (t0 == tokIdent) ? tokRevIdent : tokRevLocalOfs;
  1052. stack[oldIdxRight][1] = t1;
  1053. }
  1054. break;
  1055. case '+':
  1056. case '*':
  1057. case '&':
  1058. case '^':
  1059. case '|':
  1060. case tokEQ:
  1061. case tokNEQ:
  1062. case '<':
  1063. case '>':
  1064. case tokLEQ:
  1065. case tokGEQ:
  1066. case tokULess:
  1067. case tokUGreater:
  1068. case tokULEQ:
  1069. case tokUGEQ:
  1070. GenPrep(idx);
  1071. oldIdxLeft = *idx;
  1072. GenPrep(idx);
  1073. // If the right operand isn't a constant, but the left operand is, swap the operands
  1074. // so the constant can become an immediate right operand in the instruction
  1075. t1 = stack[oldIdxRight][0];
  1076. t0 = stack[oldIdxLeft][0];
  1077. if (t1 != tokNumInt && t0 == tokNumInt)
  1078. {
  1079. word xor;
  1080. t1 = stack[oldIdxLeft][1];
  1081. memmove(stack[oldIdxLeft], stack[oldIdxLeft + 1], (oldIdxRight - oldIdxLeft) * sizeof(stack[0]));
  1082. stack[oldIdxRight][0] = t0;
  1083. stack[oldIdxRight][1] = t1;
  1084. switch (tok)
  1085. {
  1086. case '<':
  1087. case '>':
  1088. xor = '<' ^ '>'; break;
  1089. case tokLEQ:
  1090. case tokGEQ:
  1091. xor = tokLEQ ^ tokGEQ; break;
  1092. case tokULess:
  1093. case tokUGreater:
  1094. xor = tokULess ^ tokUGreater; break;
  1095. case tokULEQ:
  1096. case tokUGEQ:
  1097. xor = tokULEQ ^ tokUGEQ; break;
  1098. default:
  1099. xor = 0; break;
  1100. }
  1101. tok ^= xor;
  1102. }
  1103. // Handle a few special cases and transform the instruction
  1104. if (stack[oldIdxRight][0] == tokNumInt)
  1105. {
  1106. unsigned m = truncUint(stack[oldIdxRight][1]);
  1107. switch (tok)
  1108. {
  1109. case '*':
  1110. // Change multiplication to left shift, this helps indexing arrays of ints/pointers/etc
  1111. if (m && !(m & (m - 1)))
  1112. {
  1113. t1 = 0;
  1114. while (m >>= 1) t1++;
  1115. stack[oldIdxRight][1] = t1;
  1116. tok = tokLShift;
  1117. }
  1118. break;
  1119. case tokLEQ:
  1120. // left <= const will later change to left < const+1, but const+1 must be <=0x7FFFFFFF
  1121. if (m == 0x7FFFFFFF)
  1122. {
  1123. // left <= 0x7FFFFFFF is always true, change to the equivalent left >= 0u
  1124. stack[oldIdxRight][1] = 0;
  1125. tok = tokUGEQ;
  1126. }
  1127. break;
  1128. case tokULEQ:
  1129. // left <= const will later change to left < const+1, but const+1 must be <=0xFFFFFFFFu
  1130. if (m == 0xFFFFFFFF)
  1131. {
  1132. // left <= 0xFFFFFFFFu is always true, change to the equivalent left >= 0u
  1133. stack[oldIdxRight][1] = 0;
  1134. tok = tokUGEQ;
  1135. }
  1136. break;
  1137. case '>':
  1138. // left > const will later change to !(left < const+1), but const+1 must be <=0x7FFFFFFF
  1139. if (m == 0x7FFFFFFF)
  1140. {
  1141. // left > 0x7FFFFFFF is always false, change to the equivalent left & 0
  1142. stack[oldIdxRight][1] = 0;
  1143. tok = '&';
  1144. }
  1145. break;
  1146. case tokUGreater:
  1147. // left > const will later change to !(left < const+1), but const+1 must be <=0xFFFFFFFFu
  1148. if (m == 0xFFFFFFFF)
  1149. {
  1150. // left > 0xFFFFFFFFu is always false, change to the equivalent left & 0
  1151. stack[oldIdxRight][1] = 0;
  1152. tok = '&';
  1153. }
  1154. break;
  1155. }
  1156. }
  1157. stack[oldIdxRight + 1][0] = tok;
  1158. break;
  1159. case ')':
  1160. while (stack[*idx][0] != '(')
  1161. {
  1162. GenPrep(idx);
  1163. if (stack[*idx][0] == ',')
  1164. --*idx;
  1165. }
  1166. --*idx;
  1167. break;
  1168. default:
  1169. //error("GenPrep: unexpected token %s\n", GetTokenName(tok));
  1170. errorInternal(101);
  1171. }
  1172. }
  1173. /*
  1174. ; l <[u] 0 // slt[u] w, w, 0 "k"
  1175. l <[u] const // slt[u] w, w, const "m"
  1176. l <[u] r // slt[u] w, l, r "i"
  1177. * if (l < 0) // bgez w, Lskip "f"
  1178. if (l <[u] const) // slt[u] w, w, const; beq w, r0, Lskip "mc"
  1179. if (l <[u] r) // slt[u] w, l, r; beq w, r0, Lskip "ic"
  1180. ; l <=[u] 0 // slt[u] w, w, 1 "l"
  1181. l <=[u] const // slt[u] w, w, const + 1 "n"
  1182. l <=[u] r // slt[u] w, r, l; xor w, w, 1 "js"
  1183. * if (l <= 0) // bgtz w, Lskip "g"
  1184. if (l <=[u] const) // slt[u] w, w, const + 1; beq w, r0, Lskip "nc"
  1185. if (l <=[u] r) // slt[u] w, r, l; bne w, r0, Lskip "jd"
  1186. l >[u] 0 // slt[u] w, r0, w "o"
  1187. l >[u] const // slt[u] w, w, const + 1; xor w, w, 1 "ns"
  1188. l >[u] r // slt[u] w, r, l "j"
  1189. * if (l > 0) // blez w, Lskip "h"
  1190. **if (l >u 0) // beq w, r0, Lskip
  1191. if (l >[u] const) // slt[u] w, w, const + 1; bne w, r0, Lskip "nd"
  1192. if (l >[u] r) // slt[u] w, r, l; beq w, r0, Lskip "jc"
  1193. ; l >=[u] 0 // slt[u] w, w, 0; xor w, w, 1 "ks"
  1194. l >=[u] const // slt[u] w, w, const; xor w, w, 1 "ms"
  1195. l >=[u] r // slt[u] w, l, r; xor w, w, 1 "is"
  1196. * if (l >= 0) // bltz w, Lskip "e"
  1197. if (l >=[u] const) // slt[u] w, w, const; bne w, r0, Lskip "md"
  1198. if (l >=[u] r) // slt[u] w, l, r; bne w, r0, Lskip "id"
  1199. l == 0 // sltu w, w, 1 "q"
  1200. l == const // xor w, w, const; sltu w, w, 1 "tq"
  1201. l == r // xor w, l, r; sltu w, w, 1 "rq"
  1202. if (l == 0) // bne w, r0, Lskip "d"
  1203. if (l == const) // xor w, w, const; bne w, r0, Lskip "td"
  1204. if (l == r) // bne l, r, Lskip "b"
  1205. l != 0 // sltu w, r0, w "p"
  1206. l != const // xor w, w, const; sltu w, r0, w "tp"
  1207. l != r // xor w, l, r; sltu w, r0, w "rp"
  1208. if (l != 0) // beq w, r0, Lskip "c"
  1209. if (l != const) // xor w, w, const; beq w, r0, Lskip "tc"
  1210. if (l != r) // beq l, r, Lskip "a"
  1211. */
  1212. char CmpBlocks[6/*op*/][2/*condbranch*/][3/*constness*/][2] =
  1213. {
  1214. {
  1215. { "k", "m", "i" },
  1216. { "f", "mc", "ic" }
  1217. },
  1218. {
  1219. { "l", "n", "js" },
  1220. { "g", "nc", "jd" }
  1221. },
  1222. {
  1223. { "o", "ns", "j" },
  1224. { "h", "nd", "jc" }
  1225. },
  1226. {
  1227. { "ks", "ms", "is" },
  1228. { "e", "md", "id" }
  1229. },
  1230. {
  1231. { "q", "tq", "rq" },
  1232. { "d", "td", "b" }
  1233. },
  1234. {
  1235. { "p", "tp", "rp" },
  1236. { "c", "tc", "a" }
  1237. }
  1238. };
  1239. void GenCmp(word* idx, word op)
  1240. {
  1241. // TODO: direct conversion from MIPS to B32P is very inefficient, so optimize this!
  1242. /*
  1243. MIPS:
  1244. slt reg, s < t (reg := 1, else reg := 0)
  1245. B32P equivalent:
  1246. bge s >= t 2
  1247. load 1 reg
  1248. load 0 reg
  1249. */
  1250. /*
  1251. Inverses:
  1252. BEQ a b BNE a b
  1253. BNE a b BEQ a b
  1254. BLTZ a (a < 0) BGE a r0 (a >= 0)
  1255. BGEZ a (a >=0) BGT r0 a (a < 0) == (0 > a)
  1256. BGTZ a (a > 0) BGE r0 a (a <= 0) == (0 >= a)
  1257. BLEZ a (a <=0) BGT a r0 (a > 0)
  1258. */
  1259. // constness: 0 = zero const, 1 = non-zero const, 2 = non-const
  1260. word constness = (stack[*idx - 1][0] == tokNumInt) ? (stack[*idx - 1][1] != 0) : 2;
  1261. word constval = (constness == 1) ? truncInt(stack[*idx - 1][1]) : 0;
  1262. // condbranch: 0 = no conditional branch, 1 = branch if true, 2 = branch if false
  1263. word condbranch = (*idx + 1 < sp) ? (stack[*idx + 1][0] == tokIf) + (stack[*idx + 1][0] == tokIfNot) * 2 : 0;
  1264. word unsign = op >> 4;
  1265. int slt = unsign ? B32PInstrSLTU : B32PInstrSLT;
  1266. word label = condbranch ? stack[*idx + 1][1] : 0;
  1267. char* p;
  1268. word i;
  1269. op &= 0xF;
  1270. if (constness == 2)
  1271. GenPopReg();
  1272. // bltz, blez, bgez, bgtz are for signed comparison with 0 only,
  1273. // so for conditional branches on <0u, <=0u, >0u, >=0u use the general method instead
  1274. if (condbranch && op < 4 && constness == 0 && unsign)
  1275. {
  1276. // Except, >0u is more optimal as !=0
  1277. if (op == 2)
  1278. op = 5;
  1279. else
  1280. constness = 1;
  1281. }
  1282. p = CmpBlocks[op][condbranch != 0][constness];
  1283. for (i = 0; i < 2; i++)
  1284. {
  1285. switch (p[i])
  1286. {
  1287. case 'a':
  1288. condbranch ^= 3;
  1289. // fallthrough
  1290. case 'b':
  1291. GenPrintInstr3Operands((condbranch == 1) ? B32PInstrBNE : B32PInstrBEQ, 0,
  1292. GenLreg, 0,
  1293. GenRreg, 0,
  1294. B32POpConst, 2);
  1295. GenPrintInstr1Operand(B32PInstrJump, 0,
  1296. B32POpNumLabel, label);
  1297. break;
  1298. case 'c':
  1299. condbranch ^= 3;
  1300. // fallthrough
  1301. case 'd':
  1302. GenPrintInstr3Operands((condbranch == 1) ? B32PInstrBNE : B32PInstrBEQ, 0,
  1303. GenWreg, 0,
  1304. B32POpRegZero, 0,
  1305. B32POpConst, 2);
  1306. GenPrintInstr1Operand(B32PInstrJump, 0,
  1307. B32POpNumLabel, label);
  1308. break;
  1309. case 'e':
  1310. condbranch ^= 3;
  1311. // fallthrough
  1312. case 'f':
  1313. /*
  1314. BLTZ a (a < 0) BGE a r0 (a >= 0)
  1315. BGEZ a (a >=0) BGT r0 a (a < 0) == (0 > a)
  1316. */
  1317. if (condbranch == 1)
  1318. {
  1319. GenPrintInstr3Operands(B32PInstrBGE, 0,
  1320. GenWreg, 0,
  1321. B32POpRegZero, 0,
  1322. B32POpConst, 2);
  1323. }
  1324. else
  1325. {
  1326. GenPrintInstr3Operands(B32PInstrBGT, 0,
  1327. B32POpRegZero, 0,
  1328. GenWreg, 0,
  1329. B32POpConst, 2);
  1330. }
  1331. GenPrintInstr1Operand(B32PInstrJump, 0,
  1332. B32POpNumLabel, label);
  1333. break;
  1334. case 'g':
  1335. condbranch ^= 3;
  1336. // fallthrough
  1337. case 'h':
  1338. /*
  1339. BGTZ a (a > 0) BGE r0 a (a <= 0) == (0 >= a)
  1340. BLEZ a (a <=0) BGT a r0 (a > 0)
  1341. */
  1342. if (condbranch == 1)
  1343. {
  1344. GenPrintInstr3Operands(B32PInstrBGE, 0,
  1345. B32POpRegZero, 0,
  1346. GenWreg, 0,
  1347. B32POpConst, 2);
  1348. }
  1349. else
  1350. {
  1351. GenPrintInstr3Operands(B32PInstrBGT, 0,
  1352. GenWreg, 0,
  1353. B32POpRegZero, 0,
  1354. B32POpConst, 2);
  1355. }
  1356. GenPrintInstr1Operand(B32PInstrJump, 0,
  1357. B32POpNumLabel, label);
  1358. break;
  1359. case 'i':
  1360. GenPrintInstr3Operands(slt, 0,
  1361. GenLreg, 0,
  1362. GenRreg, 0,
  1363. GenWreg, 0);
  1364. break;
  1365. case 'j':
  1366. GenPrintInstr3Operands(slt, 0,
  1367. GenRreg, 0,
  1368. GenLreg, 0,
  1369. GenWreg, 0);
  1370. break;
  1371. case 'k':
  1372. GenPrintInstr3Operands(slt, 0,
  1373. GenWreg, 0,
  1374. B32POpRegZero, 0,
  1375. GenWreg, 0);
  1376. break;
  1377. case 'l':
  1378. GenPrintInstr3Operands(slt, 0,
  1379. GenWreg, 0,
  1380. B32POpConst, 1,
  1381. GenWreg, 0);
  1382. break;
  1383. case 'n':
  1384. constval++;
  1385. // fallthrough
  1386. case 'm':
  1387. if (constval < 0x8000)
  1388. {
  1389. GenPrintInstr3Operands(slt, 0,
  1390. GenWreg, 0,
  1391. B32POpConst, constval,
  1392. GenWreg, 0);
  1393. }
  1394. else
  1395. {
  1396. GenPrintInstr2Operands(B32PInstrLoad, 0,
  1397. B32POpConst, constval,
  1398. TEMP_REG_A, 0);
  1399. GenPrintInstr3Operands(slt, 0,
  1400. GenWreg, 0,
  1401. TEMP_REG_A, 0,
  1402. GenWreg, 0);
  1403. }
  1404. break;
  1405. case 'o':
  1406. GenPrintInstr3Operands(slt, 0,
  1407. B32POpRegZero, 0,
  1408. GenWreg, 0,
  1409. GenWreg, 0);
  1410. break;
  1411. case 'p':
  1412. GenPrintInstr3Operands(B32PInstrSLTU, 0,
  1413. B32POpRegZero, 0,
  1414. GenWreg, 0,
  1415. GenWreg, 0);
  1416. break;
  1417. case 'q':
  1418. GenPrintInstr3Operands(B32PInstrSLTU, 0,
  1419. GenWreg, 0,
  1420. B32POpConst, 1,
  1421. GenWreg, 0);
  1422. break;
  1423. case 'r':
  1424. GenPrintInstr3Operands(B32PInstrXOR, 0,
  1425. GenLreg, 0,
  1426. GenRreg, 0,
  1427. GenWreg, 0);
  1428. break;
  1429. case 's':
  1430. GenPrintInstr3Operands(B32PInstrXOR, 0,
  1431. GenWreg, 0,
  1432. B32POpConst, 1,
  1433. GenWreg, 0);
  1434. break;
  1435. case 't':
  1436. if (constval < 0x8000)
  1437. {
  1438. GenPrintInstr3Operands(B32PInstrXOR, 0,
  1439. GenWreg, 0,
  1440. B32POpConst, constval,
  1441. GenWreg, 0);
  1442. }
  1443. else
  1444. {
  1445. GenPrintInstr2Operands(B32PInstrLoad, 0,
  1446. B32POpConst, constval,
  1447. TEMP_REG_A, 0);
  1448. GenPrintInstr3Operands(B32PInstrXOR, 0,
  1449. GenWreg, 0,
  1450. TEMP_REG_A, 0,
  1451. GenWreg, 0);
  1452. }
  1453. break;
  1454. }
  1455. }
  1456. *idx += condbranch != 0;
  1457. }
  1458. word GenIsCmp(word t)
  1459. {
  1460. return
  1461. t == '<' ||
  1462. t == '>' ||
  1463. t == tokGEQ ||
  1464. t == tokLEQ ||
  1465. t == tokULess ||
  1466. t == tokUGreater ||
  1467. t == tokUGEQ ||
  1468. t == tokULEQ ||
  1469. t == tokEQ ||
  1470. t == tokNEQ;
  1471. }
  1472. // Improved register/stack-based code generator
  1473. // DONE: test 32-bit code generation
  1474. void GenExpr0(void)
  1475. {
  1476. word i;
  1477. word gotUnary = 0;
  1478. word maxCallDepth = 0;
  1479. word callDepth = 0;
  1480. word paramOfs = 0;
  1481. word t = sp - 1;
  1482. if (stack[t][0] == tokIf || stack[t][0] == tokIfNot || stack[t][0] == tokReturn)
  1483. t--;
  1484. GenPrep(&t);
  1485. for (i = 0; i < sp; i++)
  1486. if (stack[i][0] == '(')
  1487. {
  1488. if (++callDepth > maxCallDepth)
  1489. maxCallDepth = callDepth;
  1490. }
  1491. else if (stack[i][0] == ')')
  1492. {
  1493. callDepth--;
  1494. }
  1495. CanUseTempRegs = maxCallDepth == 0;
  1496. TempsUsed = 0;
  1497. if (GenWreg != B32POpRegV0)
  1498. errorInternal(102);
  1499. for (i = 0; i < sp; i++)
  1500. {
  1501. word tok = stack[i][0];
  1502. word v = stack[i][1];
  1503. if (doAnnotations)
  1504. {
  1505. switch (tok)
  1506. {
  1507. case tokNumInt: printf2(" ; "); printd2(truncInt(v)); printf2("\n"); break;
  1508. //case tokNumUint: printf2(" ; %uu\n", truncUint(v)); break;
  1509. case tokIdent: case tokRevIdent: printf2(" ; "); printf2(IdentTable + v); printf2("\n"); break;
  1510. case tokLocalOfs: case tokRevLocalOfs: printf2(" ; local ofs\n"); break;
  1511. case ')': printf2(" ; ) fxn call\n"); break;
  1512. case tokUnaryStar: printf2(" ; * (read dereference)\n"); break;
  1513. case '=': printf2(" ; = (write dereference)\n"); break;
  1514. case tokShortCirc: printf2(" ; short-circuit "); break;
  1515. case tokGoto: printf2(" ; sh-circ-goto "); break;
  1516. case tokLogAnd: printf2(" ; short-circuit && target\n"); break;
  1517. case tokLogOr: printf2(" ; short-circuit || target\n"); break;
  1518. case tokIf: case tokIfNot: case tokReturn: break;
  1519. case tokNum0: printf2(" ; 0\n"); break;
  1520. case tokAssign0: printf2(" ; =\n"); break;
  1521. default: printf2(" ; "); printf2(GetTokenName(tok)); printf2("\n"); break;
  1522. }
  1523. }
  1524. switch (tok)
  1525. {
  1526. case tokNumInt:
  1527. if (!(i + 1 < sp && ((t = stack[i + 1][0]) == '+' ||
  1528. t == '-' ||
  1529. t == '&' ||
  1530. t == '^' ||
  1531. t == '|' ||
  1532. t == tokLShift ||
  1533. t == tokRShift ||
  1534. t == tokURShift ||
  1535. GenIsCmp(t))))
  1536. {
  1537. if (gotUnary)
  1538. GenPushReg();
  1539. GenPrintInstr2Operands(B32PInstrLoad, 0,
  1540. B32POpConst, v,
  1541. GenWreg, 0);
  1542. }
  1543. gotUnary = 1;
  1544. break;
  1545. case tokIdent:
  1546. if (gotUnary)
  1547. GenPushReg();
  1548. if (!(i + 1 < sp && ((t = stack[i + 1][0]) == ')' ||
  1549. t == tokUnaryStar ||
  1550. t == tokInc ||
  1551. t == tokDec ||
  1552. t == tokPostInc ||
  1553. t == tokPostDec)))
  1554. {
  1555. GenPrintInstr2Operands(B32PInstrAddr2reg, 0,
  1556. B32POpLabel, v,
  1557. GenWreg, 0);
  1558. }
  1559. gotUnary = 1;
  1560. break;
  1561. case tokLocalOfs:
  1562. if (gotUnary)
  1563. GenPushReg();
  1564. if (!(i + 1 < sp && ((t = stack[i + 1][0]) == tokUnaryStar ||
  1565. t == tokInc ||
  1566. t == tokDec ||
  1567. t == tokPostInc ||
  1568. t == tokPostDec)))
  1569. {
  1570. GenPrintInstr3Operands(B32PInstrADD, 0,
  1571. B32POpRegFp, 0,
  1572. B32POpConst, v,
  1573. GenWreg, 0);
  1574. }
  1575. gotUnary = 1;
  1576. break;
  1577. case '(':
  1578. if (gotUnary)
  1579. GenPushReg();
  1580. gotUnary = 0;
  1581. if (maxCallDepth != 1 && v < 16)
  1582. GenGrowStack(16 - v);
  1583. paramOfs = v - 4;
  1584. if (maxCallDepth == 1 && paramOfs >= 0 && paramOfs <= 12)
  1585. {
  1586. // Work directly in A0-A3 instead of working in V0 and avoid copying V0 to A0-A3
  1587. GenWreg = B32POpRegA0 + division(paramOfs, 4); //(paramOfs >> 2); //division(paramOfs, 4);
  1588. }
  1589. break;
  1590. case ',':
  1591. if (maxCallDepth == 1)
  1592. {
  1593. if (paramOfs == 16)
  1594. {
  1595. // Got the last on-stack parameter, the rest will go in A0-A3
  1596. GenPushReg();
  1597. gotUnary = 0;
  1598. GenWreg = B32POpRegA3;
  1599. }
  1600. if (paramOfs >= 0 && paramOfs <= 12)
  1601. {
  1602. // Advance to the next An reg or revert to V0
  1603. if (paramOfs)
  1604. GenWreg--;
  1605. else
  1606. GenWreg = B32POpRegV0;
  1607. gotUnary = 0;
  1608. }
  1609. paramOfs -= 4;
  1610. }
  1611. break;
  1612. case ')':
  1613. GenLeaf = 0;
  1614. if (maxCallDepth != 1)
  1615. {
  1616. if (v >= 4)
  1617. GenPrintInstr2Operands(B32PInstrRead, 0,
  1618. B32POpIndRegSp, 0,
  1619. B32POpRegA0, 0);
  1620. if (v >= 8)
  1621. GenPrintInstr2Operands(B32PInstrRead, 0,
  1622. B32POpIndRegSp, 4,
  1623. B32POpRegA1, 0);
  1624. if (v >= 12)
  1625. GenPrintInstr2Operands(B32PInstrRead, 0,
  1626. B32POpIndRegSp, 8,
  1627. B32POpRegA2, 0);
  1628. if (v >= 16)
  1629. GenPrintInstr2Operands(B32PInstrRead, 0,
  1630. B32POpIndRegSp, 12,
  1631. B32POpRegA3, 0);
  1632. }
  1633. else
  1634. {
  1635. GenGrowStack(16);
  1636. }
  1637. if (stack[i - 1][0] == tokIdent)
  1638. {
  1639. GenPrintInstr1Operand(B32PInstrSavPC, 0,
  1640. B32POpRegRa, 0);
  1641. GenPrintInstr3Operands(B32PInstrADD, 0,
  1642. B32POpRegRa, 0,
  1643. B32POpConst, 3,
  1644. B32POpRegRa, 0);
  1645. GenPrintInstr1Operand(B32PInstrJump, 0,
  1646. B32POpLabel, stack[i - 1][1]);
  1647. }
  1648. else
  1649. {
  1650. GenPrintInstr1Operand(B32PInstrSavPC, 0,
  1651. B32POpRegRa, 0);
  1652. GenPrintInstr3Operands(B32PInstrADD, 0,
  1653. B32POpRegRa, 0,
  1654. B32POpConst, 3,
  1655. B32POpRegRa, 0);
  1656. GenPrintInstr2Operands(B32PInstrJumpr, 0,
  1657. B32POpConst, 0,
  1658. GenWreg, 0);
  1659. }
  1660. if (v < 16)
  1661. v = 16;
  1662. GenGrowStack(-v);
  1663. break;
  1664. case tokUnaryStar:
  1665. if (stack[i - 1][0] == tokIdent)
  1666. GenReadIdent(GenWreg, v, stack[i - 1][1]);
  1667. else if (stack[i - 1][0] == tokLocalOfs)
  1668. GenReadLocal(GenWreg, v, stack[i - 1][1]);
  1669. else
  1670. GenReadIndirect(GenWreg, GenWreg, v);
  1671. break;
  1672. case tokUnaryPlus:
  1673. break;
  1674. case '~': //nor
  1675. GenPrintInstr3Operands(B32PInstrOR, 0,
  1676. GenWreg, 0,
  1677. GenWreg, 0,
  1678. GenWreg, 0);
  1679. GenPrintInstr2Operands(B32PInstrNOT, 0,
  1680. GenWreg, 0,
  1681. GenWreg, 0);
  1682. break;
  1683. case tokUnaryMinus:
  1684. GenPrintInstr3Operands(B32PInstrSUB, 0,
  1685. B32POpRegZero, 0,
  1686. GenWreg, 0,
  1687. GenWreg, 0);
  1688. break;
  1689. case '+':
  1690. case '-':
  1691. case '*':
  1692. case '&':
  1693. case '^':
  1694. case '|':
  1695. case tokLShift:
  1696. case tokRShift:
  1697. case tokURShift:
  1698. if (stack[i - 1][0] == tokNumInt && tok != '*')
  1699. {
  1700. word instr = GenGetBinaryOperatorInstr(tok);
  1701. GenPrintInstr3Operands(instr, 0,
  1702. GenWreg, 0,
  1703. B32POpConst, stack[i - 1][1],
  1704. GenWreg, 0);
  1705. }
  1706. else
  1707. {
  1708. word instr = GenGetBinaryOperatorInstr(tok);
  1709. GenPopReg();
  1710. GenPrintInstr3Operands(instr, 0,
  1711. GenLreg, 0,
  1712. GenRreg, 0,
  1713. GenWreg, 0);
  1714. }
  1715. break;
  1716. case '/':
  1717. case tokUDiv:
  1718. case '%':
  1719. case tokUMod:
  1720. {
  1721. printf("DIVISION/MOD is not supported!\n");
  1722. /*
  1723. GenPopReg();
  1724. if (tok == '/' || tok == '%')
  1725. GenPrintInstr3Operands(MipsInstrDiv, 0,
  1726. B32POpRegZero, 0,
  1727. GenLreg, 0,
  1728. GenRreg, 0);
  1729. else
  1730. GenPrintInstr3Operands(MipsInstrDivU, 0,
  1731. B32POpRegZero, 0,
  1732. GenLreg, 0,
  1733. GenRreg, 0);
  1734. if (tok == '%' || tok == tokUMod)
  1735. GenPrintInstr1Operand(MipsInstrMfHi, 0,
  1736. GenWreg, 0);
  1737. else
  1738. GenPrintInstr1Operand(MipsInstrMfLo, 0,
  1739. GenWreg, 0);
  1740. */
  1741. }
  1742. break;
  1743. case tokInc:
  1744. case tokDec:
  1745. if (stack[i - 1][0] == tokIdent)
  1746. {
  1747. GenIncDecIdent(GenWreg, v, stack[i - 1][1], tok);
  1748. }
  1749. else if (stack[i - 1][0] == tokLocalOfs)
  1750. {
  1751. GenIncDecLocal(GenWreg, v, stack[i - 1][1], tok);
  1752. }
  1753. else
  1754. {
  1755. GenPrintInstr3Operands(B32PInstrOR, 0,
  1756. B32POpRegZero, 0,
  1757. GenWreg, 0,
  1758. TEMP_REG_A, 0);
  1759. GenIncDecIndirect(GenWreg, TEMP_REG_A, v, tok);
  1760. }
  1761. break;
  1762. case tokPostInc:
  1763. case tokPostDec:
  1764. if (stack[i - 1][0] == tokIdent)
  1765. {
  1766. GenPostIncDecIdent(GenWreg, v, stack[i - 1][1], tok);
  1767. }
  1768. else if (stack[i - 1][0] == tokLocalOfs)
  1769. {
  1770. GenPostIncDecLocal(GenWreg, v, stack[i - 1][1], tok);
  1771. }
  1772. else
  1773. {
  1774. GenPrintInstr3Operands(B32PInstrOR, 0,
  1775. B32POpRegZero, 0,
  1776. GenWreg, 0,
  1777. TEMP_REG_A, 0);
  1778. GenPostIncDecIndirect(GenWreg, TEMP_REG_A, v, tok);
  1779. }
  1780. break;
  1781. case tokPostAdd:
  1782. case tokPostSub:
  1783. {
  1784. word instr = GenGetBinaryOperatorInstr(tok);
  1785. GenPopReg();
  1786. if (GenWreg == GenLreg)
  1787. {
  1788. GenPrintInstr3Operands(B32PInstrOR, 0,
  1789. B32POpRegZero, 0,
  1790. GenLreg, 0,
  1791. TEMP_REG_B, 0);
  1792. GenReadIndirect(GenWreg, TEMP_REG_B, v);
  1793. GenPrintInstr3Operands(instr, 0,
  1794. GenWreg, 0,
  1795. GenRreg, 0,
  1796. TEMP_REG_A, 0);
  1797. GenWriteIndirect(TEMP_REG_B, TEMP_REG_A, v);
  1798. }
  1799. else
  1800. {
  1801. // GenWreg == GenRreg here
  1802. GenPrintInstr3Operands(B32PInstrOR, 0,
  1803. B32POpRegZero, 0,
  1804. GenRreg, 0,
  1805. TEMP_REG_B, 0);
  1806. GenReadIndirect(GenWreg, GenLreg, v);
  1807. GenPrintInstr3Operands(instr, 0,
  1808. GenWreg, 0,
  1809. TEMP_REG_B, 0,
  1810. TEMP_REG_B, 0);
  1811. GenWriteIndirect(GenLreg, TEMP_REG_B, v);
  1812. }
  1813. }
  1814. break;
  1815. case tokAssignAdd:
  1816. case tokAssignSub:
  1817. case tokAssignMul:
  1818. case tokAssignAnd:
  1819. case tokAssignXor:
  1820. case tokAssignOr:
  1821. case tokAssignLSh:
  1822. case tokAssignRSh:
  1823. case tokAssignURSh:
  1824. if (stack[i - 1][0] == tokRevLocalOfs || stack[i - 1][0] == tokRevIdent)
  1825. {
  1826. word instr = GenGetBinaryOperatorInstr(tok);
  1827. if (stack[i - 1][0] == tokRevLocalOfs)
  1828. GenReadLocal(TEMP_REG_B, v, stack[i - 1][1]);
  1829. else
  1830. GenReadIdent(TEMP_REG_B, v, stack[i - 1][1]);
  1831. GenPrintInstr3Operands(instr, 0,
  1832. TEMP_REG_B, 0,
  1833. GenWreg, 0,
  1834. GenWreg, 0);
  1835. if (stack[i - 1][0] == tokRevLocalOfs)
  1836. GenWriteLocal(GenWreg, v, stack[i - 1][1]);
  1837. else
  1838. GenWriteIdent(GenWreg, v, stack[i - 1][1]);
  1839. }
  1840. else
  1841. {
  1842. word instr = GenGetBinaryOperatorInstr(tok);
  1843. word lsaved, rsaved;
  1844. GenPopReg();
  1845. if (GenWreg == GenLreg)
  1846. {
  1847. GenPrintInstr3Operands(B32PInstrOR, 0,
  1848. B32POpRegZero, 0,
  1849. GenLreg, 0,
  1850. TEMP_REG_B, 0);
  1851. lsaved = TEMP_REG_B;
  1852. rsaved = GenRreg;
  1853. }
  1854. else
  1855. {
  1856. // GenWreg == GenRreg here
  1857. GenPrintInstr3Operands(B32PInstrOR, 0,
  1858. B32POpRegZero, 0,
  1859. GenRreg, 0,
  1860. TEMP_REG_B, 0);
  1861. rsaved = TEMP_REG_B;
  1862. lsaved = GenLreg;
  1863. }
  1864. GenReadIndirect(GenWreg, GenLreg, v); // destroys either GenLreg or GenRreg because GenWreg coincides with one of them
  1865. GenPrintInstr3Operands(instr, 0,
  1866. GenWreg, 0,
  1867. rsaved, 0,
  1868. GenWreg, 0);
  1869. GenWriteIndirect(lsaved, GenWreg, v);
  1870. }
  1871. GenExtendRegIfNeeded(GenWreg, v);
  1872. break;
  1873. case tokAssignDiv:
  1874. case tokAssignUDiv:
  1875. case tokAssignMod:
  1876. case tokAssignUMod:
  1877. if (stack[i - 1][0] == tokRevLocalOfs || stack[i - 1][0] == tokRevIdent)
  1878. {
  1879. if (stack[i - 1][0] == tokRevLocalOfs)
  1880. GenReadLocal(TEMP_REG_B, v, stack[i - 1][1]);
  1881. else
  1882. GenReadIdent(TEMP_REG_B, v, stack[i - 1][1]);
  1883. if (tok == tokAssignDiv || tok == tokAssignMod)
  1884. {
  1885. printf("DIVISION/MOD is not supported!\n");
  1886. /*
  1887. GenPrintInstr3Operands(MipsInstrDiv, 0,
  1888. B32POpRegZero, 0,
  1889. TEMP_REG_B, 0,
  1890. GenWreg, 0);*/
  1891. }
  1892. else
  1893. {
  1894. printf("DIVISION/MOD is not supported!\n");
  1895. /*
  1896. GenPrintInstr3Operands(MipsInstrDivU, 0,
  1897. B32POpRegZero, 0,
  1898. TEMP_REG_B, 0,
  1899. GenWreg, 0);*/
  1900. }
  1901. if (tok == tokAssignMod || tok == tokAssignUMod)
  1902. {
  1903. printf("DIVISION/MOD is not supported!\n");
  1904. /*
  1905. GenPrintInstr1Operand(MipsInstrMfHi, 0,
  1906. GenWreg, 0);*/
  1907. }
  1908. else
  1909. {
  1910. printf("DIVISION/MOD is not supported!\n");
  1911. /*
  1912. GenPrintInstr1Operand(MipsInstrMfLo, 0,
  1913. GenWreg, 0);*/
  1914. }
  1915. if (stack[i - 1][0] == tokRevLocalOfs)
  1916. GenWriteLocal(GenWreg, v, stack[i - 1][1]);
  1917. else
  1918. GenWriteIdent(GenWreg, v, stack[i - 1][1]);
  1919. }
  1920. else
  1921. {
  1922. word lsaved, rsaved;
  1923. GenPopReg();
  1924. if (GenWreg == GenLreg)
  1925. {
  1926. GenPrintInstr3Operands(B32PInstrOR, 0,
  1927. B32POpRegZero, 0,
  1928. GenLreg, 0,
  1929. TEMP_REG_B, 0);
  1930. lsaved = TEMP_REG_B;
  1931. rsaved = GenRreg;
  1932. }
  1933. else
  1934. {
  1935. // GenWreg == GenRreg here
  1936. GenPrintInstr3Operands(B32PInstrOR, 0,
  1937. B32POpRegZero, 0,
  1938. GenRreg, 0,
  1939. TEMP_REG_B, 0);
  1940. rsaved = TEMP_REG_B;
  1941. lsaved = GenLreg;
  1942. }
  1943. GenReadIndirect(GenWreg, GenLreg, v); // destroys either GenLreg or GenRreg because GenWreg coincides with one of them
  1944. if (tok == tokAssignDiv || tok == tokAssignMod)
  1945. {
  1946. printf("DIVISION/MOD is not supported!\n");
  1947. /*
  1948. GenPrintInstr3Operands(MipsInstrDiv, 0,
  1949. B32POpRegZero, 0,
  1950. GenWreg, 0,
  1951. rsaved, 0);*/
  1952. }
  1953. else
  1954. {
  1955. printf("DIVISION/MOD is not supported!\n");
  1956. /*
  1957. GenPrintInstr3Operands(MipsInstrDivU, 0,
  1958. B32POpRegZero, 0,
  1959. GenWreg, 0,
  1960. rsaved, 0);*/
  1961. }
  1962. if (tok == tokAssignMod || tok == tokAssignUMod)
  1963. {
  1964. printf("DIVISION/MOD is not supported!\n");
  1965. /*
  1966. GenPrintInstr1Operand(MipsInstrMfHi, 0,
  1967. GenWreg, 0);*/
  1968. }
  1969. else
  1970. {
  1971. printf("DIVISION/MOD is not supported!\n");
  1972. /*
  1973. GenPrintInstr1Operand(MipsInstrMfLo, 0,
  1974. GenWreg, 0);*/
  1975. }
  1976. GenWriteIndirect(lsaved, GenWreg, v);
  1977. }
  1978. GenExtendRegIfNeeded(GenWreg, v);
  1979. break;
  1980. case '=':
  1981. if (stack[i - 1][0] == tokRevLocalOfs)
  1982. {
  1983. GenWriteLocal(GenWreg, v, stack[i - 1][1]);
  1984. }
  1985. else if (stack[i - 1][0] == tokRevIdent)
  1986. {
  1987. GenWriteIdent(GenWreg, v, stack[i - 1][1]);
  1988. }
  1989. else
  1990. {
  1991. GenPopReg();
  1992. GenWriteIndirect(GenLreg, GenRreg, v);
  1993. if (GenWreg != GenRreg)
  1994. GenPrintInstr3Operands(B32PInstrOR, 0,
  1995. B32POpRegZero, 0,
  1996. GenRreg, 0,
  1997. GenWreg, 0);
  1998. }
  1999. GenExtendRegIfNeeded(GenWreg, v);
  2000. break;
  2001. case tokAssign0: // assignment of 0, while throwing away the expression result value
  2002. if (stack[i - 1][0] == tokRevLocalOfs)
  2003. {
  2004. GenWriteLocal(B32POpRegZero, v, stack[i - 1][1]);
  2005. }
  2006. else if (stack[i - 1][0] == tokRevIdent)
  2007. {
  2008. GenWriteIdent(B32POpRegZero, v, stack[i - 1][1]);
  2009. }
  2010. else
  2011. {
  2012. GenWriteIndirect(GenWreg, B32POpRegZero, v);
  2013. }
  2014. break;
  2015. case '<': GenCmp(&i, 0x00); break;
  2016. case tokLEQ: GenCmp(&i, 0x01); break;
  2017. case '>': GenCmp(&i, 0x02); break;
  2018. case tokGEQ: GenCmp(&i, 0x03); break;
  2019. case tokULess: GenCmp(&i, 0x10); break;
  2020. case tokULEQ: GenCmp(&i, 0x11); break;
  2021. case tokUGreater: GenCmp(&i, 0x12); break;
  2022. case tokUGEQ: GenCmp(&i, 0x13); break;
  2023. case tokEQ: GenCmp(&i, 0x04); break;
  2024. case tokNEQ: GenCmp(&i, 0x05); break;
  2025. case tok_Bool:
  2026. /* if 0 < wreg (if wreg > 0)
  2027. wreg = 1
  2028. else
  2029. wreg = 0
  2030. GenPrintInstr3Operands(MipsInstrSLTU, 0,
  2031. GenWreg, 0,
  2032. B32POpRegZero, 0,
  2033. GenWreg, 0);
  2034. */
  2035. GenPrintInstr3Operands(B32PInstrSLTU, 0,
  2036. B32POpRegZero, 0,
  2037. GenWreg, 0,
  2038. GenWreg, 0);
  2039. break;
  2040. case tokSChar:
  2041. /* just use as an int for now
  2042. GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
  2043. GenWreg, 0,
  2044. B32POpConst, 24,
  2045. GenWreg, 0);
  2046. GenPrintInstr3Operands(B32PInstrSHIFTR, 0, //TODO this should have also replicated the sign bit (SRA)
  2047. GenWreg, 0,
  2048. B32POpConst, 24,
  2049. GenWreg, 0);
  2050. */
  2051. break;
  2052. case tokUChar:
  2053. /* just use as an int for now
  2054. GenPrintInstr3Operands(B32PInstrAND, 0,
  2055. GenWreg, 0,
  2056. B32POpConst, 0xFF,
  2057. GenWreg, 0);
  2058. */
  2059. break;
  2060. case tokShort:
  2061. /* just use as an int for now
  2062. GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
  2063. GenWreg, 0,
  2064. B32POpConst, 16,
  2065. GenWreg, 0);
  2066. GenPrintInstr3Operands(B32PInstrSHIFTR, 0, //TODO this should have also replicated the sign bit (SRA)
  2067. GenWreg, 0,
  2068. B32POpConst, 16,
  2069. GenWreg, 0);
  2070. */
  2071. break;
  2072. case tokUShort:
  2073. /*
  2074. GenPrintInstr3Operands(MipsInstrAnd, 0,
  2075. GenWreg, 0,
  2076. GenWreg, 0,
  2077. B32POpConst, 0xFFFF);*/
  2078. /* just use as an int for now
  2079. GenPrintInstr3Operands(B32PInstrSHIFTL, 0,
  2080. GenWreg, 0,
  2081. B32POpConst, 16,
  2082. GenWreg, 0);
  2083. GenPrintInstr3Operands(B32PInstrSHIFTR, 0,
  2084. GenWreg, 0,
  2085. B32POpConst, 16,
  2086. GenWreg, 0);
  2087. */
  2088. break;
  2089. case tokShortCirc:
  2090. if (doAnnotations)
  2091. {
  2092. if (v >= 0)
  2093. printf2("&&\n");
  2094. else
  2095. printf2("||\n");
  2096. }
  2097. if (v >= 0)
  2098. GenJumpIfZero(v); // &&
  2099. else
  2100. GenJumpIfNotZero(-v); // ||
  2101. gotUnary = 0;
  2102. break;
  2103. case tokGoto:
  2104. if (doAnnotations)
  2105. {
  2106. printf2("goto\n");
  2107. }
  2108. GenJumpUncond(v);
  2109. gotUnary = 0;
  2110. break;
  2111. case tokLogAnd:
  2112. case tokLogOr:
  2113. GenNumLabel(v);
  2114. break;
  2115. case tokVoid:
  2116. gotUnary = 0;
  2117. break;
  2118. case tokRevIdent:
  2119. case tokRevLocalOfs:
  2120. case tokComma:
  2121. case tokReturn:
  2122. case tokNum0:
  2123. break;
  2124. case tokIf:
  2125. GenJumpIfNotZero(stack[i][1]);
  2126. break;
  2127. case tokIfNot:
  2128. GenJumpIfZero(stack[i][1]);
  2129. break;
  2130. default:
  2131. //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok));
  2132. errorInternal(103);
  2133. break;
  2134. }
  2135. }
  2136. if (GenWreg != B32POpRegV0)
  2137. errorInternal(104);
  2138. }
  2139. void GenDumpChar(word ch)
  2140. {
  2141. if (ch < 0)
  2142. {
  2143. if (TokenStringLen)
  2144. printf2("\n");
  2145. return;
  2146. }
  2147. if (TokenStringLen == 0)
  2148. {
  2149. GenStartAsciiString();
  2150. //printf2("\"");
  2151. }
  2152. // Just print as ascii value
  2153. printd2(ch);
  2154. printf2(" ");
  2155. }
  2156. void GenExpr(void)
  2157. {
  2158. GenExpr0();
  2159. }
  2160. void GenFin(void)
  2161. {
  2162. // No idea what this does (something with structs??), so I just literally converted it to B32P asm
  2163. if (StructCpyLabel)
  2164. {
  2165. word lbl = LabelCnt++;
  2166. puts2(CodeHeaderFooter[0]);
  2167. GenNumLabel(StructCpyLabel);
  2168. //puts2(" move r2, r6\n" //r2 := r6
  2169. // " move r3, r6"); //r3 := r3
  2170. puts2(" or r0 r6 r2\n"
  2171. " or r0 r6 r3");
  2172. GenNumLabel(lbl);
  2173. //puts2(" lbu r6, 0 r5\n" // r6:=mem[r5]
  2174. // " addiu r5, r5, 1\n" // r5:= r5+1
  2175. // " addiu r4, r4, -1\n" // r4:= r4-1
  2176. // " sb r6, 0 r3\n" // mem[r3]:=r6
  2177. // " addiu r3, r3, 1"); // r3:= r3+1
  2178. puts2(" read 0 r5 r6\n"
  2179. " add r5 1 r5\n"
  2180. " sub r4 1 r4\n"
  2181. " write 0 r3 r6\n"
  2182. " add r3 1 r3");
  2183. //printf2(" bne r4, r0, "); GenPrintNumLabel(lbl); // if r4 != 0, jump to lbl
  2184. printf2("beq r4 r0 2\n");
  2185. printf2("jump ");GenPrintNumLabel(lbl);
  2186. puts2("");
  2187. puts2(" jumpr 0 r15");
  2188. puts2(CodeHeaderFooter[1]);
  2189. }
  2190. // Put all ending C specific wrapper code here
  2191. if (compileUserBDOS)
  2192. {
  2193. printf2(
  2194. ".code\n"
  2195. "Int:\n"
  2196. " load32 0x7BFFFF r13\n"
  2197. " load32 0 r14\n"
  2198. " addr2reg Return_Interrupt r1\n"
  2199. " or r0 r1 r15\n"
  2200. " jump interrupt\n"
  2201. " halt\n"
  2202. "Return_Interrupt:\n"
  2203. " pop r1\n"
  2204. " jumpr 3 r1\n"
  2205. " halt\n"
  2206. );
  2207. }
  2208. else
  2209. {
  2210. printf2(
  2211. ".code\n"
  2212. "Int:\n"
  2213. " push r1\n"
  2214. " push r2\n"
  2215. " push r3\n"
  2216. " push r4\n"
  2217. " push r5\n"
  2218. " push r6\n"
  2219. " push r7\n"
  2220. " push r8\n"
  2221. " push r9\n"
  2222. " push r10\n"
  2223. " push r11\n"
  2224. " push r12\n"
  2225. " push r13\n"
  2226. " push r14\n"
  2227. " push r15\n"
  2228. " load32 0x7FFFFF r13\n"
  2229. " load32 0 r14\n"
  2230. " addr2reg Return_Interrupt r1\n"
  2231. " or r0 r1 r15\n"
  2232. " jump int1\n"
  2233. " halt\n"
  2234. "Return_Interrupt:\n"
  2235. " pop r15\n"
  2236. " pop r14\n"
  2237. " pop r13\n"
  2238. " pop r12\n"
  2239. " pop r11\n"
  2240. " pop r10\n"
  2241. " pop r9\n"
  2242. " pop r8\n"
  2243. " pop r7\n"
  2244. " pop r6\n"
  2245. " pop r5\n"
  2246. " pop r4\n"
  2247. " pop r3\n"
  2248. " pop r2\n"
  2249. " pop r1\n"
  2250. " reti\n"
  2251. " halt\n");
  2252. }
  2253. if (compileOS)
  2254. {
  2255. printf2(
  2256. ".code\n"
  2257. "Syscall:\n"
  2258. " load32 0x3FFFFF r13\n"
  2259. " load32 0 r14\n"
  2260. " addr2reg Return_Syscall r1\n"
  2261. " or r0 r1 r15\n"
  2262. " jump syscall\n"
  2263. " halt\n"
  2264. "Return_Syscall:\n"
  2265. " pop r1\n"
  2266. " jumpr 3 r1\n"
  2267. " halt\n"
  2268. );
  2269. }
  2270. }