home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / BlitzSrc / ir.cc < prev    next >
C/C++ Source or Header  |  2007-09-19  |  105KB  |  3,694 lines

  1. // ir.cc  --  Methods for IR classes
  2. //
  3. // KPL Compiler
  4. //
  5. // Copyright 2002-2007, Harry H. Porter III
  6. //
  7. // This file may be freely copied, modified and compiled, on the sole
  8. // condition that if you modify it...
  9. //   (1) Your name and the date of modification is added to this comment
  10. //       under "Modifications by", and
  11. //   (2) Your name and the date of modification is added to the printHelp()
  12. //       routine in file "main.cc" under "Modifications by".
  13. //
  14. // Original Author:
  15. //    05/24/03 - Harry H. Porter III
  16. //
  17. // Modifcations by:
  18. //   03/15/06 - Harry H. Porter III
  19. //
  20. //
  21.  
  22. #include "main.h"
  23.  
  24.  
  25.  
  26. // within16Bits (int) --> bool
  27. //
  28. // This routine returns true if the argument can be represented as a 2's
  29. // complement signed, 16-bit integer, and can therefore be put into the
  30. // immediate field of instructions like:
  31. //        mul     r1,xxxxx,r2
  32. //        mov     xxxxx, r3
  33. //        load    [r14+xxxxx],r5
  34. //
  35. int within16Bits (int i) {
  36.   if ((i <= 32767) && (i >= -32768)) {
  37.     return 1;
  38.   } else {
  39.     return 0;
  40.   }
  41. }
  42.  
  43.  
  44.  
  45. // getIntoReg4 (src, reg)
  46. //
  47. // This routine generates the code necessary to get the "src" into "reg".
  48. // It moves the 4 bytes of data into "reg".
  49. //
  50. // "src" should be:
  51. //      LOCAL
  52. //      PARAMETER
  53. //      GLOBAL
  54. //      CLASS_FIELD
  55. //      INT_CONST
  56. //
  57. void getIntoReg4 (AstNode * src, char * reg) {
  58.   int i;
  59.   if ((src->op == LOCAL) || (src->op == PARAMETER)) {
  60.     i = ((VarDecl *) src)->offset;
  61.     if (within16Bits (i)) {
  62.       fprintf (outputFile, "\tload\t[r14+%d],%s\n", i, reg);
  63.     } else {
  64.       // printf ("16-BIT OVERFLOW IN VARIABLE1: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  65.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg);
  66.       fprintf (outputFile, "\tload\t[r14+%s],%s\n", reg, reg);
  67.     }
  68.   } else if (src->op == CLASS_FIELD) {
  69.     i = ((VarDecl *) src)->offset;
  70.     if (within16Bits (i)) {
  71.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg);
  72.       fprintf (outputFile, "\tload\t[%s+%d],%s\n", reg, i, reg);
  73.     } else {
  74.       // printf ("16-BIT OVERFLOW IN VARIABLE2: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  75.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  76.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg);
  77.       fprintf (outputFile, "\tload\t[r11+%s],%s\n", reg, reg);
  78.     }
  79.   } else if (src->op == GLOBAL) {
  80.     fprintf (outputFile, "\tset\t%s,%s\n", ((VarDecl *) src)->id->chars, reg);
  81.     fprintf (outputFile, "\tload\t[%s],%s\n", reg, reg);
  82.   } else if (src->op == INT_CONST) {
  83.     i = ((IntConst *) src)->ivalue;
  84.     if (within16Bits (i)) {
  85.       fprintf (outputFile, "\tmov\t%d,%s\n", i, reg);
  86.     } else if (i == 0x80000000) {
  87.       fprintf (outputFile, "\tset\t0x80000000,%s\n", reg);
  88.     } else {
  89.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg);
  90.     }
  91.   } else {
  92.     printf ("\nsrc->op = %s\n", symbolName (src->op));
  93.     programLogicError ("Unknown node in getIntoReg4");
  94.   }
  95. }
  96.  
  97.  
  98.  
  99. // getIntoReg1 (src, reg)
  100. //
  101. // This routine generates the code necessary to get the "src" into "reg".
  102. // It moves the 1 byte of data into the LSB of "reg1" and clears the hi-order
  103. // 24 bits.
  104. //
  105. // "src" should be:
  106. //      LOCAL
  107. //      PARAMETER
  108. //      GLOBAL
  109. //      CLASS_FIELD
  110. //      CHAR_CONST
  111. //      BOOL_CONST
  112. //
  113. void getIntoReg1 (AstNode * src, char * reg) {
  114.   int i;
  115.   if ((src->op == LOCAL) || (src->op == PARAMETER)) {
  116.     i = ((VarDecl *) src)->offset;
  117.     if (within16Bits (i)) {
  118.       fprintf (outputFile, "\tloadb\t[r14+%d],%s\n", i, reg);
  119.     } else {
  120.       // printf ("16-BIT OVERFLOW IN VARIABLE3: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  121.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg);
  122.       fprintf (outputFile, "\tloadb\t[r14+%s],%s\n", reg, reg);
  123.     }
  124.   } else if (src->op == CLASS_FIELD) {
  125.     i = ((VarDecl *) src)->offset;
  126.     if (within16Bits (i)) {
  127.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg);
  128.       fprintf (outputFile, "\tloadb\t[%s+%d],%s\n", reg, i, reg);
  129.     } else {
  130.       // printf ("16-BIT OVERFLOW IN VARIABLE4: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  131.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  132.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg);
  133.       fprintf (outputFile, "\tloadb\t[r11+%s],%s\n", reg, reg);
  134.     }
  135.   } else if (src->op == GLOBAL) {
  136.     fprintf (outputFile, "\tset\t%s,%s\n", ((VarDecl *) src)->id->chars, reg);
  137.     fprintf (outputFile, "\tloadb\t[%s],%s\n", reg, reg);
  138.   } else if (src->op == CHAR_CONST) {
  139.     i = ((IntConst *) src)->ivalue;
  140.     fprintf (outputFile, "\tmov\t%d,%s\n", i, reg);
  141.   } else if (src->op == BOOL_CONST) {
  142.     i = ((BoolConst *) src)->ivalue;
  143.     fprintf (outputFile, "\tmov\t%d,%s\n", i, reg);
  144.   } else {
  145.     printf ("\nsrc->op = %s\n", symbolName (src->op));
  146.     programLogicError ("Unknown node in getIntoReg1");
  147.   }
  148. }
  149.  
  150.  
  151.  
  152. // getIntoReg8 (src, freg1, reg2)
  153. //
  154. // This routine generates the code necessary to get the "src" into "freg1", using
  155. // "reg2" if necessary.  It moves the 8 byte of data into the floating reg "freg1".
  156. //
  157. // "src" should be:
  158. //      LOCAL
  159. //      PARAMETER
  160. //      GLOBAL
  161. //      CLASS_FIELD
  162. //      DOUBLE_CONST
  163. //
  164. void getIntoReg8 (AstNode * src, char * freg1, char * reg2) {
  165.   int i;
  166.   DoubleConst * doubleConst;
  167.   if ((src->op == LOCAL) || (src->op == PARAMETER)) {
  168.     i = ((VarDecl *) src)->offset;
  169.     if (within16Bits (i)) {
  170.       fprintf (outputFile, "\tfload\t[r14+%d],%s\n", i, freg1);
  171.     } else {
  172.       // printf ("16-BIT OVERFLOW IN VARIABLE5: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  173.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  174.       fprintf (outputFile, "\tfload\t[r14+%s],%s\n", reg2, freg1);
  175.     }
  176.   } else if (src->op == CLASS_FIELD) {
  177.     i = ((VarDecl *) src)->offset;
  178.     if (within16Bits (i)) {
  179.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg2);
  180.       fprintf (outputFile, "\tfload\t[%s+%d],%s\n", reg2, i, freg1);
  181.     } else {
  182.       // printf ("16-BIT OVERFLOW IN VARIABLE6: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  183.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  184.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  185.       fprintf (outputFile, "\tfload\t[r11+%s],%s\n", reg2, freg1);
  186.     }
  187.   } else if (src->op == GLOBAL) {
  188.     fprintf (outputFile, "\tset\t%s,%s\n", ((VarDecl *) src)->id->chars, reg2);
  189.     fprintf (outputFile, "\tfload\t[%s],%s\n", reg2, freg1);
  190.   } else if (src->op == DOUBLE_CONST) {
  191.     doubleConst = (DoubleConst *) src;
  192.     fprintf (outputFile, "\tset\t%s,%s\n", doubleConst->nameOfConstant, reg2);
  193.     fprintf (outputFile, "\tfload\t[%s],%s\n", reg2, freg1);
  194.   } else {
  195.     printf ("\nsrc->op = %s\n", symbolName (src->op));
  196.     programLogicError ("Unknown node in getIntoReg8");
  197.   }
  198. }
  199.  
  200.  
  201.  
  202. // getAddrOfVarIntoReg (src, reg1)
  203. //
  204. // This routine generates the code necessary to get the address of "src" into
  205. // "reg1".  The "src" may be:
  206. //      LOCAL
  207. //      PARAMETER
  208. //      GLOBAL
  209. //      CLASS_FIELD
  210. //
  211. void getAddrOfVarIntoReg (AstNode * src, char * reg1) {
  212.   int i;
  213.   if ((src->op == LOCAL) || (src->op == PARAMETER)) {
  214.     i = ((VarDecl *) src)->offset;
  215.     if (within16Bits (i)) {
  216.       fprintf (outputFile, "\tadd\tr14,%d,%s\n", i, reg1);
  217.     } else {
  218.       // printf ("16-BIT OVERFLOW IN VARIABLE7: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  219.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg1);
  220.       fprintf (outputFile, "\tadd\tr14,%s,%s\n", reg1, reg1);
  221.     }
  222.   } else if (src->op == GLOBAL) {
  223.     fprintf (outputFile, "\tset\t%s,%s\n", ((VarDecl *) src)->id->chars, reg1);
  224.   } else if (src->op == CLASS_FIELD) {
  225.     i = ((VarDecl *) src)->offset;
  226.     // printf ("ClassField = %s   offset = %d\n", ((VarDecl *) src)->id->chars, i);
  227.     if (within16Bits (i)) {
  228.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg1);
  229.       fprintf (outputFile, "\tadd\t%s,%d,%s\n", reg1, i, reg1);
  230.     } else {
  231.       // printf ("16-BIT OVERFLOW IN VARIABLE8: %s, offset = %d\n", ((VarDecl *) src)->id->chars, i);
  232.       fprintf (outputFile, "\tset\t%d,r11\n", i);
  233.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg1);
  234.       fprintf (outputFile, "\tadd\t%s,r11,%s\n", reg1, reg1);
  235.     }
  236.   } else {
  237.     printf ("\nsrc->op = %s\n", symbolName (src->op));
  238.     programLogicError ("Unknown node in getAddrOfVarIntoReg");
  239.   }
  240. }
  241.  
  242.  
  243.  
  244. // storeFromReg4 (dest, reg1, reg2)
  245. //
  246. // This routine generates the code necessary to move a word from "reg1" to
  247. // the "dest" location, using "reg2" if necessary.
  248. //
  249. // "dest" should be:
  250. //      LOCAL
  251. //      PARAMETER
  252. //      GLOBAL
  253. //      CLASS_FIELD
  254. //
  255. void storeFromReg4 (VarDecl * dest, char * reg1, char * reg2) {
  256.   int i;
  257.   if ((dest->op == LOCAL) || (dest->op == PARAMETER)) {
  258.     i = dest->offset;
  259.     if (within16Bits (i)) {
  260.       fprintf (outputFile, "\tstore\t%s,[r14+%d]\n", reg1, i);
  261.     } else {
  262.       // printf ("16-BIT OVERFLOW IN VARIABLE9: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  263.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  264.       fprintf (outputFile, "\tstore\t%s,[r14+%s]\n", reg1, reg2);
  265.     }
  266.   } else if (dest->op == CLASS_FIELD) {
  267.     i = dest->offset;
  268.     if (within16Bits (i)) {
  269.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg2);
  270.       fprintf (outputFile, "\tstore\t%s,[%s+%d]\n", reg1, reg2, i);
  271.     } else {
  272.       // printf ("16-BIT OVERFLOW IN VARIABLE10: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  273.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  274.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  275.       fprintf (outputFile, "\tstore\t%s,[r11+%s]\n", reg1, reg2);
  276.     }
  277.   } else if (dest->op == GLOBAL) {
  278.     fprintf (outputFile, "\tset\t%s,%s\n", dest->id->chars, reg2);
  279.     fprintf (outputFile, "\tstore\t%s,[%s]\n", reg1, reg2);
  280.   } else {
  281.     printf ("\ndest->op = %s\n", symbolName (dest->op));
  282.     programLogicError ("Unknown node in storeFromReg4");
  283.   }
  284. }
  285.  
  286.  
  287.  
  288. // storeFromReg1 (dest, reg1, reg2)
  289. //
  290. // This routine generates the code necessary to move 1 byte from "reg1" to
  291. // the "dest" location, using "reg2" if necessary.
  292. //
  293. // "dest" should be:
  294. //      LOCAL
  295. //      PARAMETER
  296. //      GLOBAL
  297. //      CLASS_FIELD
  298. //
  299. void storeFromReg1 (VarDecl * dest, char * reg1, char * reg2) {
  300.   int i;
  301.   if ((dest->op == LOCAL) || (dest->op == PARAMETER)) {
  302.     i = dest->offset;
  303.     if (within16Bits (i)) {
  304.       fprintf (outputFile, "\tstoreb\t%s,[r14+%d]\n", reg1, i);
  305.     } else {
  306.       // printf ("16-BIT OVERFLOW IN VARIABLE11: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  307.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  308.       fprintf (outputFile, "\tstoreb\t%s,[r14+%s]\n", reg1, reg2);
  309.     }
  310.   } else if (dest->op == CLASS_FIELD) {
  311.     i = dest->offset;
  312.     if (within16Bits (i)) {
  313.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg2);
  314.       fprintf (outputFile, "\tstoreb\t%s,[%s+%d]\n", reg1, reg2, i);
  315.     } else {
  316.       // printf ("16-BIT OVERFLOW IN VARIABLE12: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  317.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  318.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  319.       fprintf (outputFile, "\tstoreb\t%s,[r11+%s]\n", reg1, reg2);
  320.     }
  321.   } else if (dest->op == GLOBAL) {
  322.     fprintf (outputFile, "\tset\t%s,%s\n", dest->id->chars, reg2);
  323.     fprintf (outputFile, "\tstoreb\t%s,[%s]\n", reg1, reg2);
  324.   } else {
  325.     printf ("\ndest->op = %s\n", symbolName (dest->op));
  326.     programLogicError ("Unknown node in storeFromReg1");
  327.   }
  328. }
  329.  
  330.  
  331.  
  332. // storeFromReg8 (dest, reg1, reg2)
  333. //
  334. // This routine generates the code necessary to move 8 bytes from "freg1" to
  335. // the "dest" location, using "reg2" if necessary.
  336. //
  337. // "dest" should be:
  338. //      LOCAL
  339. //      PARAMETER
  340. //      GLOBAL
  341. //      CLASS_FIELD
  342. //
  343. void storeFromReg8 (VarDecl * dest, char * freg1, char * reg2) {
  344.   int i;
  345.   if ((dest->op == LOCAL) || (dest->op == PARAMETER)) {
  346.     i = dest->offset;
  347.     if (within16Bits (i)) {
  348.       fprintf (outputFile, "\tfstore\t%s,[r14+%d]\n", freg1, i);
  349.     } else {
  350.       // printf ("16-BIT OVERFLOW IN VARIABLE13: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  351.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  352.       fprintf (outputFile, "\tfstore\t%s,[r14+%s]\n", freg1, reg2);
  353.     }
  354.   } else if (dest->op == CLASS_FIELD) {
  355.     i = dest->offset;
  356.     if (within16Bits (i)) {
  357.       fprintf (outputFile, "\tload\t[r14+8],%s\n", reg2);
  358.       fprintf (outputFile, "\tfstore\t%s,[%s+%d]\n", freg1, reg2, i);
  359.     } else {
  360.       // printf ("16-BIT OVERFLOW IN VARIABLE14: %s, offset = %d\n", ((VarDecl *) dest)->id->chars, i);
  361.       fprintf (outputFile, "\tload\t[r14+8],r11\n");
  362.       fprintf (outputFile, "\tset\t%d,%s\n", i, reg2);
  363.       fprintf (outputFile, "\tfstore\t%s,[r11+%s]\n", freg1, reg2);
  364.     }
  365.   } else if (dest->op == GLOBAL) {
  366.     fprintf (outputFile, "\tset\t%s,%s\n", dest->id->chars, reg2);
  367.     fprintf (outputFile, "\tfstore\t%s,[%s]\n", freg1, reg2);
  368.   } else {
  369.     printf ("\ndest->op = %s\n", symbolName (dest->op));
  370.     programLogicError ("Unknown node in storeFromReg8");
  371.   }
  372. }
  373.  
  374.  
  375.  
  376. // overflowTest ()
  377. //
  378. // This routine generates:
  379. //       bvs   _runtimeErrorOverflow
  380. //
  381. void overflowTest () {
  382.     fprintf (outputFile, "\tbvs\t_runtimeErrorOverflow\n");
  383. }
  384.  
  385.  
  386.  
  387. //
  388. // printIR
  389. //
  390. // This routine runs through the IR statements and prints them.
  391. //
  392. void printIR () {
  393.     IR * inst;
  394.     for (inst = firstInstruction; inst; inst = inst->next) {
  395.       inst->print ();
  396.       // fflush (outputFile);      // Useful during debugging...
  397.     }
  398. }
  399.  
  400.  
  401.  
  402. //
  403. // printANode (node)
  404. //
  405. // This routine is passed a pointer to:
  406. //    Local
  407. //    Global
  408. //    Parameter
  409. //    ClassField
  410. //    IntConst
  411. //    DoubleConst
  412. // It prints the node into the output file.
  413. //
  414. void printANode (AstNode * node) {
  415.     double r, rval;
  416.     r = 0.0;
  417.  
  418.   if (node==NULL) {
  419.     fprintf (outputFile, "*****  NULL  *****");
  420.     // For debugging, keep going.  Later, perhaps we should just abort...
  421.     //     programLogicError ("printANode called with node == NULL");
  422.   }
  423.  
  424.   switch (node->op) {
  425.  
  426.     case INT_CONST:
  427.       fprintf (outputFile, "%d", ((IntConst *) node)->ivalue);
  428.       return;
  429.  
  430.     case DOUBLE_CONST:
  431.       rval = ((DoubleConst *) node)->rvalue;
  432.       if (rval == (-1.0) / r) {
  433.         fprintf (outputFile, "<NegativeInfinity>");
  434.       } else if (rval == (+1.0) / r) {
  435.         fprintf (outputFile, "<PositiveInfinity>");
  436.       } else if (isnan (rval)) {
  437.         fprintf (outputFile, "<Not-A-Number>");
  438.       } else if (rval == 0.0 && 1.0/rval < 0.0) {
  439.         fprintf (outputFile, "<NegativeZero>");
  440.       } else {
  441.         fprintf (outputFile, "%.16gD", rval);
  442.       }
  443.       return;
  444.  
  445.     case CHAR_CONST:
  446.       fprintf (outputFile, "%d", ((CharConst *) node)->ivalue);
  447.       return;
  448.  
  449.     case BOOL_CONST:
  450.       fprintf (outputFile, "%d", ((BoolConst *) node)->ivalue);
  451.       return;
  452.  
  453.     case GLOBAL:
  454.       printString (outputFile, ((Global *) node)->id);
  455.       return;
  456.  
  457.     case LOCAL:
  458.       printString (outputFile, ((Local *) node)->id);
  459.       return;
  460.  
  461.     case PARAMETER:
  462.       printString (outputFile, ((Parameter *) node)->id);
  463.       return;
  464.  
  465.     case CLASS_FIELD:
  466.       printString (outputFile, ((ClassField *) node)->id);
  467.       return;
  468.  
  469.     default:
  470.       printf ("\nnode->op = %s\n", symbolName (node->op));
  471.       programLogicError ("Unkown op in printANode");
  472.  
  473.   }
  474.  
  475.   programLogicError ("All cases should have returned in printANode");
  476.   return;
  477.  
  478. }
  479.  
  480.  
  481.  
  482. //----------  IR  ----------
  483.  
  484. void IR::print () {
  485.   programLogicError ("Method 'print' should have been overridden (IR)");
  486. }
  487.  
  488. void linkIR (IR * inst) {
  489.   // if (inst->next != NULL) {
  490.   //   programLogicError ("Problems in linkIR (1)");
  491.   // }
  492.   if (firstInstruction == NULL) {
  493.     firstInstruction = inst;
  494.     // if (lastInstruction != NULL) {
  495.     //   programLogicError ("Problems in linkIR (2)");
  496.     // }
  497.   }
  498.   if (lastInstruction != NULL) {
  499.     lastInstruction->next = inst;
  500.   }
  501.   lastInstruction = inst;
  502. }
  503.  
  504.  
  505.  
  506. //----------  Comment  ----------
  507.  
  508. void Comment::print () {
  509.   fprintf (outputFile, "! %s\n", str);
  510. }
  511.  
  512. void IRComment (char * str) {
  513.   linkIR (new Comment (str));
  514. }
  515.  
  516.  
  517.  
  518. //----------  Comment3  ----------
  519.  
  520. void Comment3::print () {
  521.   fprintf (outputFile, "! %s%d...\n", str, ivalue);
  522. }
  523.  
  524. void IRComment3 (char * str, int i) {
  525.   linkIR (new Comment3 (str, i));
  526. }
  527.  
  528.  
  529.  
  530. //----------  Goto  ----------
  531. void Goto::print () {
  532.   Label * lab;
  533.   // If we happen to be jumping to the very next IR instruction...
  534.   if (next && next->op == OPLabel) {
  535.     lab = (Label *) this->next;
  536.     if (lab->label == label) {
  537.       fprintf (outputFile, "!", label);   // Comment the jump out
  538.     }
  539.   }
  540.   // Else generate a "jmp" instruction...
  541.   fprintf (outputFile, "\tjmp\t%s\n", label);
  542. }
  543.  
  544. void IRGoto (char * label) {
  545.   linkIR (new Goto (label));
  546. }
  547.  
  548.  
  549.  
  550. //----------  Goto2  ----------
  551. void Goto2::print () {
  552.   fprintf (outputFile, "\tjmp\t%s\t! %d:\t%s\n", label, offset, selector);
  553. }
  554.  
  555. void IRGoto2 (char * label, int offset, char * selector) {
  556.   linkIR (new Goto2 (label, offset, selector));
  557. }
  558.  
  559.  
  560.  
  561. //----------  Label  ----------
  562.  
  563. void Label::print () {
  564.   fprintf (outputFile, "%s:\n", label);
  565. }
  566.  
  567. void IRLabel (char * label) {
  568.   linkIR (new Label (label));
  569. }
  570.  
  571.  
  572.  
  573. //----------  Import  ----------
  574.  
  575. void Import::print () {
  576.   fprintf (outputFile, "\t.import\t%s\n", name);
  577. }
  578.  
  579. void IRImport (char * nam) {
  580.   linkIR (new Import (nam));
  581. }
  582.  
  583.  
  584.  
  585. //----------  Export  ----------
  586.  
  587. void Export::print () {
  588.   fprintf (outputFile, "\t.export\t%s\n", name);
  589. }
  590.  
  591. void IRExport (char * nam) {
  592.   linkIR (new Export (nam));
  593. }
  594.  
  595.  
  596.  
  597. //----------  Data  ----------
  598.  
  599. void Data::print () {
  600.   fprintf (outputFile, "\t.data\n");
  601. }
  602.  
  603. void IRData () {
  604.   linkIR (new Data ());
  605. }
  606.  
  607.  
  608.  
  609. //----------  Text  ----------
  610.  
  611. void Text::print () {
  612.   fprintf (outputFile, "\t.text\n");
  613. }
  614.  
  615. void IRText () {
  616.   linkIR (new Text ());
  617. }
  618.  
  619.  
  620.  
  621. //----------  Align  ----------
  622.  
  623. void Align::print () {
  624.   fprintf (outputFile, "\t.align\n");
  625. }
  626.  
  627. void IRAlign () {
  628.   linkIR (new Align ());
  629. }
  630.  
  631.  
  632.  
  633. //----------  Skip  ----------
  634.  
  635. void Skip::print () {
  636.   fprintf (outputFile, "\t.skip\t%d\n", byteCount);
  637. }
  638.  
  639. void IRSkip (int i) {
  640.   linkIR (new Skip (i));
  641. }
  642.  
  643.  
  644.  
  645. //----------  Byte  ----------
  646.  
  647. void Byte::print () {
  648.   fprintf (outputFile, "\t.byte\t%d", byteValue);
  649.   if (byteValue >= 32 && byteValue <= 126) {
  650.     fprintf (outputFile, "\t\t\t! '");
  651.     printChar (outputFile, byteValue);
  652.     fprintf (outputFile, "'\n");
  653.   } else if (byteValue <= 9) {
  654.     fprintf (outputFile, "\n");
  655.   } else {
  656.     int i = intToHexChar ((byteValue >>4) & 0x0000000f);
  657.     int j = intToHexChar (byteValue & 0x0000000f);
  658.     fprintf (outputFile, "\t\t\t! (%c%c in hex)\n", i, j);
  659.   }
  660. }
  661.  
  662. void IRByte (int i) {
  663.   linkIR (new Byte (i));
  664. }
  665.  
  666.  
  667.  
  668. //----------  Word  ----------
  669.  
  670. void Word::print () {
  671.   if (wordValue == 0) {
  672.     fprintf (outputFile, "\t.word\t0\n");
  673.   } else {
  674.     fprintf (outputFile, "\t.word\t0x%08x\t\t! decimal value = %d\n",
  675.                          wordValue, wordValue);
  676.   }
  677. }
  678.  
  679. void IRWord (int i) {
  680.   linkIR (new Word (i));
  681. }
  682.  
  683.  
  684.  
  685. //----------  Word2  ----------
  686.  
  687. void Word2::print () {
  688.   fprintf (outputFile, "\t.word\t%s\n", symbol);
  689. }
  690.  
  691. void IRWord2 (char * s) {
  692.   linkIR (new Word2 (s));
  693. }
  694.  
  695.  
  696.  
  697. //----------  Word3  ----------
  698.  
  699. void Word3::print () {
  700.   fprintf (outputFile, "\t.word\t%d\t\t! %s\n", wordValue, comment);
  701. }
  702.  
  703. void IRWord3 (int i, char * s) {
  704.   linkIR (new Word3 (i, s));
  705. }
  706.  
  707.  
  708.  
  709. //----------  LoadAddr  ----------
  710.  
  711. void LoadAddr::print () {
  712.   fprintf (outputFile, "!   ");
  713.   printANode (dest);
  714.   fprintf (outputFile, " = %s\n", stringName);
  715.   fprintf (outputFile, "\tset\t%s,r1\n", stringName);
  716.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  717. }
  718.  
  719. void IRLoadAddr (AstNode * d, char * s) {
  720.   linkIR (new LoadAddr (d, s));
  721. }
  722.  
  723.  
  724.  
  725. //----------  LoadAddrIndirect  ----------
  726.  
  727. void LoadAddrIndirect::print () {
  728.   fprintf (outputFile, "!   *");
  729.   printANode (dest);
  730.   fprintf (outputFile, " = %s\n", stringName);
  731.   fprintf (outputFile, "\tset\t%s,r1\n", stringName);
  732.   getIntoReg4 (dest, "r2");
  733.   fprintf (outputFile, "\tstore\tr1,[r2]\n");
  734.  
  735.  
  736. }
  737.  
  738. void IRLoadAddrIndirect (AstNode * d, char * s) {
  739.   linkIR (new LoadAddrIndirect (d, s));
  740. }
  741.  
  742.  
  743.  
  744. //----------  LoadAddr2  ----------
  745.  
  746. void LoadAddr2::print () {
  747.   fprintf (outputFile, "!   ");
  748.   printANode (dest);
  749.   fprintf (outputFile, " = &");
  750.   printANode (src);
  751.   fprintf (outputFile, "\n");
  752.   getAddrOfVarIntoReg (src, "r1");
  753.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  754. }
  755.  
  756. void IRLoadAddr2 (VarDecl * d, AstNode * s) {
  757.   linkIR (new LoadAddr2 (d, s));
  758. }
  759.  
  760.  
  761.  
  762. //----------  LoadAddrWithIncr  ----------
  763.  
  764. void LoadAddrWithIncr::print () {
  765.   fprintf (outputFile, "!   ");
  766.   printANode (dest);
  767.   fprintf (outputFile, " = ");
  768.   printANode (src);
  769.   fprintf (outputFile, ".%s\n", fieldInit->id->chars);
  770.   getAddrOfVarIntoReg (src, "r1");
  771.   if (within16Bits (fieldInit->offset)) {
  772.     fprintf (outputFile, "\tadd\tr1,%d,r1\n", fieldInit->offset);
  773.   } else {
  774.     fprintf (outputFile, "\tset\t0x%08x,r1\n", fieldInit->offset);
  775.     fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  776.   }
  777.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  778. }
  779.  
  780. void IRLoadAddrWithIncr (VarDecl * dest, AstNode * src, FieldInit * fieldInit) {
  781.   linkIR (new LoadAddrWithIncr (dest, src, fieldInit));
  782. }
  783.  
  784.  
  785.  
  786. //----------  LoadAddrWithIncr2  ----------
  787.  
  788. void LoadAddrWithIncr2::print () {
  789.   fprintf (outputFile, "!   ");
  790.   printANode (dest);
  791.   fprintf (outputFile, " = (*");
  792.   printANode (src);
  793.   fprintf (outputFile, ") . %s\n", fieldInit->id->chars);
  794.   getIntoReg4 (src, "r1");
  795.   if (within16Bits (fieldInit->offset)) {
  796.     fprintf (outputFile, "\tadd\tr1,%d,r1\n", fieldInit->offset);
  797.   } else {
  798.     fprintf (outputFile, "\tset\t0x%08x,r1\n", fieldInit->offset);
  799.     fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  800.   }
  801.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  802. }
  803.  
  804. void IRLoadAddrWithIncr2 (VarDecl * d, AstNode * s, FieldInit * f) {
  805.   linkIR (new LoadAddrWithIncr2 (d, s, f));
  806. }
  807.  
  808.  
  809.  
  810. //----------  Double  ----------
  811.  
  812. void Double::print () {
  813.   int * p1, * p2;
  814.   double r = 0.0;
  815. #ifdef BLITZ_HOST_IS_LITTLE_ENDIAN
  816.   p2 = (int *) &doubleValue;
  817.   p1 = p2+1;
  818. #else
  819.   p1 = (int *) &doubleValue;
  820.   p2 = p1+1;
  821. #endif
  822.   fprintf (outputFile, "\t.word\t0x%08x\t\t! double value = ", *p1);
  823.   if (doubleValue == (-1.0) / r) {
  824.     fprintf (outputFile, "NegInf\n");
  825.   } else if (doubleValue == (+1.0) / r) {
  826.     fprintf (outputFile, "PosInf\n");
  827.   } else if (isnan (doubleValue)) {
  828.     fprintf (outputFile, "NaN\n");
  829.   } else if (doubleValue == 0.0 && 1.0/doubleValue < 0.0) {
  830.     fprintf (outputFile, "NegZero\n");
  831.   } else {
  832.     fprintf (outputFile, "%.15g\n", doubleValue);
  833.   }
  834.   fprintf (outputFile, "\t.word\t0x%08x\t\t! .\n", *p2);
  835. }
  836.  
  837. void IRDouble (double r) {
  838.   linkIR (new Double (r));
  839. }
  840.  
  841.  
  842.  
  843. //----------  Call  ----------
  844.  
  845. void Call::print () {
  846.   fprintf (outputFile, "\tcall\t%s\n", name);
  847. }
  848.  
  849. void IRCall (char * n) {
  850.   linkIR (new Call (n));
  851. }
  852.  
  853.  
  854.  
  855. //----------  CallIndirect  ----------
  856.  
  857. void CallIndirect::print () {
  858.   getIntoReg4 (varDesc, "r1");
  859.   fprintf (outputFile, "\tcmp\tr1,0\n");
  860.   fprintf (outputFile, "\tbe\t_runtimeErrorNullPointerDuringCall\n");
  861.   fprintf (outputFile, "\tcall\tr1\n");
  862. }
  863.  
  864. void IRCallIndirect (VarDecl * vd) {
  865.   linkIR (new CallIndirect (vd));
  866. }
  867.  
  868.  
  869.  
  870. //----------  Debug  ----------
  871.  
  872. void Debug::print () {
  873.   fprintf (outputFile, "\tdebug\n");
  874. }
  875.  
  876. void IRDebug () {
  877.   linkIR (new Debug ());
  878. }
  879.  
  880.  
  881.  
  882. //----------  Halt  ----------
  883.  
  884. void Halt::print () {
  885.   fprintf (outputFile, "\thalt\n");
  886. }
  887.  
  888. void IRHalt () {
  889.   linkIR (new Halt ());
  890. }
  891.  
  892.  
  893.  
  894. //----------  SetLineNumber  ----------
  895.  
  896. void SetLineNumber::print () {
  897.   if (within16Bits (lineNumber)) {
  898.     fprintf (outputFile, "\tmov\t%d,r13\t\t! source line %d\n",
  899.              lineNumber, lineNumber);
  900.   } else {
  901.     fprintf (outputFile, "\tset\t%d,r13\t\t! source line %d\n",
  902.              lineNumber, lineNumber);
  903.   }
  904.   fprintf (outputFile, "\tmov\t\"\\0\\0%s\",r10\n", stmtCode);
  905.  
  906. }
  907.  
  908. void IRSetLineNumber (int i, char * s) {
  909.   linkIR (new SetLineNumber (i, s));
  910. }
  911.  
  912.  
  913.  
  914. //----------  FunctionEntry  ----------
  915.  
  916. void FunctionEntry::print () {
  917.   int i;
  918.   char * label;
  919.  
  920.   fprintf (outputFile, "\tpush\tr14\n");
  921.   fprintf (outputFile, "\tmov\tr15,r14\n");
  922.   fprintf (outputFile, "\tpush\tr13\n");
  923.   fprintf (outputFile, "\tset\t%s,r1\n",
  924.            appendStrings ("_RoutineDescriptor_",fun->newName,""));
  925.   fprintf (outputFile, "\tpush\tr1\n");
  926.   if (fun->frameSize % 4 != 0) {
  927.     programLogicError ("fun->frameSize should be a multiple of 4");
  928.   }
  929.  
  930.   // Generate code to zero-out the var & arg portion of this frame...
  931.   i = fun->frameSize / 4;
  932.   if (i > 0) {
  933.     label = newLabel ();
  934.     if (within16Bits (i)) {
  935.       fprintf (outputFile, "\tmov\t%d,r1\n", i);
  936.     } else {
  937.       // printf ("16-bit OVERFLOW IN FUNCTION: %s,  i = %d\n", fun->id->chars, i);
  938.       fprintf (outputFile, "\tset\t%d,r1\n", i);
  939.     }
  940.     fprintf (outputFile, "%s:\n", label);
  941.     fprintf (outputFile, "\tpush\tr0\n");
  942.     fprintf (outputFile, "\tsub\tr1,1,r1\n");
  943.     fprintf (outputFile, "\tbne\t%s\n", label);
  944.   }
  945.  
  946. }
  947.  
  948. void IRFunctionEntry (Function * fun) {
  949.   linkIR (new FunctionEntry (fun));
  950. }
  951.  
  952.  
  953.  
  954. //----------  FunctionReturn  ----------
  955.  
  956. void FunctionReturn::print () {
  957.   int i = fun->frameSize+4;
  958.   if (within16Bits (i)) {
  959.     fprintf (outputFile, "\tadd\tr15,%d,r15\n", i);
  960.   } else {
  961.     // printf ("16-bit OVERFLOW IN FUNCTION RETURN: %s   i=%d\n", fun->id->chars, i);
  962.     fprintf (outputFile, "\tset\t%d,r1\n", i);
  963.     fprintf (outputFile, "\tadd\tr15,r1,r15\n");
  964.   }
  965.   fprintf (outputFile, "\tpop\tr13\n");
  966.   fprintf (outputFile, "\tpop\tr14\n");
  967.   fprintf (outputFile, "\tret\n");
  968. }
  969.  
  970. void IRFunctionReturn (Function * fun) {
  971.   linkIR (new FunctionReturn (fun));
  972. }
  973.  
  974.  
  975.  
  976. //----------  MethodEntry  ----------
  977.  
  978. void MethodEntry::print () {
  979.   int i;
  980.   char * label;
  981.  
  982.   fprintf (outputFile, "\tpush\tr14\n");
  983.   fprintf (outputFile, "\tmov\tr15,r14\n");
  984.   fprintf (outputFile, "\tpush\tr13\n");
  985.   fprintf (outputFile, "\tset\t%s,r1\n",
  986.            appendStrings ("_RoutineDescriptor_",meth->newName,""));
  987.   fprintf (outputFile, "\tpush\tr1\n");
  988.   if (meth->frameSize % 4 != 0) {
  989.     programLogicError ("meth->frameSize should be a multiple of 4");
  990.   }
  991.  
  992.   // Generate code to zero-out the var & arg portion of this frame...
  993.   i = meth->frameSize / 4;
  994.   if (i > 0) {
  995.     label = newLabel ();
  996.     if (within16Bits (i)) {
  997.       fprintf (outputFile, "\tmov\t%d,r1\n", i);
  998.     } else {
  999.       // printf ("16-bit OVERFLOW IN METHOD: %s,  i = %d\n", meth->selector->chars, i);
  1000.       fprintf (outputFile, "\tset\t%d,r1\n", i);
  1001.     }
  1002.     fprintf (outputFile, "%s:\n", label);
  1003.     fprintf (outputFile, "\tpush\tr0\n");
  1004.     fprintf (outputFile, "\tsub\tr1,1,r1\n");
  1005.     fprintf (outputFile, "\tbne\t%s\n", label);
  1006.   }
  1007.  
  1008. }
  1009.  
  1010. void IRMethodEntry (Method * meth) {
  1011.   linkIR (new MethodEntry (meth));
  1012. }
  1013.  
  1014.  
  1015.  
  1016. //----------  MethodReturn  ----------
  1017.  
  1018. void MethodReturn::print () {
  1019.   int i = meth->frameSize+4;
  1020.   if (within16Bits (i)) {
  1021.     fprintf (outputFile, "\tadd\tr15,%d,r15\n", i);
  1022.   } else {
  1023.     // printf ("16-bit OVERFLOW IN METHOD RETURN: %s   i=%d\n", meth->selector->chars, i);
  1024.     fprintf (outputFile, "\tset\t%d,r1\n", i);
  1025.     fprintf (outputFile, "\tadd\tr15,r1,r15\n");
  1026.   }
  1027.   fprintf (outputFile, "\tpop\tr13\n");
  1028.   fprintf (outputFile, "\tpop\tr14\n");
  1029.   fprintf (outputFile, "\tret\n");
  1030. }
  1031.  
  1032. void IRMethodReturn (Method * meth) {
  1033.   linkIR (new MethodReturn (meth));
  1034. }
  1035.  
  1036.  
  1037.  
  1038. //----------  CheckVersion  ----------
  1039.  
  1040. void CheckVersion::print () {
  1041.   fprintf (outputFile, "!\n");
  1042.   fprintf (outputFile, "! CheckVersion\n");
  1043.   fprintf (outputFile, "!\n");
  1044.   fprintf (outputFile, "!     This routine is passed:\n");
  1045.   fprintf (outputFile, "!       r2 = ptr to the name of the 'using' package\n");
  1046.   fprintf (outputFile, "!       r3 = the expected hashVal for 'used' package (myPackage)\n");
  1047.   fprintf (outputFile, "!     It prints an error message if the expected hashVal is not correct\n");
  1048.   fprintf (outputFile, "!     It then checks all the packages that 'myPackage' uses.\n");
  1049.   fprintf (outputFile, "!\n");
  1050.   fprintf (outputFile, "!     This routine returns:\n");
  1051.   fprintf (outputFile, "!       r1:  0=No problems, 1=Problems\n");
  1052.   fprintf (outputFile, "!\n");
  1053.   fprintf (outputFile, "!     Registers modified: r1-r4\n");
  1054.   fprintf (outputFile, "!\n");
  1055.  
  1056.   fprintf (outputFile, "_CheckVersion%s:\n", mySaniName);
  1057.   fprintf (outputFile, "\t.export\t_CheckVersion%s\n", mySaniName);
  1058.  
  1059. //  fprintf (outputFile, "\tset\t_CVMess7,r1\n");
  1060. //  fprintf (outputFile, "\tcall\t_putString\n");
  1061.  
  1062. //  fprintf (outputFile, "\tset\t_packageName,r1\t\t! print 'Checking this package name'\n");
  1063. //  fprintf (outputFile, "\tcall\t_putString\n");
  1064.  
  1065. //  fprintf (outputFile, "\tset\t_CVMess8,r1\n");
  1066. //  fprintf (outputFile, "\tcall\t_putString\n");
  1067. //  fprintf (outputFile, "\tcall\t_flush\n");
  1068.  
  1069.   fprintf (outputFile, "\tset\t0x%08x,r4\t\t! myHashVal = %d\n", myHashVal, myHashVal);
  1070.   fprintf (outputFile, "\tcmp\tr3,r4\n");
  1071.   fprintf (outputFile, "\tbe\t%s\n", label1);
  1072.  
  1073.   fprintf (outputFile, "\tset\t_CVMess1,r1\n");
  1074.   fprintf (outputFile, "\tcall\t_putString\n");
  1075.  
  1076.   fprintf (outputFile, "\tmov\tr2,r1\t\t\t! print using package\n");
  1077.   fprintf (outputFile, "\tcall\t_putString\n");
  1078.  
  1079.   fprintf (outputFile, "\tset\t_CVMess2,r1\n");
  1080.   fprintf (outputFile, "\tcall\t_putString\n");
  1081.  
  1082.   fprintf (outputFile, "\tset\t_packageName,r1\t\t! print myPackage\n");
  1083.   fprintf (outputFile, "\tcall\t_putString\n");
  1084.  
  1085.   fprintf (outputFile, "\tset\t_CVMess3,r1\n");
  1086.   fprintf (outputFile, "\tcall\t_putString\n");
  1087.  
  1088.   fprintf (outputFile, "\tset\t_packageName,r1\t\t! print myPackage\n");
  1089.   fprintf (outputFile, "\tcall\t_putString\n");
  1090.  
  1091.   fprintf (outputFile, "\tset\t_CVMess4,r1\n");
  1092.   fprintf (outputFile, "\tcall\t_putString\n");
  1093.  
  1094.   fprintf (outputFile, "\tmov\tr2,r1\t\t\t! print using package\n");
  1095.   fprintf (outputFile, "\tcall\t_putString\n");
  1096.  
  1097.   fprintf (outputFile, "\tset\t_CVMess5,r1\n");
  1098.   fprintf (outputFile, "\tcall\t_putString\n");
  1099.  
  1100.   fprintf (outputFile, "\tset\t_packageName,r1\t\t! print myPackage\n");
  1101.   fprintf (outputFile, "\tcall\t_putString\n");
  1102.  
  1103.   fprintf (outputFile, "\tset\t_CVMess6,r1\n");
  1104.   fprintf (outputFile, "\tcall\t_putString\n");
  1105.   // fprintf (outputFile, "\tcall\t_flush\n");
  1106.  
  1107.   fprintf (outputFile, "\tmov\t1,r1\n");
  1108.   fprintf (outputFile, "\tret\t\n");
  1109.  
  1110.   fprintf (outputFile, "%s:\n", label1);
  1111.   fprintf (outputFile, "\tmov\t0,r1\n");
  1112. }
  1113.  
  1114. void IRCheckVersion (char * mySaniName, int myHashVal, char * label1) {
  1115.   linkIR (new CheckVersion (mySaniName, myHashVal, label1));
  1116. }
  1117.  
  1118.  
  1119.  
  1120. //----------  CallCheckVersion  ----------
  1121.  
  1122. void CallCheckVersion::print () {
  1123.  
  1124.   fprintf (outputFile, "! Make sure %s has hash value 0x%08x (decimal %d)\n",
  1125.                         theirSaniName, theirHashVal, theirHashVal);
  1126.   fprintf (outputFile, "\tset\t_packageName,r2\n");
  1127.   fprintf (outputFile, "\tset\t0x%08x,r3\n", theirHashVal);
  1128.   fprintf (outputFile, "\tcall\t_CheckVersion%s\n", theirSaniName);
  1129.   fprintf (outputFile, "\t.import\t_CheckVersion%s\n", theirSaniName);
  1130.   fprintf (outputFile, "\tcmp\tr1,0\n");
  1131.   fprintf (outputFile, "\tbne\t%s\n", label2);
  1132. }
  1133.  
  1134. void IRCallCheckVersion (char * theirSaniName, int theirHashVal, char * label2) {
  1135.   linkIR (new CallCheckVersion (theirSaniName, theirHashVal, label2));
  1136. }
  1137.  
  1138.  
  1139.  
  1140. //----------  EndCheckVersion  ----------
  1141.  
  1142. void EndCheckVersion::print () {
  1143.   fprintf (outputFile, "%s:\n", label2);
  1144.   fprintf (outputFile, "\tret\n");
  1145.   fprintf (outputFile, "_CVMess1:\t.ascii\t\"\\nVERSION CONSISTENCY ERROR: Package '\\0\"\n");
  1146.   fprintf (outputFile, "_CVMess2:\t.ascii\t\"' uses package '\\0\"\n");
  1147.   fprintf (outputFile, "_CVMess3:\t.ascii\t\"'.  Whenever a header file is modified, all packages that use that package (directly or indirectly) must be recompiled.  The header file for '\\0\"\n");
  1148.   fprintf (outputFile, "_CVMess4:\t.ascii\t\"' has been changed since '\\0\"\n");
  1149.   fprintf (outputFile, "_CVMess5:\t.ascii\t\"' was compiled last.  Please recompile all packages that depend on '\\0\"\n");
  1150.   fprintf (outputFile, "_CVMess6:\t.ascii\t\"'.\\n\\n\\0\"\n");
  1151. //  fprintf (outputFile, "_CVMess7:\t.ascii\t\"Checking \\0\"\n");
  1152. //  fprintf (outputFile, "_CVMess8:\t.ascii\t\"...\\n\\0\"\n");
  1153.   fprintf (outputFile, "\t.align\n");
  1154. }
  1155.  
  1156. void IREndCheckVersion (char * label2) {
  1157.   linkIR (new EndCheckVersion (label2));
  1158. }
  1159.  
  1160.  
  1161.  
  1162. //----------  StartCheckVersion  ----------
  1163.  
  1164. void StartCheckVersion::print () {
  1165.  
  1166.   fprintf (outputFile, "\tset\t_packageName,r2\t\t! Get CheckVersion started\n");
  1167.   fprintf (outputFile, "\tset\t0x%08x,r3\t\t! .  hashVal = %d\n",
  1168.                               myHashVal, myHashVal);
  1169.   fprintf (outputFile, "\tcall\t_CheckVersion%s\t! .\n", mySaniName);
  1170.   fprintf (outputFile, "\tcmp\tr1,0\t\t\t! .\n");
  1171.   fprintf (outputFile, "\tbe\t%s\t\t! .\n", continueLab);
  1172.   fprintf (outputFile, "\tret\t\t\t\t! .\n");
  1173.   fprintf (outputFile, "%s:\t\t\t\t! .\n", continueLab);
  1174. }
  1175.  
  1176. void IRStartCheckVersion (char * mySaniName, int myHashVal, char * continueLab) {
  1177.   linkIR (new StartCheckVersion (mySaniName, myHashVal, continueLab));
  1178. }
  1179.  
  1180.  
  1181.  
  1182. //----------  VarDesc1  ----------
  1183.  
  1184. void VarDesc1::print () {
  1185.   fprintf (outputFile, "\t.word\t%s\n", label);
  1186.   fprintf (outputFile, "\t.word\t%d\n", varDecl->offset);
  1187.   fprintf (outputFile, "\t.word\t%d\n", sizeInBytes);
  1188. }
  1189.  
  1190. void IRVarDesc1 (char * lab, VarDecl * vd, int sz) {
  1191.   linkIR (new VarDesc1 (lab, vd, sz));
  1192. }
  1193.  
  1194.  
  1195.  
  1196. //----------  VarDesc2  ----------
  1197.  
  1198. void VarDesc2::print () {
  1199.   fprintf (outputFile, "%s:\n", label);
  1200.   fprintf (outputFile, "\t.byte\t'%c'\n", kind);
  1201.   fprintf (outputFile, "\t.ascii\t\"%s\\0\"\n", name);
  1202.   fprintf (outputFile, "\t.align\n");
  1203. }
  1204.  
  1205. void IRVarDesc2 (char * lab, char k, char * n) {
  1206.   linkIR (new VarDesc2 (lab, k, n));
  1207. }
  1208.  
  1209.  
  1210.  
  1211. //----------  FrameSize  ----------
  1212.  
  1213. void FrameSize::print () {
  1214.   int i;
  1215.   if (funOrMeth->op == FUNCTION) {
  1216.     i = ((Function *) funOrMeth)->frameSize;
  1217.   } else if (funOrMeth->op == METHOD) {
  1218.     i = ((Method *) funOrMeth)->frameSize;
  1219.   } else {
  1220.     programLogicError ("Expecting fun or meth in IRFrameSize");
  1221.   }
  1222.   fprintf (outputFile, "\t.word\t%d\t\t! frame size = %d\n", i, i);
  1223. }
  1224.  
  1225. void IRFrameSize (AstNode * funOrMeth) {
  1226.   linkIR (new FrameSize (funOrMeth));
  1227. }
  1228.  
  1229.  
  1230.  
  1231. //----------  Assign1  ----------
  1232.  
  1233. void Assign1::print () {
  1234.   fprintf (outputFile, "!   ");
  1235.   printANode (dest);
  1236.   fprintf (outputFile, " = ");
  1237.   printANode (src);
  1238.   fprintf (outputFile, "\t\t(1 byte)\n");
  1239.   getIntoReg1 (src, "r1");
  1240.   storeFromReg1 ((VarDecl *) dest, "r1", "r2");
  1241. }
  1242.  
  1243. void IRAssign1 (AstNode * d, AstNode * s) {
  1244.   linkIR (new Assign1 (d, s));
  1245. }
  1246.  
  1247.  
  1248.  
  1249. //----------  Assign4  ----------
  1250.  
  1251. void Assign4::print () {
  1252.   fprintf (outputFile, "!   ");
  1253.   printANode (dest);
  1254.   fprintf (outputFile, " = ");
  1255.   printANode (src);
  1256.   fprintf (outputFile, "\t\t(4 bytes)\n");
  1257.   getIntoReg4 (src, "r1");
  1258.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1259. }
  1260.  
  1261. void IRAssign4 (AstNode * d, AstNode * s) {
  1262.   linkIR (new Assign4 (d, s));
  1263. }
  1264.  
  1265.  
  1266.  
  1267. //----------  Assign8  ----------
  1268.  
  1269. void Assign8::print () {
  1270.   fprintf (outputFile, "!   ");
  1271.   printANode (dest);
  1272.   fprintf (outputFile, " = ");
  1273.   printANode (src);
  1274.   fprintf (outputFile, "\t\t(8 bytes)\n");
  1275.  
  1276.   getIntoReg8 (src, "f0", "r1");
  1277.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1278. }
  1279.  
  1280. void IRAssign8 (AstNode * d, AstNode * s) {
  1281.   linkIR (new Assign8 (d, s));
  1282. }
  1283.  
  1284.  
  1285.  
  1286. //----------  Ascii  ----------
  1287.  
  1288. void Ascii::print () {
  1289.   fprintf (outputFile, "\t.ascii\t\"%s\"\n", str);
  1290. }
  1291.  
  1292. void IRAscii (char * s) {
  1293.   linkIR (new Ascii (s));
  1294. }
  1295.  
  1296.  
  1297.  
  1298. //----------  Ascii0  ----------
  1299.  
  1300. void Ascii0::print () {
  1301.   fprintf (outputFile, "\t.ascii\t\"%s\\0\"\n", str);
  1302. }
  1303.  
  1304. void IRAscii0 (char * s) {
  1305.   linkIR (new Ascii0 (s));
  1306. }
  1307.  
  1308.  
  1309.  
  1310. //----------  Ascii2  ----------
  1311.  
  1312. void Ascii2::print () {
  1313.   fprintf (outputFile, "\t.word\t%d\t\t\t! length\n", str->length);
  1314.   fprintf (outputFile, "\t.ascii\t\"");
  1315.   printString (outputFile, str);
  1316.   fprintf (outputFile, "\"\n");
  1317. }
  1318.  
  1319. void IRAscii2 (String * s) {
  1320.   linkIR (new Ascii2 (s));
  1321. }
  1322.  
  1323.  
  1324.  
  1325. //----------  IAdd  ----------
  1326.  
  1327. void IAdd::print () {
  1328.   fprintf (outputFile, "!   ");
  1329.   printANode (dest);
  1330.   fprintf (outputFile, " = ");
  1331.   printANode (arg1);
  1332.   fprintf (outputFile, " + ");
  1333.   printANode (arg2);
  1334.   fprintf (outputFile, "\t\t(int)\n");
  1335.   getIntoReg4 (arg1, "r1");
  1336.   getIntoReg4 (arg2, "r2");
  1337.   fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  1338.   overflowTest ();
  1339.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1340. }
  1341.  
  1342. void IRIAdd (AstNode * d, AstNode * a1, AstNode * a2) {
  1343.   linkIR (new IAdd (d, a1, a2));
  1344. }
  1345.  
  1346.  
  1347.  
  1348. //----------  ISub  ----------
  1349.  
  1350. void ISub::print () {
  1351.   fprintf (outputFile, "!   ");
  1352.   printANode (dest);
  1353.   fprintf (outputFile, " = ");
  1354.   printANode (arg1);
  1355.   fprintf (outputFile, " - ");
  1356.   printANode (arg2);
  1357.   fprintf (outputFile, "\t\t(int)\n");
  1358.   getIntoReg4 (arg1, "r1");
  1359.   getIntoReg4 (arg2, "r2");
  1360.   fprintf (outputFile, "\tsub\tr1,r2,r1\n");
  1361.   overflowTest ();
  1362.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1363. }
  1364.  
  1365. void IRISub (AstNode * d, AstNode * a1, AstNode * a2) {
  1366.   linkIR (new ISub (d, a1, a2));
  1367. }
  1368.  
  1369.  
  1370.  
  1371. //----------  IMul  ----------
  1372.  
  1373. void IMul::print () {
  1374.   fprintf (outputFile, "!   ");
  1375.   printANode (dest);
  1376.   fprintf (outputFile, " = ");
  1377.   printANode (arg1);
  1378.   fprintf (outputFile, " * ");
  1379.   printANode (arg2);
  1380.   fprintf (outputFile, "\t\t(int)\n");
  1381.   getIntoReg4 (arg1, "r1");
  1382.   getIntoReg4 (arg2, "r2");
  1383.   fprintf (outputFile, "\tmul\tr1,r2,r1\n");
  1384.   overflowTest ();
  1385.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1386. }
  1387.  
  1388. void IRIMul (AstNode * d, AstNode * a1, AstNode * a2) {
  1389.   linkIR (new IMul (d, a1, a2));
  1390. }
  1391.  
  1392.  
  1393.  
  1394. //----------  IDiv  ----------
  1395.  
  1396. void IDiv::print () {
  1397.   fprintf (outputFile, "!   ");
  1398.   printANode (dest);
  1399.   fprintf (outputFile, " = ");
  1400.   printANode (arg1);
  1401.   fprintf (outputFile, " div ");
  1402.   printANode (arg2);
  1403.   fprintf (outputFile, "\t\t(int)\n");
  1404.   getIntoReg4 (arg1, "r1");
  1405.   getIntoReg4 (arg2, "r2");
  1406.   fprintf (outputFile, "\tcmp\tr2,0\n");
  1407.   fprintf (outputFile, "\tbe\t_runtimeErrorZeroDivide\n");
  1408.   fprintf (outputFile, "\tdiv\tr1,r2,r1\n");
  1409.   overflowTest ();
  1410.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1411. }
  1412.  
  1413. void IRIDiv (AstNode * d, AstNode * a1, AstNode * a2) {
  1414.   linkIR (new IDiv (d, a1, a2));
  1415. }
  1416.  
  1417.  
  1418.  
  1419. //----------  IRem  ----------
  1420.  
  1421. void IRem::print () {
  1422.   fprintf (outputFile, "!   ");
  1423.   printANode (dest);
  1424.   fprintf (outputFile, " = ");
  1425.   printANode (arg1);
  1426.   fprintf (outputFile, " rem ");
  1427.   printANode (arg2);
  1428.   fprintf (outputFile, "\t\t(int)\n");
  1429.   getIntoReg4 (arg1, "r1");
  1430.   getIntoReg4 (arg2, "r2");
  1431.   fprintf (outputFile, "\tcmp\tr2,0\n");
  1432.   fprintf (outputFile, "\tbe\t_runtimeErrorZeroDivide\n");
  1433.   fprintf (outputFile, "\trem\tr1,r2,r1\n");
  1434.   overflowTest ();
  1435.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1436. }
  1437.  
  1438. void IRIRem (AstNode * d, AstNode * a1, AstNode * a2) {
  1439.   linkIR (new IRem (d, a1, a2));
  1440. }
  1441.  
  1442.  
  1443.  
  1444. //----------  Sll  ----------
  1445.  
  1446. void Sll::print () {
  1447.   fprintf (outputFile, "!   ");
  1448.   printANode (dest);
  1449.   fprintf (outputFile, " = ");
  1450.   printANode (arg1);
  1451.   fprintf (outputFile, " sll ");
  1452.   printANode (arg2);
  1453.   fprintf (outputFile, "\t\t(int)\n");
  1454.   getIntoReg4 (arg1, "r1");
  1455.   getIntoReg4 (arg2, "r2");
  1456.   fprintf (outputFile, "\tsll\tr1,r2,r1\n");
  1457.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1458. }
  1459.  
  1460. void IRSll (AstNode * d, AstNode * a1, AstNode * a2) {
  1461.   linkIR (new Sll (d, a1, a2));
  1462. }
  1463.  
  1464.  
  1465.  
  1466. //----------  Sra  ----------
  1467.  
  1468. void Sra::print () {
  1469.   fprintf (outputFile, "!   ");
  1470.   printANode (dest);
  1471.   fprintf (outputFile, " = ");
  1472.   printANode (arg1);
  1473.   fprintf (outputFile, " sra ");
  1474.   printANode (arg2);
  1475.   fprintf (outputFile, "\t\t(int)\n");
  1476.   getIntoReg4 (arg1, "r1");
  1477.   getIntoReg4 (arg2, "r2");
  1478.   fprintf (outputFile, "\tsra\tr1,r2,r1\n");
  1479.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1480. }
  1481.  
  1482. void IRSra (AstNode * d, AstNode * a1, AstNode * a2) {
  1483.   linkIR (new Sra (d, a1, a2));
  1484. }
  1485.  
  1486.  
  1487.  
  1488. //----------  Srl  ----------
  1489.  
  1490. void Srl::print () {
  1491.   fprintf (outputFile, "!   ");
  1492.   printANode (dest);
  1493.   fprintf (outputFile, " = ");
  1494.   printANode (arg1);
  1495.   fprintf (outputFile, " srl ");
  1496.   printANode (arg2);
  1497.   fprintf (outputFile, "\t\t(int)\n");
  1498.   getIntoReg4 (arg1, "r1");
  1499.   getIntoReg4 (arg2, "r2");
  1500.   fprintf (outputFile, "\tsrl\tr1,r2,r1\n");
  1501.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1502. }
  1503.  
  1504. void IRSrl (AstNode * d, AstNode * a1, AstNode * a2) {
  1505.   linkIR (new Srl (d, a1, a2));
  1506. }
  1507.  
  1508.  
  1509.  
  1510. //----------  And  ----------
  1511.  
  1512. void And::print () {
  1513.   fprintf (outputFile, "!   ");
  1514.   printANode (dest);
  1515.   fprintf (outputFile, " = ");
  1516.   printANode (arg1);
  1517.   fprintf (outputFile, " AND ");
  1518.   printANode (arg2);
  1519.   fprintf (outputFile, "\t\t(int)\n");
  1520.   getIntoReg4 (arg1, "r1");
  1521.   getIntoReg4 (arg2, "r2");
  1522.   fprintf (outputFile, "\tand\tr1,r2,r1\n");
  1523.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1524. }
  1525.  
  1526. void IRAnd (AstNode * d, AstNode * a1, AstNode * a2) {
  1527.   linkIR (new And (d, a1, a2));
  1528. }
  1529.  
  1530.  
  1531.  
  1532. //----------  Or  ----------
  1533.  
  1534. void Or::print () {
  1535.   fprintf (outputFile, "!   ");
  1536.   printANode (dest);
  1537.   fprintf (outputFile, " = ");
  1538.   printANode (arg1);
  1539.   fprintf (outputFile, " OR ");
  1540.   printANode (arg2);
  1541.   fprintf (outputFile, "\t\t(int)\n");
  1542.   getIntoReg4 (arg1, "r1");
  1543.   getIntoReg4 (arg2, "r2");
  1544.   fprintf (outputFile, "\tor\tr1,r2,r1\n");
  1545.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1546. }
  1547.  
  1548. void IROr (AstNode * d, AstNode * a1, AstNode * a2) {
  1549.   linkIR (new Or (d, a1, a2));
  1550. }
  1551.  
  1552.  
  1553.  
  1554. //----------  Xor  ----------
  1555.  
  1556. void Xor::print () {
  1557.   fprintf (outputFile, "!   ");
  1558.   printANode (dest);
  1559.   fprintf (outputFile, " = ");
  1560.   printANode (arg1);
  1561.   fprintf (outputFile, " XOR ");
  1562.   printANode (arg2);
  1563.   fprintf (outputFile, "\t\t(int)\n");
  1564.   getIntoReg4 (arg1, "r1");
  1565.   getIntoReg4 (arg2, "r2");
  1566.   fprintf (outputFile, "\txor\tr1,r2,r1\n");
  1567.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1568. }
  1569.  
  1570. void IRXor (AstNode * d, AstNode * a1, AstNode * a2) {
  1571.   linkIR (new Xor (d, a1, a2));
  1572. }
  1573.  
  1574.  
  1575.  
  1576. //----------  INeg  ----------
  1577.  
  1578. void INeg::print () {
  1579.   fprintf (outputFile, "!   ");
  1580.   printANode (dest);
  1581.   fprintf (outputFile, " = -");
  1582.   printANode (arg);
  1583.   fprintf (outputFile, "\t\t(int)\n");
  1584.   getIntoReg4 (arg, "r1");
  1585.   fprintf (outputFile, "\tneg\tr1\n");
  1586.   overflowTest ();
  1587.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1588. }
  1589.  
  1590. void IRINeg (AstNode * d, AstNode * a) {
  1591.   linkIR (new INeg (d, a));
  1592. }
  1593.  
  1594.  
  1595.  
  1596. //----------  Not  ----------
  1597.  
  1598. void Not::print () {
  1599.   fprintf (outputFile, "!   ");
  1600.   printANode (dest);
  1601.   fprintf (outputFile, " = NOT ");
  1602.   printANode (arg);
  1603.   fprintf (outputFile, "\t\t(int)\n");
  1604.   getIntoReg4 (arg, "r1");
  1605.   fprintf (outputFile, "\tnot\tr1\n");
  1606.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1607. }
  1608.  
  1609. void IRNot (AstNode * d, AstNode * a) {
  1610.   linkIR (new Not (d, a));
  1611. }
  1612.  
  1613.  
  1614.  
  1615. //----------  FAdd  ----------
  1616.  
  1617. void FAdd::print () {
  1618.   fprintf (outputFile, "!   ");
  1619.   printANode (dest);
  1620.   fprintf (outputFile, " = ");
  1621.   printANode (arg1);
  1622.   fprintf (outputFile, " + ");
  1623.   printANode (arg2);
  1624.   fprintf (outputFile, "\t\t(float)\n");
  1625.   getIntoReg8 (arg1, "f0", "r1");
  1626.   getIntoReg8 (arg2, "f1", "r2");
  1627.   fprintf (outputFile, "\tfadd\tf0,f1,f0\n");
  1628.   // CCR is not affected: no overflow test possible
  1629.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1630. }
  1631.  
  1632. void IRFAdd (AstNode * d, AstNode * a1, AstNode * a2) {
  1633.   linkIR (new FAdd (d, a1, a2));
  1634. }
  1635.  
  1636.  
  1637.  
  1638. //----------  FSub  ----------
  1639.  
  1640. void FSub::print () {
  1641.   fprintf (outputFile, "!   ");
  1642.   printANode (dest);
  1643.   fprintf (outputFile, " = ");
  1644.   printANode (arg1);
  1645.   fprintf (outputFile, " + ");
  1646.   printANode (arg2);
  1647.   fprintf (outputFile, "\t\t(float)\n");
  1648.   getIntoReg8 (arg1, "f0", "r1");
  1649.   getIntoReg8 (arg2, "f1", "r2");
  1650.   fprintf (outputFile, "\tfsub\tf0,f1,f0\n");
  1651.   // CCR is not affected: no overflow test possible
  1652.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1653. }
  1654.  
  1655. void IRFSub (AstNode * d, AstNode * a1, AstNode * a2) {
  1656.   linkIR (new FSub (d, a1, a2));
  1657. }
  1658.  
  1659.  
  1660.  
  1661. //----------  FMul  ----------
  1662.  
  1663. void FMul::print () {
  1664.   fprintf (outputFile, "!   ");
  1665.   printANode (dest);
  1666.   fprintf (outputFile, " = ");
  1667.   printANode (arg1);
  1668.   fprintf (outputFile, " + ");
  1669.   printANode (arg2);
  1670.   fprintf (outputFile, "\t\t(float)\n");
  1671.   getIntoReg8 (arg1, "f0", "r1");
  1672.   getIntoReg8 (arg2, "f1", "r2");
  1673.   fprintf (outputFile, "\tfmul\tf0,f1,f0\n");
  1674.   // CCR is not affected: no overflow test possible
  1675.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1676. }
  1677.  
  1678. void IRFMul (AstNode * d, AstNode * a1, AstNode * a2) {
  1679.   linkIR (new FMul (d, a1, a2));
  1680. }
  1681.  
  1682.  
  1683.  
  1684. //----------  FDiv  ----------
  1685.  
  1686. void FDiv::print () {
  1687.   fprintf (outputFile, "!   ");
  1688.   printANode (dest);
  1689.   fprintf (outputFile, " = ");
  1690.   printANode (arg1);
  1691.   fprintf (outputFile, " + ");
  1692.   printANode (arg2);
  1693.   fprintf (outputFile, "\t\t(float)\n");
  1694.   getIntoReg8 (arg1, "f0", "r1");
  1695.   getIntoReg8 (arg2, "f1", "r2");
  1696.   fprintf (outputFile, "\tfdiv\tf0,f1,f0\n");
  1697.   // CCR is not affected: no overflow test possible
  1698.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1699. }
  1700.  
  1701. void IRFDiv (AstNode * d, AstNode * a1, AstNode * a2) {
  1702.   linkIR (new FDiv (d, a1, a2));
  1703. }
  1704.  
  1705.  
  1706.  
  1707. //----------  FNeg  ----------
  1708.  
  1709. void FNeg::print () {
  1710.   fprintf (outputFile, "!   ");
  1711.   printANode (dest);
  1712.   fprintf (outputFile, " = -");
  1713.   printANode (arg);
  1714.   fprintf (outputFile, "\t\t(float)\n");
  1715.   getIntoReg8 (arg, "f0", "r1");
  1716.   fprintf (outputFile, "\tfneg\tf0,f0\n");
  1717.   // CCR is not affected: no overflow test possible
  1718.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1719. }
  1720.  
  1721. void IRFNeg (AstNode * d, AstNode * a) {
  1722.   linkIR (new FNeg (d, a));
  1723. }
  1724.  
  1725.  
  1726.  
  1727. //----------  ItoF  ----------
  1728.  
  1729. void ItoF::print () {
  1730.   fprintf (outputFile, "!   ");
  1731.   printANode (dest);
  1732.   fprintf (outputFile, " = intToFloat (");
  1733.   printANode (arg);
  1734.   fprintf (outputFile, ")\n");
  1735.   getIntoReg4 (arg, "r1");
  1736.   fprintf (outputFile, "\titof\tr1,f0\n");
  1737.   // CCR is not affected: no overflow test possible
  1738.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1739. }
  1740.  
  1741. void IRItoF (AstNode * d, AstNode * a) {
  1742.   linkIR (new ItoF (d, a));
  1743. }
  1744.  
  1745.  
  1746.  
  1747. //----------  FtoI  ----------
  1748.  
  1749. void FtoI::print () {
  1750.   fprintf (outputFile, "!   ");
  1751.   printANode (dest);
  1752.   fprintf (outputFile, " = floatToInt (");
  1753.   printANode (arg);
  1754.   fprintf (outputFile, ")\n");
  1755.   getIntoReg8 (arg, "f0", "r1");
  1756.   fprintf (outputFile, "\tftoi\tf0,r1\n");
  1757.   // CCR is not affected: no overflow test possible
  1758.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1759. }
  1760.  
  1761. void IRFtoI (AstNode * d, AstNode * a) {
  1762.   linkIR (new FtoI (d, a));
  1763. }
  1764.  
  1765.  
  1766.  
  1767. //----------  ItoC  ----------
  1768.  
  1769. void ItoC::print () {
  1770.   fprintf (outputFile, "!   ");
  1771.   printANode (dest);
  1772.   fprintf (outputFile, " = intToChar (");
  1773.   printANode (arg);
  1774.   fprintf (outputFile, ")\n");
  1775.   getIntoReg4 (arg, "r1");
  1776.   // CCR is not affected: no overflow test possible
  1777.   storeFromReg1 ((VarDecl *) dest, "r1", "r2");
  1778. }
  1779.  
  1780. void IRItoC (AstNode * d, AstNode * a) {
  1781.   linkIR (new ItoC (d, a));
  1782. }
  1783.  
  1784.  
  1785.  
  1786. //----------  CtoI  ----------
  1787.  
  1788. void CtoI::print () {
  1789.   fprintf (outputFile, "!   ");
  1790.   printANode (dest);
  1791.   fprintf (outputFile, " = charToInt (");
  1792.   printANode (arg);
  1793.   fprintf (outputFile, ")\n");
  1794.   getIntoReg1 (arg, "r1");
  1795.   fprintf (outputFile, "\tsll\tr1,24,r1\n");
  1796.   fprintf (outputFile, "\tsra\tr1,24,r1\n");
  1797.   storeFromReg4 ((VarDecl *) dest, "r1", "r2");
  1798. }
  1799.  
  1800. void IRCtoI (AstNode * d, AstNode * a) {
  1801.   linkIR (new CtoI (d, a));
  1802. }
  1803.  
  1804.  
  1805.  
  1806. //----------  PosInf  ----------
  1807.  
  1808. void PosInf::print () {
  1809.   fprintf (outputFile, "!   ");
  1810.   printANode (dest);
  1811.   fprintf (outputFile, " = PosInf\n");
  1812.   fprintf (outputFile, "\tset\t_PosInf,r1\n");
  1813.   fprintf (outputFile, "\tfload\t[r1],f0\n");
  1814.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1815. }
  1816.  
  1817. void IRPosInf (AstNode * d) {
  1818.   linkIR (new PosInf (d));
  1819. }
  1820.  
  1821.  
  1822.  
  1823. //----------  NegInf  ----------
  1824.  
  1825. void NegInf::print () {
  1826.   fprintf (outputFile, "!   ");
  1827.   printANode (dest);
  1828.   fprintf (outputFile, " = NegInf\n");
  1829.   fprintf (outputFile, "\tset\t_NegInf,r1\n");
  1830.   fprintf (outputFile, "\tfload\t[r1],f0\n");
  1831.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1832. }
  1833.  
  1834. void IRNegInf (AstNode * d) {
  1835.   linkIR (new NegInf (d));
  1836. }
  1837.  
  1838.  
  1839.  
  1840. //----------  NegZero  ----------
  1841.  
  1842. void NegZero::print () {
  1843.   fprintf (outputFile, "!   ");
  1844.   printANode (dest);
  1845.   fprintf (outputFile, " = NegZero\n");
  1846.   fprintf (outputFile, "\tset\t_NegZero,r1\n");
  1847.   fprintf (outputFile, "\tfload\t[r1],f0\n");
  1848.   storeFromReg8 ((VarDecl *) dest, "f0", "r2");
  1849. }
  1850.  
  1851. void IRNegZero (AstNode * d) {
  1852.   linkIR (new NegZero (d));
  1853. }
  1854.  
  1855.  
  1856.  
  1857. //----------  IntLTGoto  ----------
  1858.  
  1859. void IntLTGoto::print () {
  1860.   fprintf (outputFile, "!   if ");
  1861.   printANode (arg1);
  1862.   fprintf (outputFile, " < ");
  1863.   printANode (arg2);
  1864.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1865.   getIntoReg4 (arg1, "r1");
  1866.   getIntoReg4 (arg2, "r2");
  1867.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1868.   overflowTest ();
  1869.   fprintf (outputFile, "\tbl\t%s\n", label);
  1870. }
  1871.  
  1872. void IRIntLTGoto (AstNode * a1, AstNode * a2, char * lab) {
  1873.   linkIR (new IntLTGoto (a1, a2, lab));
  1874. }
  1875.  
  1876.  
  1877.  
  1878. //----------  IntLEGoto  ----------
  1879.  
  1880. void IntLEGoto::print () {
  1881.   fprintf (outputFile, "!   if ");
  1882.   printANode (arg1);
  1883.   fprintf (outputFile, " <= ");
  1884.   printANode (arg2);
  1885.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1886.   getIntoReg4 (arg1, "r1");
  1887.   getIntoReg4 (arg2, "r2");
  1888.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1889.   overflowTest ();
  1890.   fprintf (outputFile, "\tble\t%s\n", label);
  1891. }
  1892.  
  1893. void IRIntLEGoto (AstNode * a1, AstNode * a2, char * lab) {
  1894.   linkIR (new IntLEGoto (a1, a2, lab));
  1895. }
  1896.  
  1897.  
  1898.  
  1899. //----------  IntGTGoto  ----------
  1900.  
  1901. void IntGTGoto::print () {
  1902.   fprintf (outputFile, "!   if ");
  1903.   printANode (arg1);
  1904.   fprintf (outputFile, " > ");
  1905.   printANode (arg2);
  1906.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1907.   getIntoReg4 (arg1, "r1");
  1908.   getIntoReg4 (arg2, "r2");
  1909.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1910.   overflowTest ();
  1911.   fprintf (outputFile, "\tbg\t%s\n", label);
  1912. }
  1913.  
  1914. void IRIntGTGoto (AstNode * a1, AstNode * a2, char * lab) {
  1915.   linkIR (new IntGTGoto (a1, a2, lab));
  1916. }
  1917.  
  1918.  
  1919.  
  1920. //----------  IntGEGoto  ----------
  1921.  
  1922. void IntGEGoto::print () {
  1923.   fprintf (outputFile, "!   if ");
  1924.   printANode (arg1);
  1925.   fprintf (outputFile, " >= ");
  1926.   printANode (arg2);
  1927.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1928.   getIntoReg4 (arg1, "r1");
  1929.   getIntoReg4 (arg2, "r2");
  1930.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1931.   overflowTest ();
  1932.   fprintf (outputFile, "\tbge\t%s\n", label);
  1933. }
  1934.  
  1935. void IRIntGEGoto (AstNode * a1, AstNode * a2, char * lab) {
  1936.   linkIR (new IntGEGoto (a1, a2, lab));
  1937. }
  1938.  
  1939.  
  1940.  
  1941. //----------  IntEQGoto  ----------
  1942.  
  1943. void IntEQGoto::print () {
  1944.   fprintf (outputFile, "!   if ");
  1945.   printANode (arg1);
  1946.   fprintf (outputFile, " == ");
  1947.   printANode (arg2);
  1948.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1949.   getIntoReg4 (arg1, "r1");
  1950.   getIntoReg4 (arg2, "r2");
  1951.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1952.   // overflowTest ();             // The Z flag will be ok, even if overflow
  1953.   fprintf (outputFile, "\tbe\t%s\n", label);
  1954. }
  1955.  
  1956. void IRIntEQGoto (AstNode * a1, AstNode * a2, char * lab) {
  1957.   linkIR (new IntEQGoto (a1, a2, lab));
  1958. }
  1959.  
  1960.  
  1961.  
  1962. //----------  IntNEGoto  ----------
  1963.  
  1964. void IntNEGoto::print () {
  1965.   fprintf (outputFile, "!   if ");
  1966.   printANode (arg1);
  1967.   fprintf (outputFile, " != ");
  1968.   printANode (arg2);
  1969.   fprintf (outputFile, " then goto %s\t\t(int)\n", label);
  1970.   getIntoReg4 (arg1, "r1");
  1971.   getIntoReg4 (arg2, "r2");
  1972.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  1973.   // overflowTest ();             // The Z flag will be ok, even if overflow
  1974.   fprintf (outputFile, "\tbne\t%s\n", label);
  1975. }
  1976.  
  1977. void IRIntNEGoto (AstNode * a1, AstNode * a2, char * lab) {
  1978.   linkIR (new IntNEGoto (a1, a2, lab));
  1979. }
  1980.  
  1981.  
  1982.  
  1983. //----------  FloatLTGoto  ----------
  1984.  
  1985. void FloatLTGoto::print () {
  1986.   fprintf (outputFile, "!   if ");
  1987.   printANode (arg1);
  1988.   fprintf (outputFile, " < ");
  1989.   printANode (arg2);
  1990.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  1991.   getIntoReg8 (arg1, "f0", "r1");
  1992.   getIntoReg8 (arg2, "f1", "r1");
  1993.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  1994.   overflowTest ();             // Can occur if either is Nan
  1995.   fprintf (outputFile, "\tbl\t%s\n", label);
  1996. }
  1997.  
  1998. void IRFloatLTGoto (AstNode * a1, AstNode * a2, char * lab) {
  1999.   linkIR (new FloatLTGoto (a1, a2, lab));
  2000. }
  2001.  
  2002.  
  2003.  
  2004. //----------  FloatLEGoto  ----------
  2005.  
  2006. void FloatLEGoto::print () {
  2007.   fprintf (outputFile, "!   if ");
  2008.   printANode (arg1);
  2009.   fprintf (outputFile, " <= ");
  2010.   printANode (arg2);
  2011.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  2012.   getIntoReg8 (arg1, "f0", "r1");
  2013.   getIntoReg8 (arg2, "f1", "r1");
  2014.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  2015.   overflowTest ();             // Can occur if either is Nan
  2016.   fprintf (outputFile, "\tble\t%s\n", label);
  2017. }
  2018.  
  2019. void IRFloatLEGoto (AstNode * a1, AstNode * a2, char * lab) {
  2020.   linkIR (new FloatLEGoto (a1, a2, lab));
  2021. }
  2022.  
  2023.  
  2024.  
  2025. //----------  FloatGTGoto  ----------
  2026.  
  2027. void FloatGTGoto::print () {
  2028.   fprintf (outputFile, "!   if ");
  2029.   printANode (arg1);
  2030.   fprintf (outputFile, " > ");
  2031.   printANode (arg2);
  2032.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  2033.   getIntoReg8 (arg1, "f0", "r1");
  2034.   getIntoReg8 (arg2, "f1", "r1");
  2035.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  2036.   overflowTest ();             // Can occur if either is Nan
  2037.   fprintf (outputFile, "\tbg\t%s\n", label);
  2038. }
  2039.  
  2040. void IRFloatGTGoto (AstNode * a1, AstNode * a2, char * lab) {
  2041.   linkIR (new FloatGTGoto (a1, a2, lab));
  2042. }
  2043.  
  2044.  
  2045.  
  2046. //----------  FloatGEGoto  ----------
  2047.  
  2048. void FloatGEGoto::print () {
  2049.   fprintf (outputFile, "!   if ");
  2050.   printANode (arg1);
  2051.   fprintf (outputFile, " >= ");
  2052.   printANode (arg2);
  2053.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  2054.   getIntoReg8 (arg1, "f0", "r1");
  2055.   getIntoReg8 (arg2, "f1", "r1");
  2056.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  2057.   overflowTest ();             // Can occur if either is Nan
  2058.   fprintf (outputFile, "\tbge\t%s\n", label);
  2059. }
  2060.  
  2061. void IRFloatGEGoto (AstNode * a1, AstNode * a2, char * lab) {
  2062.   linkIR (new FloatGEGoto (a1, a2, lab));
  2063. }
  2064.  
  2065.  
  2066.  
  2067. //----------  FloatEQGoto  ----------
  2068.  
  2069. void FloatEQGoto::print () {
  2070.   fprintf (outputFile, "!   if ");
  2071.   printANode (arg1);
  2072.   fprintf (outputFile, " == ");
  2073.   printANode (arg2);
  2074.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  2075.   getIntoReg8 (arg1, "f0", "r1");
  2076.   getIntoReg8 (arg2, "f1", "r1");
  2077.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  2078.   overflowTest ();             // Can occur if either is Nan
  2079.   fprintf (outputFile, "\tbe\t%s\n", label);
  2080. }
  2081.  
  2082. void IRFloatEQGoto (AstNode * a1, AstNode * a2, char * lab) {
  2083.   linkIR (new FloatEQGoto (a1, a2, lab));
  2084. }
  2085.  
  2086.  
  2087.  
  2088. //----------  FloatNEGoto  ----------
  2089.  
  2090. void FloatNEGoto::print () {
  2091.   fprintf (outputFile, "!   if ");
  2092.   printANode (arg1);
  2093.   fprintf (outputFile, " != ");
  2094.   printANode (arg2);
  2095.   fprintf (outputFile, " then goto %s\t\t(float)\n", label);
  2096.   getIntoReg8 (arg1, "f0", "r1");
  2097.   getIntoReg8 (arg2, "f1", "r1");
  2098.   fprintf (outputFile, "\tfcmp\tf0,f1\n");
  2099.   overflowTest ();             // Can occur if either is Nan
  2100.   fprintf (outputFile, "\tbne\t%s\n", label);
  2101. }
  2102.  
  2103. void IRFloatNEGoto (AstNode * a1, AstNode * a2, char * lab) {
  2104.   linkIR (new FloatNEGoto (a1, a2, lab));
  2105. }
  2106.  
  2107.  
  2108.  
  2109. //----------  BoolTest  ----------
  2110.  
  2111. void BoolTest::print () {
  2112.   fprintf (outputFile, "!   if ");
  2113.   printANode (arg);
  2114.   fprintf (outputFile, " then goto %s else goto %s\n", trueLabel, falseLabel);
  2115.   getIntoReg1 (arg, "r1");
  2116.   fprintf (outputFile, "\tcmp\tr1,0\n");
  2117.   fprintf (outputFile, "\tbe\t%s\n", falseLabel);
  2118.   fprintf (outputFile, "\tjmp\t%s\n", trueLabel);
  2119. }
  2120.  
  2121. void IRBoolTest (AstNode * a, char * lab1, char * lab2) {
  2122.   linkIR (new BoolTest (a, lab1, lab2));
  2123. }
  2124.  
  2125.  
  2126.  
  2127. //----------  BoolTest2  ----------
  2128.  
  2129. void BoolTest2::print () {
  2130.   fprintf (outputFile, "!   if result==true then goto %s else goto %s\n", trueLabel, falseLabel);
  2131.   fprintf (outputFile, "\tloadb\t[r15],r1\n");
  2132.   fprintf (outputFile, "\tcmp\tr1,0\n");
  2133.   fprintf (outputFile, "\tbe\t%s\n", falseLabel);
  2134.   fprintf (outputFile, "\tjmp\t%s\n", trueLabel);
  2135. }
  2136.  
  2137. void IRBoolTest2 (char * lab1, char * lab2) {
  2138.   linkIR (new BoolTest2 (lab1, lab2));
  2139. }
  2140.  
  2141.  
  2142.  
  2143. //----------  BXor  ----------
  2144.  
  2145. void BXor::print () {
  2146.   fprintf (outputFile, "!   ");
  2147.   printANode (dest);
  2148.   fprintf (outputFile, " = ");
  2149.   printANode (arg1);
  2150.   fprintf (outputFile, " XOR ");
  2151.   printANode (arg2);
  2152.   fprintf (outputFile, "\t\t(bool)\n");
  2153.   getIntoReg1 (arg1, "r1");
  2154.   getIntoReg1 (arg2, "r2");
  2155.   fprintf (outputFile, "\txor\tr1,r2,r1\n");
  2156.   storeFromReg1 ((VarDecl *) dest, "r1", "r2");
  2157. }
  2158.  
  2159. void IRBXor (AstNode * d, AstNode * a1, AstNode * a2) {
  2160.   linkIR (new BXor (d, a1, a2));
  2161. }
  2162.  
  2163.  
  2164.  
  2165. //----------  BEq  ----------
  2166.  
  2167. void BEq::print () {
  2168.   fprintf (outputFile, "!   ");
  2169.   printANode (dest);
  2170.   fprintf (outputFile, " = ");
  2171.   printANode (arg1);
  2172.   fprintf (outputFile, " XOR ");
  2173.   printANode (arg2);
  2174.   fprintf (outputFile, "\t\t(bool)\n");
  2175.   getIntoReg1 (arg1, "r1");
  2176.   getIntoReg1 (arg2, "r2");
  2177.   fprintf (outputFile, "\txor\tr1,r2,r1\n");
  2178.   fprintf (outputFile, "\tbtog\t1,r1\n");
  2179.   storeFromReg1 ((VarDecl *) dest, "r1", "r2");
  2180. }
  2181.  
  2182. void IRBEq (AstNode * d, AstNode * a1, AstNode * a2) {
  2183.   linkIR (new BEq (d, a1, a2));
  2184. }
  2185.  
  2186.  
  2187.  
  2188. //----------  BNot  ----------
  2189.  
  2190. void BNot::print () {
  2191.   fprintf (outputFile, "!   ");
  2192.   printANode (dest);
  2193.   fprintf (outputFile, " = ");
  2194.   fprintf (outputFile, " NOT ");
  2195.   printANode (arg);
  2196.   fprintf (outputFile, "\t\t(bool)\n");
  2197.   getIntoReg1 (arg, "r1");
  2198.   fprintf (outputFile, "\tbtog\t1,r1\n");
  2199.   storeFromReg1 ((VarDecl *) dest, "r1", "r2");
  2200. }
  2201.  
  2202. void IRBNot (AstNode * d, AstNode * a) {
  2203.   linkIR (new BNot (d, a));
  2204. }
  2205.  
  2206.  
  2207.  
  2208. //----------  IntEqZero  ----------
  2209.  
  2210. void IntEqZero::print () {
  2211.   fprintf (outputFile, "!   if intIsZero (");
  2212.   printANode (arg);
  2213.   fprintf (outputFile, ") then goto %s\n", label);
  2214.   getIntoReg4 (arg, "r1");
  2215.   fprintf (outputFile, "\tcmp\tr1,r0\n");
  2216.   fprintf (outputFile, "\tbe\t%s\n", label);
  2217. }
  2218.  
  2219. void IRIntEqZero (AstNode * a, char * lab) {
  2220.   linkIR (new IntEqZero (a, lab));
  2221. }
  2222.  
  2223.  
  2224.  
  2225. //----------  IntNeZero  ----------
  2226.  
  2227. void IntNeZero::print () {
  2228.   fprintf (outputFile, "!   if intNotZero (");
  2229.   printANode (arg);
  2230.   fprintf (outputFile, ") then goto %s\n", label);
  2231.   getIntoReg4 (arg, "r1");
  2232.   fprintf (outputFile, "\tcmp\tr1,r0\n");
  2233.   fprintf (outputFile, "\tbne\t%s\n", label);
  2234. }
  2235.  
  2236. void IRIntNeZero (AstNode * a, char * lab) {
  2237.   linkIR (new IntNeZero (a, lab));
  2238. }
  2239.  
  2240.  
  2241.  
  2242. //----------  IntLeZero  ----------
  2243.  
  2244. void IntLeZero::print () {
  2245.   fprintf (outputFile, "!   if ");
  2246.   printANode (arg);
  2247.   fprintf (outputFile, " <= 0 then goto %s\n", label);
  2248.   getIntoReg4 (arg, "r1");
  2249.   fprintf (outputFile, "\tcmp\tr1,r0\n");
  2250.   fprintf (outputFile, "\tble\t%s\n", label);
  2251. }
  2252.  
  2253. void IRIntLeZero (AstNode * a, char * lab) {
  2254.   linkIR (new IntLeZero (a, lab));
  2255. }
  2256.  
  2257.  
  2258.  
  2259. //----------  BoolEqZeroIndirect  ----------
  2260.  
  2261. void BoolEqZeroIndirect::print () {
  2262.   fprintf (outputFile, "!   if boolIsZero (");
  2263.   printANode (arg);
  2264.   fprintf (outputFile, " ) then goto %s\t\t(int)\n", label);
  2265.   getIntoReg4 (arg, "r1");
  2266.   fprintf (outputFile, "\tloadb\t[r1],r1\n");
  2267.   fprintf (outputFile, "\tcmp\tr1,r0\n");
  2268.   fprintf (outputFile, "\tbe\t%s\n", label);
  2269. }
  2270.  
  2271. void IRBoolEqZeroIndirect (VarDecl * a, char * lab) {
  2272.   linkIR (new BoolEqZeroIndirect (a, lab));
  2273. }
  2274.  
  2275.  
  2276.  
  2277. //----------  PrepareArg  ----------
  2278.  
  2279. void PrepareArg::print () {
  2280.   char * label;
  2281.   int i;
  2282.   fprintf (outputFile, "!   Prepare Argument: offset=%d  value=", offset);
  2283.   printANode (tempName);
  2284.   fprintf (outputFile, "  sizeInBytes=%d\n", sizeInBytes);
  2285.   if (sizeInBytes == 1) {
  2286.     getIntoReg1 (tempName, "r1");
  2287.     if (within16Bits (offset-8)) {
  2288.       fprintf (outputFile, "\tstoreb\tr1,[r15+%d]\n", offset-8);
  2289.     } else {
  2290.       fprintf (outputFile, "\tset\t%d,r2\n", offset-8);
  2291.       fprintf (outputFile, "\tstoreb\tr1,[r15+r2]\n");
  2292.     }
  2293.   } else if (sizeInBytes == 4) {
  2294.     getIntoReg4 (tempName, "r1");
  2295.     if (within16Bits (offset-8)) {
  2296.       fprintf (outputFile, "\tstore\tr1,[r15+%d]\n", offset-8);
  2297.     } else {
  2298.       fprintf (outputFile, "\tset\t%d,r2\n", offset-8);
  2299.       fprintf (outputFile, "\tstore\tr1,[r15+r2]\n");
  2300.     }
  2301.   } else if (sizeInBytes == 8) {
  2302.     getIntoReg8 (tempName, "f0", "r1");
  2303.     if (within16Bits (offset-8)) {
  2304.       fprintf (outputFile, "\tfstore\tf0,[r15+%d]\n", offset-8);
  2305.     } else {
  2306.       fprintf (outputFile, "\tset\t%d,r2\n", offset-8);
  2307.       fprintf (outputFile, "\tfstore\tf0,[r15+r2]\n");
  2308.     }
  2309.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  2310.     printf ("sizeInBytes = %d\n", sizeInBytes);
  2311.     programLogicError ("In PrepareArg, problems with sizeInBytes");
  2312.   } else {
  2313.     // Generate code to move N bytes into the arg position...
  2314.     //     r3 = counter of words
  2315.     //     r4 = ptr to dest
  2316.     //     r5 = ptr to source
  2317.     //     r1 = word being moved
  2318.     label = newLabel ();
  2319.     if (within16Bits (sizeInBytes / 4)) {
  2320.       fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  2321.     } else {
  2322.       fprintf (outputFile, "\tset\t%d,r3\n", sizeInBytes / 4);
  2323.     }
  2324.     if (within16Bits (offset-8)) {
  2325.       fprintf (outputFile, "\tadd\tr15,%d,r4\n", offset-8);
  2326.     } else {
  2327.       fprintf (outputFile, "\tset\t%d,r4\n", offset-8);
  2328.       fprintf (outputFile, "\tadd\tr15,r4,r4\n");
  2329.     }
  2330.     getAddrOfVarIntoReg (tempName, "r5");
  2331.     fprintf (outputFile, "%s:\n", label);
  2332.     fprintf (outputFile, "\tload\t[r5],r1\n");
  2333.     fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2334.     fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2335.     fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2336.     fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2337.     fprintf (outputFile, "\tbne\t%s\n", label);
  2338.   }
  2339. }
  2340.  
  2341. void IRPrepareArg (int off, AstNode * tname, int size) {
  2342.   linkIR (new PrepareArg (off, tname, size));
  2343. }
  2344.  
  2345.  
  2346.  
  2347. //----------  RetrieveResult  ----------
  2348.  
  2349. void RetrieveResult::print () {
  2350.   char * label;
  2351.   int i;
  2352.  
  2353.   fprintf (outputFile, "!   Retrieve Result: targetName=");
  2354.   printANode (targetName);
  2355.   fprintf (outputFile, "  sizeInBytes=%d\n", sizeInBytes);
  2356.   if (sizeInBytes == 1) {
  2357.     fprintf (outputFile, "\tloadb\t[r15],r1\n");
  2358.     storeFromReg1 (targetName, "r1", "r2");
  2359.   } else if (sizeInBytes == 4) {
  2360.     fprintf (outputFile, "\tload\t[r15],r1\n");
  2361.     storeFromReg4 (targetName, "r1", "r2");
  2362.   } else if (sizeInBytes == 8) {
  2363.     fprintf (outputFile, "\tfload\t[r15],f0\n");
  2364.     storeFromReg8 (targetName, "f0", "r2");
  2365.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  2366.     printf ("sizeInBytes = %d\n", sizeInBytes);
  2367.     programLogicError ("In RetrieveResult, problems with sizeInBytes");
  2368.   } else {
  2369.     // Generate code to move N bytes from result to target...
  2370.     //     r3 = counter of words
  2371.     //     r4 = ptr to dest
  2372.     //     r5 = ptr to source
  2373.     //     r1 = word being moved
  2374.     label = newLabel ();
  2375.     if (within16Bits (sizeInBytes / 4)) {
  2376.       fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  2377.     } else {
  2378.       fprintf (outputFile, "\tset\t%d,r3\n", sizeInBytes / 4);
  2379.     }
  2380.     fprintf (outputFile, "\tmov\tr15,r5\n");
  2381.     getAddrOfVarIntoReg (targetName, "r4");
  2382.     fprintf (outputFile, "%s:\n", label);
  2383.     fprintf (outputFile, "\tload\t[r5],r1\n");
  2384.     fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2385.     fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2386.     fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2387.     fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2388.     fprintf (outputFile, "\tbne\t%s\n", label);
  2389.   }
  2390. }
  2391.  
  2392. void IRRetrieveResult (VarDecl * tname, int size) {
  2393.   linkIR (new RetrieveResult (tname, size));
  2394. }
  2395.  
  2396.  
  2397.  
  2398. //----------  ReturnResult  ----------
  2399.  
  2400. void ReturnResult::print () {
  2401.   char * label;
  2402.   int i;
  2403.  
  2404.   fprintf (outputFile, "!   ReturnResult: ");
  2405.   printANode (tempName);
  2406.   fprintf (outputFile, "  (sizeInBytes=%d)\n", sizeInBytes);
  2407.   if (sizeInBytes == 1) {
  2408.     getIntoReg1 (tempName, "r1");
  2409.     fprintf (outputFile, "\tstoreb\tr1,[r14+8]\n");
  2410.   } else if (sizeInBytes == 4) {
  2411.     getIntoReg4 (tempName, "r1");
  2412.     fprintf (outputFile, "\tstore\tr1,[r14+8]\n");
  2413.   } else if (sizeInBytes == 8) {
  2414.     getIntoReg8 (tempName, "f0", "r1");
  2415.     fprintf (outputFile, "\tfstore\tf0,[r14+8]\n");
  2416.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  2417.     printf ("sizeInBytes = %d\n", sizeInBytes);
  2418.     programLogicError ("In ReturnResult, problems with sizeInBytes");
  2419.   } else {
  2420.     // Generate code to move N bytes into the arg position...
  2421.     //     r3 = counter of words
  2422.     //     r4 = ptr to dest (r14+8)
  2423.     //     r5 = ptr to source (tempName)
  2424.     //     r1 = word being moved
  2425.     label = newLabel ();
  2426.     if (within16Bits (sizeInBytes / 4)) {
  2427.       fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  2428.     } else {
  2429.       fprintf (outputFile, "\tset\t%d,r3\n", sizeInBytes / 4);
  2430.     }
  2431.     fprintf (outputFile, "\tadd\tr14,8,r4\n");
  2432.     getAddrOfVarIntoReg (tempName, "r5");
  2433.     fprintf (outputFile, "%s:\n", label);
  2434.     fprintf (outputFile, "\tload\t[r5],r1\n");
  2435.     fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2436.     fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2437.     fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2438.     fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2439.     fprintf (outputFile, "\tbne\t%s\n", label);
  2440.   }
  2441. }
  2442.  
  2443. void IRReturnResult (AstNode * tname, int size) {
  2444.   linkIR (new ReturnResult (tname, size));
  2445. }
  2446.  
  2447.  
  2448.  
  2449. //----------  Comment2  ----------
  2450.  
  2451. void Comment2::print () {
  2452.   fprintf (outputFile, "! %s%s%s\n", str1, str2, str3);
  2453. }
  2454.  
  2455. void IRComment2 (char * str1, char * str2, char * str3) {
  2456.   linkIR (new Comment2 (str1, str2, str3));
  2457. }
  2458.  
  2459.  
  2460.  
  2461. //----------  Set  ----------
  2462.  
  2463. void Set::print () {
  2464.   if (within16Bits (initValue)) {
  2465.     fprintf (outputFile, "\tmov\t%d,r1\n", initValue);
  2466.   } else if (initValue == 0x80000000) {
  2467.     fprintf (outputFile, "\tset\t0x80000000,r1\n");
  2468.   } else {
  2469.     fprintf (outputFile, "\tset\t%d,r1\n", initValue);
  2470.   }
  2471.   storeFromReg4 (varDecl, "r1", "r2");
  2472. }
  2473.  
  2474. void IRSet (VarDecl * v, int i) {
  2475.   linkIR (new Set (v, i));
  2476. }
  2477.  
  2478.  
  2479.  
  2480. //----------  Send  ----------
  2481.  
  2482. void Send::print () {
  2483.   fprintf (outputFile, "!   Send message %s\n", methProto->selector->chars);
  2484.   getIntoReg4 (recvr, "r1");
  2485. //  The check for null pointer occurs elsewhere, when the ptr is first encountered.
  2486. //     fprintf (outputFile, "\tcmp\tr1,0\n");
  2487. //     fprintf (outputFile, "\tbe\t_runtimeErrorNullPointer\n");
  2488.   fprintf (outputFile, "\tload\t[r1],r2\n");
  2489.   fprintf (outputFile, "\tcmp\tr2,0\n");
  2490.   fprintf (outputFile, "\tbe\t _runtimeErrorUninitializedObject\n");
  2491.   fprintf (outputFile, "\tstore\tr1,[r15]\n");
  2492.   if (within16Bits (methProto->offset)) {
  2493.     fprintf (outputFile, "\tadd\tr2,%d,r2\n", methProto->offset);
  2494.   } else {
  2495.     fprintf (outputFile, "\tset\t%d,r11\n", methProto->offset);
  2496.     fprintf (outputFile, "\tadd\tr2,r11,r2\n");
  2497.     // printf ("16-bit overflow in IRSend   Method=%s  offset=%d\n",
  2498.     //         methProto->selector->chars, methProto->offset);
  2499.   }
  2500.   fprintf (outputFile, "\tcall\tr2\n");
  2501. }
  2502.  
  2503. void IRSend (VarDecl * r, MethodProto * m) {
  2504.   linkIR (new Send (r, m));
  2505. }
  2506.  
  2507.  
  2508.  
  2509. //----------  LoadSelfPtr  ----------
  2510.  
  2511. void LoadSelfPtr::print () {
  2512.     fprintf (outputFile, "\tload\t[r14+8],r1\n");
  2513.     storeFromReg4 (targetName, "r1", "r2");
  2514. }
  2515.  
  2516. void IRLoadSelfPtr (VarDecl * tname) {
  2517.   linkIR (new LoadSelfPtr (tname));
  2518. }
  2519.  
  2520.  
  2521.  
  2522. //----------  Move  ----------
  2523.  
  2524. void Move::print () {
  2525.   char * label;
  2526.   int i;
  2527.   fprintf (outputFile, "!   Data Move: ");
  2528.   if (targetVar) {
  2529.     printANode (targetVar);
  2530.   }
  2531.   if (targetPtr) {
  2532.     fprintf (outputFile, "*");
  2533.     printANode (targetPtr);
  2534.   }
  2535.   fprintf (outputFile, " = ");
  2536.   if (srcVar) {
  2537.     printANode (srcVar);
  2538.   }
  2539.   if (srcPtr) {
  2540.     fprintf (outputFile, "*");
  2541.     printANode (srcPtr);
  2542.   }
  2543.   fprintf (outputFile, "  (sizeInBytes=%d)\n", sizeInBytes);
  2544.   if ((targetVar==NULL) == (targetPtr==NULL)) {
  2545.     programLogicError ("In Move, targetVar and targetPtr are incorrect");
  2546.   }
  2547.   if ((srcVar==NULL) == (srcPtr==NULL)) {
  2548.     programLogicError ("In Move, srcVar and srcPtr are incorrect");
  2549.   }
  2550.   if (sizeInBytes == 1) {
  2551.     if (srcVar) {
  2552.       // untested...
  2553.       getIntoReg1 (srcVar, "r1");
  2554.     } else if (srcPtr) {
  2555.       getIntoReg4 (srcPtr, "r1");
  2556.       fprintf (outputFile, "\tloadb\t[r1],r1\n");
  2557.     }
  2558.     if (targetVar) {
  2559.       storeFromReg1 (targetVar, "r1", "r2");
  2560.     } else if (targetPtr) {
  2561.       // untested...
  2562.       getIntoReg4 (targetPtr, "r2");
  2563.       fprintf (outputFile, "\tstoreb\tr1,[r2]\n");
  2564.     }
  2565.   } else if (sizeInBytes == 4) {
  2566.     if (srcVar) {
  2567.       getIntoReg4 (srcVar, "r1");
  2568.     } else if (srcPtr) {
  2569.       getIntoReg4 (srcPtr, "r1");
  2570.       fprintf (outputFile, "\tload\t[r1],r1\n");
  2571.     }
  2572.     if (targetVar) {
  2573.       storeFromReg4 (targetVar, "r1", "r2");
  2574.     } else if (targetPtr) {
  2575.       // untested...
  2576.       getIntoReg4 (targetPtr, "r2");
  2577.       fprintf (outputFile, "\tstore\tr1,[r2]\n");
  2578.     }
  2579.   } else if (sizeInBytes == 8) {
  2580.     if (srcVar) {
  2581.       // untested...
  2582.       getIntoReg8 (srcVar, "f1", "r1");
  2583.     } else if (srcPtr) {
  2584.       getIntoReg4 (srcPtr, "r1");
  2585.       fprintf (outputFile, "\tfload\t[r1],f1\n");
  2586.     }
  2587.     if (targetVar) {
  2588.       storeFromReg8 (targetVar, "f1", "r2");
  2589.     } else if (targetPtr) {
  2590.       // untested...
  2591.       getIntoReg4 (targetPtr, "r2");
  2592.       fprintf (outputFile, "\tfstore\tf1,[r2]\n");
  2593.     }
  2594.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  2595.     printf ("sizeInBytes = %d\n", sizeInBytes);
  2596.     programLogicError ("In Move, problems with sizeInBytes");
  2597.   } else {
  2598.  
  2599.     if (srcVar) {
  2600.       // untested...
  2601.       getAddrOfVarIntoReg (srcVar, "r5");
  2602.     } else if (srcPtr) {
  2603.       getIntoReg4 (srcPtr, "r5");
  2604.     }
  2605.     if (targetVar) {
  2606.       // untested...
  2607.       getAddrOfVarIntoReg (targetVar, "r4");
  2608.     } else if (targetPtr) {
  2609.       getIntoReg4 (targetPtr, "r4");
  2610.     }
  2611.  
  2612.     if (sizeInBytes == 12) {
  2613.       fprintf (outputFile, "\tload\t[r5],r1\n");
  2614.       fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2615.       fprintf (outputFile, "\tload\t[r5+4],r1\n");
  2616.       fprintf (outputFile, "\tstore\tr1,[r4+4]\n");
  2617.       fprintf (outputFile, "\tload\t[r5+8],r1\n");
  2618.       fprintf (outputFile, "\tstore\tr1,[r4+8]\n");
  2619.     } else if (sizeInBytes == 16) {
  2620.       fprintf (outputFile, "\tload\t[r5],r1\n");
  2621.       fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2622.       fprintf (outputFile, "\tload\t[r5+4],r1\n");
  2623.       fprintf (outputFile, "\tstore\tr1,[r4+4]\n");
  2624.       fprintf (outputFile, "\tload\t[r5+8],r1\n");
  2625.       fprintf (outputFile, "\tstore\tr1,[r4+8]\n");
  2626.       fprintf (outputFile, "\tload\t[r5+12],r1\n");
  2627.       fprintf (outputFile, "\tstore\tr1,[r4+12]\n");
  2628.     } else if (sizeInBytes == 20) {
  2629.       fprintf (outputFile, "\tload\t[r5],r1\n");
  2630.       fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2631.       fprintf (outputFile, "\tload\t[r5+4],r1\n");
  2632.       fprintf (outputFile, "\tstore\tr1,[r4+4]\n");
  2633.       fprintf (outputFile, "\tload\t[r5+8],r1\n");
  2634.       fprintf (outputFile, "\tstore\tr1,[r4+8]\n");
  2635.       fprintf (outputFile, "\tload\t[r5+12],r1\n");
  2636.       fprintf (outputFile, "\tstore\tr1,[r4+12]\n");
  2637.       fprintf (outputFile, "\tload\t[r5+16],r1\n");
  2638.       fprintf (outputFile, "\tstore\tr1,[r4+16]\n");
  2639.     } else if (sizeInBytes == 24) {
  2640.       fprintf (outputFile, "\tload\t[r5],r1\n");
  2641.       fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2642.       fprintf (outputFile, "\tload\t[r5+4],r1\n");
  2643.       fprintf (outputFile, "\tstore\tr1,[r4+4]\n");
  2644.       fprintf (outputFile, "\tload\t[r5+8],r1\n");
  2645.       fprintf (outputFile, "\tstore\tr1,[r4+8]\n");
  2646.       fprintf (outputFile, "\tload\t[r5+12],r1\n");
  2647.       fprintf (outputFile, "\tstore\tr1,[r4+12]\n");
  2648.       fprintf (outputFile, "\tload\t[r5+16],r1\n");
  2649.       fprintf (outputFile, "\tstore\tr1,[r4+16]\n");
  2650.       fprintf (outputFile, "\tload\t[r5+20],r1\n");
  2651.       fprintf (outputFile, "\tstore\tr1,[r4+20]\n");
  2652.     } else {
  2653.       // Generate code to move N bytes...
  2654.       //     r3 = counter of words
  2655.       //     r4 = ptr to dest
  2656.       //     r5 = ptr to source
  2657.       //     r1 = word being moved
  2658.       label = newLabel ();
  2659.       if (within16Bits (sizeInBytes / 4)) {
  2660.         fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  2661.       } else {
  2662.         fprintf (outputFile, "\tset\t0x%08x,r3\t\t\t! decimal = %d\n",
  2663.                  sizeInBytes / 4, sizeInBytes / 4);
  2664.       }
  2665.       fprintf (outputFile, "%s:\n", label);
  2666.       fprintf (outputFile, "\tload\t[r5],r1\n");
  2667.       fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2668.       fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2669.       fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2670.       fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2671.       fprintf (outputFile, "\tbne\t%s\n", label);
  2672.     }
  2673.   }
  2674. }
  2675.  
  2676. void IRMove (VarDecl * tarV, VarDecl * tarP, AstNode * srcV, VarDecl * srcP, int sz) {
  2677.   linkIR (new Move (tarV, tarP, srcV, srcP, sz));
  2678. }
  2679.  
  2680.  
  2681.  
  2682. //----------  DynamicObjectMove  ----------
  2683.  
  2684. void DynamicObjectMove::print () {
  2685.   char * label;
  2686.   int i;
  2687.   fprintf (outputFile, "!   Dynamic Object Move: *");
  2688.   printANode (targetPtr);
  2689.   fprintf (outputFile, " = *");
  2690.   printANode (srcPtr);
  2691.   fprintf (outputFile, "\n");
  2692.   // Generate code to get pointers to the objects into r4 and r5...
  2693.   // fprintf (outputFile, "! get ptr to target into r4 and ptr to src into r5...\n");
  2694.   getIntoReg4 (targetPtr, "r4");
  2695.   getIntoReg4 (srcPtr, "r5");
  2696.   // Generate code to make sure the dispatch table ptrs are the same...
  2697.   // fprintf (outputFile, "! make sure the dispatch table ptrs are the same...\n");
  2698.   fprintf (outputFile, "\tload\t[r4],r1\n");
  2699.   fprintf (outputFile, "\tload\t[r5],r3\n");
  2700.   fprintf (outputFile, "\tcmp\tr1,r3\n");
  2701.   fprintf (outputFile, "\tbne\t_runtimeErrorWrongObject3\n");
  2702.   // Generate code to get the size in words into r3...
  2703.   // fprintf (outputFile, "! get size in words into r3...\n");
  2704.   fprintf (outputFile, "\tload\t[r3],r3\n");
  2705.   fprintf (outputFile, "\tload\t[r3+16],r3\n");
  2706.   fprintf (outputFile, "\tcmp\tr3,4\n");
  2707.   fprintf (outputFile, "\tbl\t_runtimeErrorBadObjectSize\n");
  2708.   fprintf (outputFile, "\tsrl\tr3,2,r3\n");
  2709.   // Generate code to move N bytes...
  2710.   //     r3 = counter of words
  2711.   //     r4 = ptr to dest
  2712.   //     r5 = ptr to source
  2713.   //     r1 = word being moved
  2714.   // fprintf (outputFile, "! do the move...\n");
  2715.   label = newLabel ();
  2716.   fprintf (outputFile, "%s:\n", label);
  2717.   fprintf (outputFile, "\tload\t[r5],r1\n");
  2718.   fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2719.   fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2720.   fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2721.   fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2722.   fprintf (outputFile, "\tbne\t%s\n", label);
  2723.   fprintf (outputFile, "! done with move\n");
  2724. }
  2725.  
  2726. void IRDynamicObjectMove (VarDecl * tar, VarDecl * src) {
  2727.   linkIR (new DynamicObjectMove (tar, src));
  2728. }
  2729.  
  2730.  
  2731.  
  2732. //   //----------  ZeroLocal  ----------
  2733. //   
  2734. //   void ZeroLocal::print () {
  2735. //     int i;
  2736. //     if (local->sizeInBytes == 1) {
  2737. //       fprintf (outputFile, "\tstoreb\tr0,[r14+%d]\n", local->offset);
  2738. //     } else {
  2739. //       if (local->sizeInBytes <= 20) {
  2740. //         for (i = 0; i < local->sizeInBytes; i = i + 4) {
  2741. //           fprintf (outputFile, "\tstore\tr0,[r14+%d]\n", local->offset + i);
  2742. //         }
  2743. //       } else {
  2744. //         printf ("UNIMPLEMENTED / UNTESTED: IRZeroLocal with large value\n");
  2745. //       }
  2746. //     }
  2747. //   }
  2748. //   
  2749. //   void IRZeroLocal (Local * loc) {
  2750. //     linkIR (new ZeroLocal (loc));
  2751. //   }
  2752.  
  2753.  
  2754.  
  2755. //----------  CheckDPT  ----------
  2756.  
  2757. void CheckDPT::print () {
  2758.   getIntoReg4 (var, "r1");
  2759.   fprintf (outputFile, "\tload\t[r1],r1\n");
  2760.   fprintf (outputFile, "\tset\t%s,r2\n", classDef->newName);
  2761.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  2762.   fprintf (outputFile, "\tbne\t_runtimeErrorWrongObject\n");
  2763. }
  2764.  
  2765. void IRCheckDPT (VarDecl * v, ClassDef * cl) {
  2766.   linkIR (new CheckDPT (v, cl));
  2767. }
  2768.  
  2769.  
  2770.  
  2771. //----------  CheckDPT2  ----------
  2772.  
  2773. void CheckDPT2::print () {
  2774.   getIntoReg4 (var, "r1");
  2775.   fprintf (outputFile, "\tload\t[r1],r1\n");
  2776.   fprintf (outputFile, "\tset\t%s,r2\n", classDef->newName);
  2777.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  2778.   fprintf (outputFile, "\tbne\t_runtimeErrorWrongObject2\n");
  2779. }
  2780.  
  2781. void IRCheckDPT2 (VarDecl * v, ClassDef * cl) {
  2782.   linkIR (new CheckDPT2 (v, cl));
  2783. }
  2784.  
  2785.  
  2786.  
  2787. //----------  CopyArrays  ----------
  2788.  
  2789. void CopyArrays::print () {
  2790.   char * label;
  2791.   int i;
  2792.   fprintf (outputFile, "!   Dynamic Array Copy: *");
  2793.   printANode (targetPtr);
  2794.   fprintf (outputFile, " = *");
  2795.   printANode (srcPtr);
  2796.   fprintf (outputFile, "\n");
  2797.   // Generate code to get pointers to the arrays into r4 and r5...
  2798.   fprintf (outputFile, "!     get ptr to target into r4 and ptr to src into r5...\n");
  2799.   getIntoReg4 (targetPtr, "r4");
  2800.   getIntoReg4 (srcPtr, "r5");
  2801.   // Generate code to make sure the sizes are the same...
  2802.   fprintf (outputFile, "!     make sure the sizes are the same...\n");
  2803.   fprintf (outputFile, "\tload\t[r4],r1\n");
  2804.   fprintf (outputFile, "\tload\t[r5],r3\n");
  2805.   fprintf (outputFile, "\tcmp\tr1,r3\n");
  2806.   fprintf (outputFile, "\tbne\t_runtimeErrorDifferentArraySizes\n");
  2807.   // Generate code to get the size in words into r3...
  2808.   fprintf (outputFile, "!     get size in words into r3...\n");
  2809.   if (within16Bits (elementSize)) {
  2810.     fprintf (outputFile, "\tmul\tr3,%d,r3\t\t! multiply by size of elements\n", elementSize);
  2811.   } else {
  2812.     // printf ("16-BIT OVERFLOW;  DEST = %s, SOURCE = %s, ELEMENT SIZE = %d\n",
  2813.     //         ((VarDecl *) targetPtr)->id->chars, ((VarDecl *) srcPtr)->id->chars,
  2814.     //         elementSize);
  2815.     fprintf (outputFile, "\tset\t%d,r11\t\t! multiply by size of elements\n", elementSize);
  2816.     fprintf (outputFile, "\tmul\tr3,r11,r3\n");
  2817.   }
  2818.   overflowTest ();
  2819.   fprintf (outputFile, "\tadd\tr3,7,r3\t\t! add 4 and divide by 4, rounding up\n");
  2820.   overflowTest ();
  2821.   fprintf (outputFile, "\tsrl\tr3,2,r3\n");
  2822.   // Generate code to move N bytes...
  2823.   //     r3 = counter of words
  2824.   //     r4 = ptr to dest
  2825.   //     r5 = ptr to source
  2826.   //     r1 = word being moved
  2827.   fprintf (outputFile, "!     do the move...\n");
  2828.   label = newLabel ();
  2829.   fprintf (outputFile, "%s:\n", label);
  2830.   fprintf (outputFile, "\tload\t[r5],r1\n");
  2831.   fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2832.   fprintf (outputFile, "\tstore\tr1,[r4]\n");
  2833.   fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2834.   fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2835.   fprintf (outputFile, "\tbne\t%s\n", label);
  2836.   fprintf (outputFile, "! done with move\n");
  2837. }
  2838.  
  2839. void IRCopyArrays (VarDecl * tar, VarDecl * src, int i) {
  2840.   linkIR (new CopyArrays (tar, src, i));
  2841. }
  2842.  
  2843.  
  2844.  
  2845. //----------  CheckArraySizeInt  ----------
  2846.  
  2847. void CheckArraySizeInt::print () {
  2848.   // This instruction is passed a variable "ptr", which contains the address
  2849.   // of an array, and "numberOfElements", which is the expected size of the
  2850.   // the array.  It signals an error if the array does not have that size.
  2851.   fprintf (outputFile, "!   make sure array has size %d\n", numberOfElements);
  2852.   getIntoReg4 (ptr, "r1");
  2853.   fprintf (outputFile, "\tload\t[r1],r1\n");
  2854.   fprintf (outputFile, "\tset\t%d, r2\n", numberOfElements);
  2855.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  2856.   overflowTest ();
  2857.   fprintf (outputFile, "\tbne\t_runtimeErrorWrongArraySize\n");
  2858. }
  2859.  
  2860. void IRCheckArraySizeInt (VarDecl * p, int i) {
  2861.   linkIR (new CheckArraySizeInt (p, i));
  2862. }
  2863.  
  2864.  
  2865.  
  2866. //----------  CheckArraySizeInt2  ----------
  2867.  
  2868. void CheckArraySizeInt2::print () {
  2869.   // This instruction is passed a variable "ptr", which contains the address
  2870.   // of an array, and "numberOfElements", which is the expected size of the
  2871.   // the array.  It signals an error if the array does not have that size.
  2872.   // HOWEVER: If the array size if zero (i.e., the array is uninitialized), it
  2873.   // ignores the previous size.
  2874.   char * label;
  2875.   fprintf (outputFile, "!   make sure array has size %d\n", numberOfElements);
  2876.   getIntoReg4 (ptr, "r1");
  2877.   fprintf (outputFile, "\tload\t[r1],r1\n");
  2878.   fprintf (outputFile, "\tset\t%d, r2\n", numberOfElements);
  2879.   fprintf (outputFile, "\tcmp\tr1,0\n");
  2880.   label = newLabel ();
  2881.   fprintf (outputFile, "\tbe\t%s\n", label);
  2882.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  2883.   overflowTest ();
  2884.   fprintf (outputFile, "\tbne\t_runtimeErrorWrongArraySize\n");
  2885.   fprintf (outputFile, "%s:\n", label);
  2886. }
  2887.  
  2888. void IRCheckArraySizeInt2 (VarDecl * p, int i) {
  2889.   linkIR (new CheckArraySizeInt2 (p, i));
  2890. }
  2891.  
  2892.  
  2893.  
  2894. //----------  ArrayIndex  ----------
  2895.  
  2896. void ArrayIndex::print () {
  2897.   fprintf (outputFile, "!   Move address of ");
  2898.   printANode (baseAddr);
  2899.   fprintf (outputFile, " [");
  2900.   printANode (indexVal);
  2901.   fprintf (outputFile, " ] into ");
  2902.   printANode (result);
  2903.   fprintf (outputFile, "\n");
  2904.   fprintf (outputFile, "!     make sure index expr is >= 0\n");
  2905.   getIntoReg4 (indexVal, "r2");
  2906.   fprintf (outputFile, "\tcmp\tr2,0\n");
  2907.   fprintf (outputFile, "\tbl\t_runtimeErrorBadArrayIndex\n");
  2908.   fprintf (outputFile, "!     make sure index expr is < array size\n");
  2909.   getIntoReg4 (baseAddr, "r1");
  2910.   fprintf (outputFile, "\tload\t[r1],r3\n");
  2911.   fprintf (outputFile, "\tcmp\tr3,0\n");
  2912.   fprintf (outputFile, "\tble\t_runtimeErrorUninitializedArray\n");
  2913.   fprintf (outputFile, "\tcmp\tr2,r3\n");
  2914.   overflowTest ();
  2915.   fprintf (outputFile, "\tbge\t_runtimeErrorBadArrayIndex\n");
  2916.   fprintf (outputFile, "!     compute address of array element\n");
  2917.   fprintf (outputFile, "\tset\t%d,r3\n", elementSize);
  2918.   fprintf (outputFile, "\tmul\tr2,r3,r2\n");
  2919.   fprintf (outputFile, "\tadd\tr2,4,r2\n");
  2920.   fprintf (outputFile, "\tadd\tr2,r1,r2\n");
  2921.   storeFromReg4 (result, "r2", "r1");
  2922. }
  2923.  
  2924. void IRArrayIndex (VarDecl * b, AstNode * i, VarDecl * r, int sz) {
  2925.   linkIR (new ArrayIndex (b, i, r, sz));
  2926. }
  2927.  
  2928.  
  2929.  
  2930. //----------  TestObjEq  ----------
  2931.  
  2932. void TestObjEq::print () {
  2933.   char * label;
  2934.   fprintf (outputFile, "!   TEST OBJECT EQUALITY: if * ");
  2935.   printANode (ptr1);
  2936.   fprintf (outputFile, " == * ");
  2937.   printANode (ptr2);
  2938.   fprintf (outputFile, " goto %s else goto %s\n", trueLabel, falseLabel);
  2939.  
  2940.   // Generate code to get pointers to the objects into r4 and r5...
  2941.   fprintf (outputFile, "!    get ptr1 into r4 and ptr2 into r5...\n");
  2942.   getIntoReg4 (ptr1, "r4");
  2943.   getIntoReg4 (ptr2, "r5");
  2944.  
  2945.   // Generate code to make sure the dispatch table ptrs are the same...
  2946.   fprintf (outputFile, "!    make sure the dispatch table ptrs are the same...\n");
  2947.   fprintf (outputFile, "\tload\t[r4],r1\n");
  2948.   fprintf (outputFile, "\tcmp\tr1,0\n");
  2949.   fprintf (outputFile, "\tbe\t_runtimeErrorUninitializedObject\n");
  2950.   fprintf (outputFile, "\tload\t[r5],r3\n");
  2951.   fprintf (outputFile, "\tcmp\tr3,0\n");
  2952.   fprintf (outputFile, "\tbe\t_runtimeErrorUninitializedObject\n");
  2953.   fprintf (outputFile, "\tcmp\tr1,r3\n");
  2954.   fprintf (outputFile, "\tbne\t%s\n", falseLabel);
  2955.   // Generate code to get the size in words into r3...
  2956.   fprintf (outputFile, "!    get size in words into r3...\n");
  2957.   fprintf (outputFile, "\tload\t[r3],r3\n");
  2958.   fprintf (outputFile, "\tload\t[r3+16],r3\n");
  2959.   fprintf (outputFile, "\tcmp\tr3,4\n");
  2960.   fprintf (outputFile, "\tbl\t_runtimeErrorBadObjectSize\n");
  2961.   fprintf (outputFile, "\tsrl\tr3,2,r3\n");
  2962.   // Generate code to test N bytes...
  2963.   //     r3 = counter of words
  2964.   //     r4 = ptr to dest -- ptr1
  2965.   //     r5 = ptr to source -- ptr2
  2966.   //     r1 = word from *ptr1
  2967.   //     r2 = word from *ptr2
  2968.   fprintf (outputFile, "!    do the testing in a loop...\n");
  2969.   label = newLabel ();
  2970.   fprintf (outputFile, "%s:\n", label);
  2971.   fprintf (outputFile, "\tload\t[r4],r1\n");
  2972.   fprintf (outputFile, "\tadd\tr4,4,r4\n");
  2973.   fprintf (outputFile, "\tload\t[r5],r2\n");
  2974.   fprintf (outputFile, "\tadd\tr5,4,r5\n");
  2975.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  2976.   fprintf (outputFile, "\tbne\t%s\n", falseLabel);
  2977.   fprintf (outputFile, "\tsub\tr3,1,r3\n");
  2978.   fprintf (outputFile, "\tbne\t%s\n", label);
  2979.   fprintf (outputFile, "\tjmp\t%s\n", trueLabel);
  2980.   fprintf (outputFile, "!    done with test\n");
  2981. }
  2982.  
  2983. void IRTestObjEq (VarDecl * ptr1, VarDecl * ptr2, char * trueLabel, char * falseLabel) {
  2984.   linkIR (new TestObjEq (ptr1, ptr2, trueLabel, falseLabel));
  2985. }
  2986.  
  2987.  
  2988.  
  2989. //----------  ForTest  ----------
  2990.  
  2991. void ForTest::print () {
  2992.   fprintf (outputFile, "!   Perform the FOR-LOOP termination test\n");
  2993.   fprintf (outputFile, "!   if * ");
  2994.   printANode (ptr);
  2995.   fprintf (outputFile, " > ");
  2996.   printANode (stopVal);
  2997.   fprintf (outputFile, " then goto %s\t\t\n", exitLabel);
  2998.   getIntoReg4 (ptr, "r1");
  2999.   fprintf (outputFile, "\tload\t[r1],r1\n");
  3000.   getIntoReg4 (stopVal, "r2");
  3001.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  3002.   overflowTest ();
  3003.   fprintf (outputFile, "\tbg\t%s\n", exitLabel);
  3004. }
  3005.  
  3006. void IRForTest (VarDecl * pt, AstNode * st, char * lab) {
  3007.   linkIR (new ForTest (pt, st, lab));
  3008. }
  3009.  
  3010.  
  3011.  
  3012. //----------  ForTest2  ----------
  3013.  
  3014. void ForTest2::print () {
  3015.   fprintf (outputFile, "!   Perform the FOR-LOOP termination test\n");
  3016.   fprintf (outputFile, "!   if ");
  3017.   printANode (var);
  3018.   fprintf (outputFile, " > ");
  3019.   printANode (stopVal);
  3020.   fprintf (outputFile, " then goto %s\t\t\n", exitLabel);
  3021.   getIntoReg4 (var, "r1");
  3022.   getIntoReg4 (stopVal, "r2");
  3023.   fprintf (outputFile, "\tcmp\tr1,r2\n");
  3024.   overflowTest ();
  3025.   fprintf (outputFile, "\tbg\t%s\n", exitLabel);
  3026. }
  3027.  
  3028. void IRForTest2 (VarDecl * v, AstNode * st, char * lab) {
  3029.   linkIR (new ForTest2 (v, st, lab));
  3030. }
  3031.  
  3032.  
  3033.  
  3034. //----------  IncrVarDirect  ----------
  3035. //
  3036. // IRIncrVarDirect (VarDecl * dest, VarDecl * src, AstNode * incr, int incrInt, int wantOverflowTest)
  3037. //
  3038. // 
  3039. void IncrVarDirect::print () {
  3040.   fprintf (outputFile, "!   ");
  3041.   printANode (dest);
  3042.   fprintf (outputFile, " = ");
  3043.   printANode (src);
  3044.   fprintf (outputFile, " + ");
  3045.   if (incr == NULL) {
  3046.     fprintf (outputFile, "%d\n", incrInt);
  3047.   } else {
  3048.     printANode (incr);
  3049.     fprintf (outputFile, "\n");
  3050.   }
  3051.  
  3052.   getIntoReg4 (src, "r1");
  3053.   if (incr == NULL) {
  3054.     if (within16Bits (incrInt)) {
  3055.       fprintf (outputFile, "\tadd\tr1,%d,r1\n", incrInt);
  3056.     } else {
  3057.       fprintf (outputFile, "\tset\t0x%08x,r2\t\t\t! decimal = %d\n", incrInt, incrInt);
  3058.       fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  3059.     }
  3060.   } else {
  3061.     getIntoReg4 (incr, "r2");
  3062.     fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  3063.   }
  3064.   if (wantOverflowTest) {
  3065.     overflowTest ();
  3066.   }
  3067.   storeFromReg4 (dest, "r1", "r2");
  3068. }
  3069.  
  3070. void IRIncrVarDirect (VarDecl * dest, VarDecl * src,
  3071.                       AstNode * incr, int incrInt, int wantOverflowTest) {
  3072.   linkIR (new IncrVarDirect (dest, src, incr, incrInt, wantOverflowTest));
  3073. }
  3074.  
  3075.  
  3076.  
  3077. //----------  IncrVarIndirect  ----------
  3078.  
  3079. void IncrVarIndirect::print () {
  3080.   getIntoReg4 (ptr, "r1");
  3081.   fprintf (outputFile, "\tload\t[r1],r3\n");
  3082.   if (incr == NULL) {
  3083.     if (within16Bits (incrInt)) {
  3084.       fprintf (outputFile, "\tadd\tr3,%d,r3\n", incrInt);
  3085.     } else {
  3086.       fprintf (outputFile, "\tset\t0x%08x,r2\t\t\t! decimal = %d\n", incrInt, incrInt);
  3087.       fprintf (outputFile, "\tadd\tr3,r2,r3\n");
  3088.     }
  3089.     overflowTest ();
  3090.   } else {
  3091.     getIntoReg4 (incr, "r2");
  3092.     fprintf (outputFile, "\tadd\tr3,r2,r3\n");
  3093.     overflowTest ();
  3094.   }
  3095.   fprintf (outputFile, "\tstore\tr3,[r1]\n");
  3096. }
  3097.  
  3098. void IRIncrVarIndirect (VarDecl * p, VarDecl * i, int i2) {
  3099.   linkIR (new IncrVarIndirect (p, i, i2));
  3100. }
  3101.  
  3102.  
  3103.  
  3104. //----------  MultiplyVarImmed  ----------
  3105.  
  3106. void MultiplyVarImmed::print () {
  3107.   fprintf (outputFile, "!   ");
  3108.   printANode (dest);
  3109.   fprintf (outputFile, " = ");
  3110.   printANode (src);
  3111.   fprintf (outputFile, " * %d\n", ivalue);
  3112.  
  3113.   getIntoReg4 (src, "r1");
  3114.   if (within16Bits (ivalue)) {
  3115.     fprintf (outputFile, "\tmul\tr1,%d,r1\n", ivalue);
  3116.     overflowTest ();
  3117.   } else {
  3118.     fprintf (outputFile, "\tset\t0x%08x,r2\t\t\t! decimal = %d\n", ivalue, ivalue);
  3119.     fprintf (outputFile, "\tmul\tr1,r2,r1\n");
  3120.     overflowTest ();
  3121.   }
  3122.   storeFromReg4 (dest, "r1", "r2");
  3123. }
  3124.  
  3125. void IRMultiplyVarImmed (VarDecl * dest, VarDecl * src, int ivalue) {
  3126.   linkIR (new MultiplyVarImmed (dest, src, ivalue));
  3127. }
  3128.  
  3129.  
  3130.  
  3131. //----------  SwitchReg1  ----------
  3132.  
  3133. void SwitchReg1::print () {
  3134.   getIntoReg4 (expr, "r1");
  3135. }
  3136.  
  3137. void IRSwitchReg1 (AstNode * e) {
  3138.   linkIR (new SwitchReg1 (e));
  3139. }
  3140.  
  3141.  
  3142.  
  3143. //----------  SwitchTestReg1  ----------
  3144.  
  3145. void SwitchTestReg1::print () {
  3146.   if (within16Bits (ivalue)) {
  3147.     fprintf (outputFile, "\tcmp\tr1,%d\n", ivalue);
  3148.   } else {
  3149.     fprintf (outputFile, "\tset\t%d,r2\n", ivalue);
  3150.     fprintf (outputFile, "\tcmp\tr1,r2\n");
  3151.   }
  3152.   fprintf (outputFile, "\tbe\t%s\n", label);
  3153. }
  3154.  
  3155. void IRSwitchTestReg1 (int i, char * l) {
  3156.   linkIR (new SwitchTestReg1 (i, l));
  3157. }
  3158.  
  3159.  
  3160.  
  3161. //----------  SwitchDirect  ----------
  3162.  
  3163. void SwitchDirect::print () {
  3164.   char * okLabel = newLabel ();
  3165.   getIntoReg4 (expr, "r1");
  3166.   // Make sure the expr is not negative...
  3167.   fprintf (outputFile, "!   If ");
  3168.   printANode (expr);
  3169.   fprintf (outputFile, " is not within 16-bits goto default code\n");
  3170.   fprintf (outputFile, "\tsrl\tr1,15,r2\n");
  3171.   fprintf (outputFile, "\tcmp\tr2,0\n");
  3172.   fprintf (outputFile, "\tbe\t%s\n", okLabel);
  3173.   fprintf (outputFile, "\tset\t0x1ffff,r3\n");
  3174.   fprintf (outputFile, "\tcmp\tr2,r3\n");
  3175.   fprintf (outputFile, "\tbne\t%s\n", defaultLabel);
  3176.   fprintf (outputFile, "%s:\n", okLabel);
  3177.   // Make sure the expr is not < lowValue...
  3178.   fprintf (outputFile, "!   If ");
  3179.   printANode (expr);
  3180.   fprintf (outputFile, " is < %d (==smallestCaseValue) goto default code\n", lowValue, highValue);
  3181.   fprintf (outputFile, "\tcmp\tr1,%d\n", lowValue);
  3182.   // (Overflow cannot occur since r1 and lowValue are both within -32768..32767.)
  3183.   fprintf (outputFile, "\tbl\t%s\n", defaultLabel);
  3184.   // Make sure the expr is not > highValue...
  3185.   // (Overflow cannot occur since r1 and highValue are both within -32768..32767.)
  3186.   fprintf (outputFile, "!   If ");
  3187.   printANode (expr);
  3188.   fprintf (outputFile, " is > %d (==greatestCaseValue) goto default code\n", highValue);
  3189.   fprintf (outputFile, "\tcmp\tr1,%d\n", highValue);
  3190.   fprintf (outputFile, "\tbg\t%s\n", defaultLabel);
  3191.   fprintf (outputFile, "!   r1 = (r1-lowValue) * 4 + jumpTableAddr\n");
  3192.   fprintf (outputFile, "\tsub\tr1,%d,r1\n", lowValue);
  3193.   fprintf (outputFile, "\tsll\tr1,2,r1\n");
  3194.   fprintf (outputFile, "\tset\t%s,r2\n", directTable);
  3195.   fprintf (outputFile, "\tadd\tr1,r2,r1\n");
  3196.   fprintf (outputFile, "!   Jump indirect through the jump table\n");
  3197.   fprintf (outputFile, "\tjmp\tr1\n");
  3198. }
  3199.  
  3200. void IRSwitchDirect (AstNode * e, char * tab, char * def, int low, int high) {
  3201.   linkIR (new SwitchDirect (e, tab, def, low, high));
  3202. }
  3203.  
  3204.  
  3205.  
  3206. //----------  SwitchHashJump  ----------
  3207.  
  3208. void SwitchHashJump::print () {
  3209.   char * loopLabel = newLabel ();
  3210.   char * incrLabel = newLabel ();
  3211.   getIntoReg4 (expr, "r1");
  3212.   fprintf (outputFile, "!   r2 = hashValue (r1)\n");
  3213.   fprintf (outputFile, "\trem\tr1,%d,r2\n", tableSize);
  3214.   fprintf (outputFile, "!   LOOP: r5 = addr of hashTable [r2 * 8 + 4]\n");
  3215.   fprintf (outputFile, "%s:\n", loopLabel);
  3216.   fprintf (outputFile, "\tsll\tr2,3,r5\n");
  3217.   fprintf (outputFile, "\tadd\tr5,%s+4,r5\n", tableName);
  3218.   fprintf (outputFile, "!   r3 = the label for this table entry\n");
  3219.   fprintf (outputFile, "\tload\t[r5],r3\n");
  3220.   fprintf (outputFile, "!   If r3 == 0 goto default code\n");
  3221.   fprintf (outputFile, "\tcmp\tr3,0\n");
  3222.   fprintf (outputFile, "\tbe\t%s\n", defaultLabel);
  3223.   fprintf (outputFile, "!   r4 = the value for this table entry\n");
  3224.   fprintf (outputFile, "\tload\t[r5+-4],r4\n");
  3225.   fprintf (outputFile, "!   If r1 != r4 goto %s\n", incrLabel);
  3226.   fprintf (outputFile, "\tcmp\tr1,r4\n");
  3227.   fprintf (outputFile, "\tbne\t%s\n", incrLabel);
  3228.   fprintf (outputFile, "!   Jump indirect through r3\n");
  3229.   fprintf (outputFile, "\tjmp\tr3\n");
  3230.   fprintf (outputFile, "%s:\n", incrLabel);
  3231.   fprintf (outputFile, "!   r2 = r2+1\n");
  3232.   fprintf (outputFile, "\tadd\tr2,1,r2\n");
  3233.   fprintf (outputFile, "!   If r2 != tableSize goto LOOP\n");
  3234.   fprintf (outputFile, "\tcmp\tr2,%d\n", tableSize);
  3235.   fprintf (outputFile, "\tbne\t%s\n", loopLabel);
  3236.   fprintf (outputFile, "!   r2 = 0\n");
  3237.   fprintf (outputFile, "\tmov\t0,r2\n");
  3238.   fprintf (outputFile, "!   Goto LOOP\n");
  3239.   fprintf (outputFile, "\tjmp\t%s\n", loopLabel);
  3240. }
  3241.  
  3242. void IRSwitchHashJump (AstNode * e, char * tab, char * def, int sz) {
  3243.   linkIR (new SwitchHashJump (e, tab, def, sz));
  3244. }
  3245.  
  3246.  
  3247.  
  3248. //----------  Alloc  ----------
  3249.  
  3250. void Alloc::print () {
  3251.   fprintf (outputFile, "!   ");
  3252.   printANode (dest);
  3253.   fprintf (outputFile, " = alloc (");
  3254.   printANode (byteCount);
  3255.   fprintf (outputFile, ")\n");
  3256.  
  3257.   getIntoReg4 (byteCount, "r1");
  3258.   fprintf (outputFile, "\tcall\t_heapAlloc\n");  // Will not return NULL
  3259.   storeFromReg4 (dest, "r1", "r2");
  3260. }
  3261.  
  3262. void IRAlloc (VarDecl * dest, VarDecl * byteCount) {
  3263.   linkIR (new Alloc (dest, byteCount));
  3264. }
  3265.  
  3266.  
  3267.  
  3268. //----------  Free  ----------
  3269.  
  3270. void Free::print () {
  3271.   fprintf (outputFile, "!   Free (");
  3272.   printANode (ptr);
  3273.   fprintf (outputFile, ")\n");
  3274.  
  3275.   getIntoReg4 (ptr, "r1");
  3276.   fprintf (outputFile, "\tcall\t_heapFree\n");
  3277. }
  3278.  
  3279. void IRFree (AstNode * ptr) {
  3280.   linkIR (new Free (ptr));
  3281. }
  3282.  
  3283.  
  3284.  
  3285. //----------  SaveCatchStack  ----------
  3286.  
  3287. void SaveCatchStack::print () {
  3288.   fprintf (outputFile, "!   Save Catch Stack to ");
  3289.   printANode (temp);
  3290.   fprintf (outputFile, "\n");
  3291.   storeFromReg4 (temp, "r12", "r2");
  3292. }
  3293.  
  3294. void IRSaveCatchStack (VarDecl * temp) {
  3295.   linkIR (new SaveCatchStack (temp));
  3296. }
  3297.  
  3298.  
  3299.  
  3300. //----------  RestoreCatchStack  ----------
  3301.  
  3302. void RestoreCatchStack::print () {
  3303.   // This instruction does the following.  Since the code sequence is
  3304.   // is lengthy, most of the work is done in a routine in "runtime.s".
  3305.   //        load   <temp>, r4
  3306.   //        r1 := r12 (CatchStack top ptr)
  3307.   //        r12 := r4
  3308.   //    loop:
  3309.   //        if r1 == r4 goto done
  3310.   //        if r1 == NULL goto _runtimeErrorRestoreCatchStackError
  3311.   //        load   [r1], r2
  3312.   //        push   r2
  3313.   //        push   r4
  3314.   //        free   (r1)
  3315.   //        pop    r4
  3316.   //        pop    r1
  3317.   //        goto   loop
  3318.   //    done:
  3319.  
  3320.   fprintf (outputFile, "!   Restore Catch Stack from ");
  3321.   printANode (temp);
  3322.   fprintf (outputFile, "\n");
  3323.   getIntoReg4 (temp, "r4");
  3324.   fprintf (outputFile, "\tcall\t_RestoreCatchStack\n");    
  3325. }
  3326.  
  3327. void IRRestoreCatchStack (VarDecl * temp) {
  3328.   linkIR (new RestoreCatchStack (temp));
  3329. }
  3330.  
  3331.  
  3332.  
  3333. //----------  PushCatchRecord  ----------
  3334.  
  3335. void PushCatchRecord::print () {
  3336.   // Generate this code...
  3337.   //     r1 = alloc (28)
  3338.   //     r1->0 = r12 (catchStack top ptr)
  3339.   //     r1->4 = errorID
  3340.   //     r1->8 = catchCodeAddr
  3341.   //     r1->12 = r14
  3342.   //     r1->16 = r15
  3343.   //     r1->20 = ptr to source file name
  3344.   //     r1->24 = source line number
  3345.   //     r12 = r1
  3346.   //
  3347.   fprintf (outputFile, "!   Push Catch Record\n");
  3348.   fprintf (outputFile, "\tmov\t28,r1\n");
  3349.   fprintf (outputFile, "\tcall\t_heapAlloc\n");
  3350.   fprintf (outputFile, "\tstore\tr12,[r1]\n");
  3351.   fprintf (outputFile, "\tset\t%s,r2\n", cat->myDef->newName);
  3352.   fprintf (outputFile, "\tstore\tr2,[r1+4]\n");
  3353.   fprintf (outputFile, "\tset\t%s,r2\n", cat->label);
  3354.   fprintf (outputFile, "\tstore\tr2,[r1+8]\n");
  3355.   fprintf (outputFile, "\tstore\tr14,[r1+12]\n");
  3356.   fprintf (outputFile, "\tstore\tr15,[r1+16]\n");
  3357.   fprintf (outputFile, "\tset\t_sourceFileName,r2\n");
  3358.   fprintf (outputFile, "\tstore\tr2,[r1+20]\n");
  3359.   fprintf (outputFile, "\tset\t%d,r2\n", extractLineNumber (cat->tokn));
  3360.   fprintf (outputFile, "\tstore\tr2,[r1+24]\n");
  3361.   fprintf (outputFile, "\tmov\tr1,r12\n");
  3362.   // fprintf (outputFile, "\tdebug\n");
  3363. }
  3364.  
  3365. void IRPushCatchRecord (Catch * cat) {
  3366.   linkIR (new PushCatchRecord (cat));
  3367. }
  3368.  
  3369.  
  3370.  
  3371. //----------  Throw  ----------
  3372.  
  3373. void Throw::print () {
  3374.   fprintf (outputFile, "\tset\t%s,r4\n", errorDecl->newName);
  3375.   fprintf (outputFile, "\tjmp\t_PerformThrow\n");
  3376. }
  3377.  
  3378. void IRThrow (ErrorDecl * errorDecl) {
  3379.   linkIR (new Throw (errorDecl));
  3380. }
  3381.  
  3382.  
  3383.  
  3384. //----------  CopyCatchParm  ----------
  3385.  
  3386. void CopyCatchParm::print () {
  3387.   char * label;
  3388.   int sizeInBytes = parm->sizeInBytes;
  3389.  
  3390.   // fprintf (outputFile, "debug\n");
  3391.  
  3392.   fprintf (outputFile, "!   Copy catch arg to parm %s, offset=%d, throwSideOffset=%d, sizeInBytes=%d\n",
  3393.          parm->id->chars,
  3394.          parm->offset,
  3395.          parm->throwSideOffset,
  3396.          sizeInBytes);
  3397.   // printf ("Parm=%s     Offset=%d    ThrowSideOffset=%d    SizeInBytes=%d\n",
  3398.   //        parm->id->chars,
  3399.   //        parm->offset,
  3400.   //        parm->throwSideOffset,
  3401.   //        sizeInBytes);
  3402.  
  3403.   // At this point, r15 is the old SP, and will be used to acess the src args
  3404.  
  3405.   if (sizeInBytes == 1 || sizeInBytes == 4 || sizeInBytes == 8) {
  3406.     if (within16Bits (parm->throwSideOffset)) {
  3407.       if (sizeInBytes == 1) {
  3408.         fprintf (outputFile, "\tloadb\t[r15+%d], r1\n", parm->throwSideOffset);
  3409.       } else if (sizeInBytes == 4) {
  3410.         fprintf (outputFile, "\tload\t[r15+%d], r1\n", parm->throwSideOffset);
  3411.       } else if (sizeInBytes == 8) {
  3412.         fprintf (outputFile, "\tfload\t[r15+%d], f0\n", parm->throwSideOffset);
  3413.       }
  3414.     } else {
  3415.       // printf ("          throwSideOffset exceeds 16-bit size limitation: %s, %d\n",
  3416.       //         parm->id->chars, parm->throwSideOffset);
  3417.       if (sizeInBytes == 1) {
  3418.         fprintf (outputFile, "\tset\t%d, r11\n", parm->throwSideOffset);
  3419.         fprintf (outputFile, "\tloadb\t[r15+r11], r1\n");
  3420.       } else if (sizeInBytes == 4) {
  3421.         fprintf (outputFile, "\tset\t%d, r11\n", parm->throwSideOffset);
  3422.         fprintf (outputFile, "\tload\t[r15+r11], r1\n");
  3423.       } else if (sizeInBytes == 8) {
  3424.         fprintf (outputFile, "\tset\t%d, r11\n", parm->throwSideOffset);
  3425.         fprintf (outputFile, "\tfload\t[r15+r11], f0\n");
  3426.       }
  3427.     }
  3428.     if (within16Bits (parm->offset)) {
  3429.       if (sizeInBytes == 1) {
  3430.         fprintf (outputFile, "\tstoreb\tr1,[r14+%d]\n", parm->offset);
  3431.       } else if (sizeInBytes == 4) {
  3432.         fprintf (outputFile, "\tstore\tr1,[r14+%d]\n", parm->offset);
  3433.       } else if (sizeInBytes == 8) {
  3434.         fprintf (outputFile, "\tfstore\tf0,[r14+%d]\n", parm->offset);
  3435.       }
  3436.     } else {
  3437.       // printf ("          offset exceeds 16-bit size limitation: %s, %d\n",
  3438.       //         parm->id->chars, parm->offset);
  3439.       if (sizeInBytes == 1) {
  3440.         fprintf (outputFile, "\tset\t%d, r11\n", parm->offset);
  3441.         fprintf (outputFile, "\tstoreb\tr1,[r14+r11]\n");
  3442.       } else if (sizeInBytes == 4) {
  3443.         fprintf (outputFile, "\tset\t%d, r11\n", parm->offset);
  3444.         fprintf (outputFile, "\tstore\tr1,[r14+r11]\n");
  3445.       } else if (sizeInBytes == 8) {
  3446.         fprintf (outputFile, "\tset\t%d, r11\n", parm->offset);
  3447.         fprintf (outputFile, "\tfstore\tf0,[r14+r11]\n");
  3448.       }
  3449.     }
  3450.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  3451.     printf ("sizeInBytes = %d\n", sizeInBytes);
  3452.     programLogicError ("In CopyCatchParm, problems with sizeInBytes");
  3453.   } else {
  3454.     // Generate code to move N bytes into the arg position...
  3455.     //     r3 = counter of words
  3456.     //     r4 = ptr to dest
  3457.     //     r5 = ptr to source
  3458.     //     r1 = word being moved
  3459.     label = newLabel ();
  3460.     if (within16Bits (sizeInBytes / 4)) {
  3461.       fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  3462.     } else {
  3463.       fprintf (outputFile, "\tset\t%d,r3\n", sizeInBytes / 4);
  3464.       // printf ("In IRCopyCatchParm, sizeInBytes / 4 exceeds 16-bit size limitation: %s\n",
  3465.       //         parm->id->chars);
  3466.     }
  3467.     if (within16Bits (parm->offset)) {
  3468.       fprintf (outputFile, "\tadd\tr14,%d,r4\n", parm->offset);
  3469.     } else {
  3470.       fprintf (outputFile, "\tset\t%d,r11\n", parm->offset);
  3471.       fprintf (outputFile, "\tadd\tr14,r11,r4\n");
  3472.       // printf ("In IRCopyCatchParm, offset exceeds 16-bit size limitation: %s\n",
  3473.       //         parm->id->chars);
  3474.     }
  3475.     if (within16Bits (parm->throwSideOffset)) {
  3476.       fprintf (outputFile, "\tadd\tr15,%d,r5\n", parm->throwSideOffset);
  3477.     } else {
  3478.       fprintf (outputFile, "\tset\t%d,r11\n", parm->throwSideOffset);
  3479.       fprintf (outputFile, "\tadd\tr15,r11,r5\n");
  3480.       // printf ("In IRCopyCatchParm, throwSideOffset exceeds 16-bit size limitation: %s\n",
  3481.       //         parm->id->chars);
  3482.     }
  3483.     fprintf (outputFile, "%s:\n", label);
  3484.     fprintf (outputFile, "\tload\t[r5],r1\n");
  3485.     fprintf (outputFile, "\tadd\tr5,4,r5\n");
  3486.     fprintf (outputFile, "\tstore\tr1,[r4]\n");
  3487.     fprintf (outputFile, "\tadd\tr4,4,r4\n");
  3488.     fprintf (outputFile, "\tsub\tr3,1,r3\n");
  3489.     fprintf (outputFile, "\tbne\t%s\n", label);
  3490.   }
  3491.  
  3492.  
  3493.  
  3494. }
  3495.  
  3496. void IRCopyCatchParm (Parameter * parm) {
  3497.   linkIR (new CopyCatchParm (parm));
  3498. }
  3499.  
  3500.  
  3501.  
  3502. //----------  ResetStack  ----------
  3503.  
  3504. void ResetStack::print () {
  3505.   fprintf (outputFile, "\tmov\tr6,r15\t\t! Done copying args so reset stack\n");
  3506. }
  3507.  
  3508. void IRResetStack () {
  3509.   linkIR (new ResetStack ());
  3510. }
  3511.  
  3512.  
  3513.  
  3514. //----------  IsKindOf  ----------
  3515.  
  3516. void IsKindOf::print () {
  3517.   if (target) {
  3518.     fprintf (outputFile, "!   ");
  3519.     printANode (target);
  3520.     fprintf (outputFile, " = IsKindOf (");
  3521.     printANode (temp);
  3522.     fprintf (outputFile, ", %s)\n", descLab);
  3523.   } else {
  3524.     fprintf (outputFile, "!   if not isKindOf (");
  3525.     printANode (temp);
  3526.     fprintf (outputFile, ", %s) then goto %s\n", descLab, falseLabel);
  3527.   }
  3528.   getIntoReg4 (temp, "r1");
  3529.   fprintf (outputFile, "\tset\t%s,r2\n", descLab);
  3530.   fprintf (outputFile, "\tcall\t_IsKindOf\n");
  3531.   // If we have a target, move r1 into it...
  3532.   if (target) {
  3533.     storeFromReg1 (target, "r1", "r2");
  3534.   // Else, generate a jump if false, and fall thru otherwise...
  3535.   } else {
  3536.     fprintf (outputFile, "\tcmp\tr1,0\n");
  3537.     fprintf (outputFile, "\tbe\t%s\n", falseLabel);
  3538.   }
  3539. }
  3540.  
  3541. void IRIsKindOf (VarDecl * target, VarDecl * temp, char * descLab, char * falseLabel) {
  3542.   linkIR (new IsKindOf (target, temp, descLab, falseLabel));
  3543. }
  3544.  
  3545.  
  3546.  
  3547. //----------  IsInstanceOf  ----------
  3548.  
  3549. void IsInstanceOf::print () {
  3550.   char * retLabel, * return0;
  3551.   if (target) {
  3552.     fprintf (outputFile, "!   ");
  3553.     printANode (target);
  3554.     fprintf (outputFile, " = IsInstanceOf (");
  3555.     printANode (temp);
  3556.     fprintf (outputFile, ", %s)\n", descLab);
  3557.   } else {
  3558.     fprintf (outputFile, "!   if not IsInstanceOf (");
  3559.     printANode (temp);
  3560.     fprintf (outputFile, ", %s) then goto %s\n", descLab, falseLabel);
  3561.   }
  3562.   getIntoReg4 (temp, "r1");
  3563.   fprintf (outputFile, "\tcmp\tr1,0\n");
  3564.   fprintf (outputFile, "\tbe\t_runtimeErrorNullPointer\n");
  3565.   fprintf (outputFile, "\tset\t%s,r2\n", descLab);
  3566.   fprintf (outputFile, "\tload\t[r1],r1\n");
  3567.   fprintf (outputFile, "\tcmp\tr1,0\n");
  3568.   // If we have a target, generate code to move 0 or 1 into it...
  3569.   if (target) {
  3570.     return0 = newLabel ();
  3571.     retLabel = newLabel ();
  3572.     fprintf (outputFile, "\tbe\t%s\n", return0);
  3573.     fprintf (outputFile, "\tcmp\tr1,r2\n");
  3574.     fprintf (outputFile, "\tbne\t%s\n", return0);
  3575.     fprintf (outputFile, "\tmov\t1,r1\n");
  3576.     fprintf (outputFile, "\tjmp\t%s\n", retLabel);
  3577.     fprintf (outputFile, "%s:\n", return0);
  3578.     fprintf (outputFile, "\tmov\t0,r1\n");
  3579.     fprintf (outputFile, "%s:\n", retLabel);
  3580.     storeFromReg1 (target, "r1", "r2");
  3581.   // Else, generate a jump if false, and fall thru otherwise...
  3582.   } else {
  3583.     fprintf (outputFile, "\tbe\t%s\n", falseLabel);
  3584.     fprintf (outputFile, "\tcmp\tr1,r2\n");
  3585.     fprintf (outputFile, "\tbne\t%s\n", falseLabel);
  3586.   }
  3587.   
  3588. }
  3589.  
  3590. void IRIsInstanceOf (VarDecl * target, VarDecl * temp, char * descLab, char * falseLabel) {
  3591.   linkIR (new IsInstanceOf (target, temp, descLab, falseLabel));
  3592. }
  3593.  
  3594.  
  3595.  
  3596. //----------  ZeroMemory  ----------
  3597.  
  3598. void ZeroMemory::print () {
  3599.   char * label;
  3600.   int i;
  3601.   fprintf (outputFile, "!   ZeroMemory: ");
  3602.   if (targetVar) {
  3603.     printANode (targetVar);
  3604.   }
  3605.   if (targetPtr) {
  3606.     fprintf (outputFile, "*");
  3607.     printANode (targetPtr);
  3608.   }
  3609.   fprintf (outputFile, " = zeros  (sizeInBytes=%d)\n", sizeInBytes);
  3610.   if ((targetVar==NULL) == (targetPtr==NULL)) {
  3611.     programLogicError ("In ZeroMemory, targetVar and targetPtr are incorrect");
  3612.   }
  3613.   if (sizeInBytes == 1) {
  3614.     programLogicError ("In ZeroMemory, untested code - 1");
  3615.     if (targetVar) {
  3616.       storeFromReg1 (targetVar, "r0", "r1");
  3617.     } else if (targetPtr) {
  3618.       getIntoReg4 (targetPtr, "r1");
  3619.       fprintf (outputFile, "\tstoreb\tr0,[r1]\n");
  3620.     }
  3621.   } else if (sizeInBytes == 4) {
  3622.     programLogicError ("In ZeroMemory, untested code - 2");
  3623.     if (targetVar) {
  3624.       storeFromReg4 (targetVar, "r0", "r1");
  3625.     } else if (targetPtr) {
  3626.       getIntoReg4 (targetPtr, "r1");
  3627.       fprintf (outputFile, "\tstore\tr0,[r1]\n");
  3628.     }
  3629.   } else if ((sizeInBytes < 0) || (sizeInBytes%4 != 0)) {
  3630.     printf ("sizeInBytes = %d\n", sizeInBytes);
  3631.     programLogicError ("In ZeroMemory, problems with sizeInBytes");
  3632.   } else {
  3633.  
  3634.     if (targetVar) {
  3635.       getAddrOfVarIntoReg (targetVar, "r4");
  3636.     } else if (targetPtr) {
  3637.       getIntoReg4 (targetPtr, "r4");
  3638.     }
  3639.  
  3640.     if (sizeInBytes == 8) {
  3641.       // tested...
  3642.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3643.       fprintf (outputFile, "\tstore\tr0,[r4+4]\n");
  3644.     } else if (sizeInBytes == 12) {
  3645.       // tested...
  3646.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3647.       fprintf (outputFile, "\tstore\tr0,[r4+4]\n");
  3648.       fprintf (outputFile, "\tstore\tr0,[r4+8]\n");
  3649.     } else if (sizeInBytes == 16) {
  3650.       // tested...
  3651.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3652.       fprintf (outputFile, "\tstore\tr0,[r4+4]\n");
  3653.       fprintf (outputFile, "\tstore\tr0,[r4+8]\n");
  3654.       fprintf (outputFile, "\tstore\tr0,[r4+12]\n");
  3655.     } else if (sizeInBytes == 20) {
  3656.       // tested...
  3657.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3658.       fprintf (outputFile, "\tstore\tr0,[r4+4]\n");
  3659.       fprintf (outputFile, "\tstore\tr0,[r4+8]\n");
  3660.       fprintf (outputFile, "\tstore\tr0,[r4+12]\n");
  3661.       fprintf (outputFile, "\tstore\tr0,[r4+16]\n");
  3662.     } else if (sizeInBytes == 24) {
  3663.       // tested...
  3664.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3665.       fprintf (outputFile, "\tstore\tr0,[r4+4]\n");
  3666.       fprintf (outputFile, "\tstore\tr0,[r4+8]\n");
  3667.       fprintf (outputFile, "\tstore\tr0,[r4+12]\n");
  3668.       fprintf (outputFile, "\tstore\tr0,[r4+16]\n");
  3669.       fprintf (outputFile, "\tstore\tr0,[r4+20]\n");
  3670.     } else {
  3671.       // tested...
  3672.       // Generate code to move N bytes...
  3673.       //     r3 = counter of words
  3674.       //     r4 = ptr to dest
  3675.       label = newLabel ();
  3676.       if (within16Bits (sizeInBytes / 4)) {
  3677.         fprintf (outputFile, "\tmov\t%d,r3\n", sizeInBytes / 4);
  3678.       } else {
  3679.         fprintf (outputFile, "\tset\t0x%08x,r3\t\t\t! decimal = %d\n",
  3680.                  sizeInBytes / 4, sizeInBytes / 4);
  3681.       }
  3682.       fprintf (outputFile, "%s:\n", label);
  3683.       fprintf (outputFile, "\tstore\tr0,[r4]\n");
  3684.       fprintf (outputFile, "\tadd\tr4,4,r4\n");
  3685.       fprintf (outputFile, "\tsub\tr3,1,r3\n");
  3686.       fprintf (outputFile, "\tbne\t%s\n", label);
  3687.     }
  3688.   }
  3689. }
  3690.  
  3691. void IRZeroMemory (VarDecl * tarV, VarDecl * tarP, int sz) {
  3692.   linkIR (new ZeroMemory (tarV, tarP, sz));
  3693. }
  3694.