backend.c 70 KB

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