OperatorNodes.cpp

Go to the documentation of this file.
00001 /*
00002  *      OperatorNodes.cpp -
00003  *
00004  *  Copyright (C) 2002-2003 The Pentagram Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "pent_include.h"
00022 
00023 #include "OperatorNodes.h"
00024 #include "Folder.h"
00025 
00026 /****************************************************************************
00027         NonOperatorNode
00028  ****************************************************************************/
00029 /*void TempNode::fold(const uint32 end)
00030 {
00031         PTRACE(("(Temp)\t\tPOS: %4d\tOP: %04X offset: %04X\n", end, foldops[end].op(), foldops[end].offset));
00032         assert(foldops[end].deleted==false);
00033 
00034         _opcode = foldops[end].op(); // store the op locally
00035         _offset = foldops[end].offset; // store the offset locally
00036 
00037         switch(_opcode)
00038         {
00039                 case 0x12:
00040                         ttype = POP_TEMP;
00041                         break;
00042                 case 0x4E:
00043                         ttype = PUSH_GLOBAL;
00044                         offset = foldops[end].i0;
00045                         size = foldops[end].i1;
00046                         break;
00047                 case 0x4F:
00048                         ttype = POP_GLOBAL;
00049                         offset = foldops[end].i0;
00050                         size = foldops[end].i1;
00051                         break;
00052                 case 0x50:
00053                         ttype = RET;
00054                         break;
00055                 case 0x51:
00056                         ttype = JNE;
00057                         offset = foldops[end].nextoffset + static_cast<short>(foldops[end].i0);
00058                         break;
00059                 case 0x52:
00060                         ttype = JMP;
00061                         offset = foldops[end].nextoffset + static_cast<short>(foldops[end].i0);
00062                         break;
00063                 case 0x53:
00064                         ttype = SUSPEND;
00065                         break;
00066                 // the PUSH_*_RET ops are just placeholders to temporarially stop things complaning
00067                 // should be removed soon: FIXME:
00068                 case 0x5D:
00069                         ttype = PUSH_BYTE_RET;
00070                         break;
00071                 case 0x5E:
00072                         ttype = PUSH_WORD_RET;
00073                         break;
00074                 case 0x5F:
00075                         ttype = PUSH_DWORD_RET;
00076                         break;
00077                 case 0x62:
00078                         ttype = FREE_STRING_BP;
00079                         node  = new PushVarNode(PushVarNode::VT_STRING, PushVarNode::DT_BP,
00080                                 foldops[end].i0);
00081                         break;
00082                 case 0x63:
00083                         ttype = FREE_SLIST_BP;
00084                         node  = new PushVarNode(PushVarNode::VT_SLIST, PushVarNode::DT_BP,
00085                                 foldops[end].i0);
00086                         break;
00087                 case 0x64:
00088                         ttype = FREE_LIST_BP;
00089                         node  = new PushVarNode(PushVarNode::VT_LIST, PushVarNode::DT_BP,
00090                                 foldops[end].i0);
00091                         break;
00092                 case 0x65:
00093                         ttype = FREE_STRING_SP;
00094                         node = new PushVarNode(PushVarNode::VT_STRING, PushVarNode::DT_SP,
00095                                 foldops[end].i0);
00096                         break;
00097                 case 0x66:
00098                         ttype = FREE_LIST_SP;
00099                         node = new PushVarNode(PushVarNode::VT_LIST, PushVarNode::DT_SP,
00100                                 foldops[end].i0);
00101                         break;
00102                 case 0x6C:
00103                         ttype = PARAM_PID_CHANGE;
00104                         type = foldops[end].i1;
00105                         switch(type)
00106                         {
00107                                 case 0x01:
00108                                         node = new PushVarNode(PushVarNode::VT_STRING, PushVarNode::DT_BP,
00109                                                 foldops[end].i0);
00110                                         break;
00111                                 case 0x02:
00112                                         node = new PushVarNode(PushVarNode::VT_SLIST, PushVarNode::DT_BP,
00113                                                 foldops[end].i0);
00114                                         break;
00115                                 case 0x03:
00116                                         node = new PushVarNode(PushVarNode::VT_LIST, PushVarNode::DT_BP,
00117                                                 foldops[end].i0);
00118                                         break;
00119                         }
00120                         break;
00121                 case 0x70:
00122                         ttype = LOOP;
00123                         node  = new PushVarNode(PushVarNode::VT_WORD, PushVarNode::DT_BP,
00124                                 foldops[end].i0);
00125                         size = foldops[end].i1;
00126                         type = foldops[end].i2;
00127                         break;
00128                 case 0x73:
00129                         ttype = LOOPNEXT;
00130                         break;
00131                 case 0x74:
00132                         ttype = LOOPSCR;
00133                         delta = static_cast<short>(foldops[end].i0);
00134                         break;
00135                 case 0x75:
00136                         ttype = FOREACH_LIST;
00137                         node  = new PushVarNode(PushVarNode::VT_LIST, PushVarNode::DT_BP,
00138                                 foldops[end].i0);
00139                         size = foldops[end].i1;
00140                         offset = foldops[end].nextoffset + static_cast<short>(foldops[end].i2);
00141                         break;
00142                 case 0x76:
00143                         ttype = FOREACH_SLIST;
00144                         node  = new PushVarNode(PushVarNode::VT_SLIST, PushVarNode::DT_BP,
00145                                 foldops[end].i0);
00146                         size = foldops[end].i1;
00147                         offset = foldops[end].nextoffset + static_cast<short>(foldops[end].i2);
00148                         break;
00149                 case 0x79:
00150                         if(!crusader) // if we're u8...
00151                                 ttype = END;
00152                         else
00153                                 assert(false); // if we're crusader, which can't happen.
00154                 case 0x7A:
00155                         ttype = END;
00156                         break;
00157                 default:
00158                         assert(false); // can't happen
00159         }
00160 }
00161 
00162 void TempNode::print() const
00163 {
00164         switch(ttype)
00165         {
00166                 case POP_TEMP:
00167                         printf("pop_temp()");
00168                         break;
00169                 case PUSH_GLOBAL:
00170                         printf("push_global(0x%04X, 0x%02X)", offset, size);
00171                         break;
00172                 case POP_GLOBAL:
00173                         printf("pop_global(0x%04X, 0x%02X)", offset, size);
00174                         break;
00175                 case RET:
00176                         printf("ret");
00177                         break;
00178                 case JNE:
00179                         printf("jne(0x%04X)", offset);
00180                         break;
00181                 case JMP:
00182                         printf("jmp(0x%04X)", offset);
00183                         break;
00184                 case SUSPEND:
00185                         printf("suspend");
00186                         break;
00187                 case PUSH_BYTE_RET:
00188                         printf("push_byte_ret()");
00189                         break;
00190                 case PUSH_WORD_RET:
00191                         printf("push_byte_ret()");
00192                         break;
00193                 case PUSH_DWORD_RET:
00194                         printf("push_byte_ret()");
00195                         break;
00196                 case FREE_STRING_BP:
00197                         printf("free_string_bp(");
00198                         node->print();
00199                         printf(")");
00200                         break;
00201                 case FREE_SLIST_BP:
00202                         printf("free_slist_bp(");
00203                         node->print();
00204                         printf(")");
00205                         break;
00206                 case FREE_LIST_BP:
00207                         printf("free_list_bp(");
00208                         node->print();
00209                         printf(")");
00210                         break;
00211                 case FREE_STRING_SP:
00212                         printf("free_string_sp(");
00213                         node->print();
00214                         printf(")");
00215                         break;
00216                 case FREE_LIST_SP:
00217                         printf("free_list_sp(");
00218                         node->print();
00219                         printf(")");
00220                         break;
00221                 case PARAM_PID_CHANGE:
00222                         printf("param_pid_change(");
00223                         node->print();
00224                         printf(", 0x%02X)", type);
00225                         break;
00226                 case LOOP:
00227                         printf("loop(");
00228                         node->print();
00229                         printf(", %d, %d)", size, type);
00230                         break;
00231                 case LOOPNEXT:
00232                         printf("loopnext()");
00233                         break;
00234                 case LOOPSCR:
00235                         printf("loopscr(%d, \"%c\")", delta, static_cast<char>(delta));
00236                         break;
00237                 case FOREACH_LIST:
00238                         printf("foreach_list(");
00239                         node->print();
00240                         printf(", %d, 0x%04X)", size, offset);
00241                         break;
00242                 case FOREACH_SLIST:
00243                         printf("foreach_slist(");
00244                         node->print();
00245                         printf(", %d, 0x%04X)", size, offset);
00246                         break;
00247                 case END:
00248                         printf("end");
00249                         break;
00250                 default:
00251                         assert(false); // can't happen
00252         }
00253 
00254 }*/
00255 
00256 
00257 /****************************************************************************
00258         UniOperatorNode
00259  ****************************************************************************/
00260 
00261 void UniOperatorNode::print_unk(Console &o, const uint32 isize) const
00262 {
00263         assert(rtype().type()!=Type::T_INVALID);
00264         switch(otype)
00265         {
00266                 case NOT:
00267                         assert(node!=0);
00268                         o.Printf("not ");
00269                         node->print_unk(o, isize);
00270                         break;
00271                 case STR_TO_PTR:
00272                         assert(node!=0);
00273                         o.Printf("str_to_ptr(");
00274                         node->print_unk(o, isize);
00275                         o.Putchar(')');
00276                         break;
00277                 default: assert(false); // can't happen
00278         }
00279 }
00280 
00281 void UniOperatorNode::print_asm(Console &o) const
00282 {
00283         assert(rtype().type()!=Type::T_INVALID);
00284         switch(otype)
00285         {
00286                 case NOT:
00287                         assert(node!=0);
00288                         node->print_asm(o);
00289                         o.Putchar('\n');
00290                         Node::print_asm(o);
00291                         o.Printf("not");
00292                         break;
00293                 case STR_TO_PTR:
00294                         assert(node!=0);
00295                         node->print_asm(o);
00296                         o.Putchar('\n');
00297                         Node::print_asm(o);
00298                         o.Printf("str to ptr");
00299                         break;
00300                 default: assert(false); // can't happen
00301         }
00302 }
00303 
00304 void UniOperatorNode::print_bin(ODequeDataSource &o) const
00305 {
00306         assert(rtype().type()!=Type::T_INVALID);
00307         switch(otype)
00308         {
00309                 case NOT:
00310                         assert(node!=0);
00311                         node->print_bin(o);
00312                         o.write1(0x30);
00313                         break;
00314                 case STR_TO_PTR:
00315                         assert(node!=0);
00316                         node->print_bin(o);
00317                         o.write1(0x6B);
00318                         break;
00319                 default: assert(false); // can't happen
00320         }
00321 }
00322 
00323 bool UniOperatorNode::fold(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00324 {
00325         switch(otype)
00326         {
00327                 case NOT:
00328                         assert(acceptType(nodes.back()->rtype(), Type::T_WORD, Type::T_BYTE));
00329                         //assert(nodes.back()->rtype()==Type::T_WORD || nodes.back()->rtype()==Type::T_BYTE);
00330                         grab_n(nodes);
00331                         break;
00332                 case STR_TO_PTR:
00333                         assert(acceptType(nodes.back()->rtype(), Type::T_STRING));
00334                         grab_n(nodes);
00335                         break;
00336                 default: assert(false);
00337         }
00338         return true;
00339 };
00340 
00341 /*void UniOperatorNode::fold(const uint32 end)
00342 {
00343         assert(foldops[end].deleted==false);
00344 
00345         _opcode = foldops[end].op(); // store the op locally
00346         _offset = foldops[end].offset; // store the offset locally
00347 
00348         switch(_opcode)
00349         {
00350                 case 0x3B: otype=BITNOT;        rtype=Type::T_WORD; break;
00351                 default: assert(false); // can't happen
00352         }
00353 
00354         sint32 tempsize = 2;
00355         grab_n(tempsize, end);
00356         assert(tempsize==0);
00357 
00358         // debugging
00359         assert(node!=0);
00360 }*/
00361 
00362 /*void UniOperatorNode::print() const
00363 {
00364         assert(node!=0);
00365 
00366         printf("(%s) (", rtype.name());
00367 
00368         switch(otype)
00369         {
00370                 case BITNOT:    printf("~");            break;
00371                 default:        assert(false); // can't happen
00372         }
00373 
00374         node->print();
00375         printf(")");
00376 }*/
00377 
00378 /*void ConvertNode::fold(const uint32 end)
00379 {
00380         assert(foldops[end].deleted==false);
00381 
00382         _opcode = foldops[end].op(); // store the op locally
00383         _offset = foldops[end].offset; // store the offset locally
00384 
00385         switch(_opcode)
00386         {
00387                 case 0x60: ctype=WORD_DWORD;  break;
00388                 case 0x61: ctype=DWORD_WORD;  break;
00389                 case 0x6B: ctype=STR_PTR; break;
00390                 default:   assert(false); // can't happen
00391         }
00392 
00393         sint32 tempsize;
00394 
00395         switch(ctype)
00396         {
00397                 case WORD_DWORD: tempsize=2; break;
00398                 case DWORD_WORD: tempsize=4; break;
00399                 case STR_PTR:    tempsize=2; break;
00400                 default:         assert(false); // can't happen
00401         }
00402 
00403         grab_n(tempsize, end);
00404         assert(tempsize==0);
00405 
00406         // now we switch the size, since we're converting the type
00407         switch(ctype)
00408         {
00409                 case WORD_DWORD: assert(node->rtype.size()==2); rtype=Type::T_DWORD; break;
00410                 case DWORD_WORD: assert(node->rtype.size()==4); rtype=Type::T_WORD; break;
00411                 case STR_PTR:    assert(node->rtype.size()==2); rtype=Type::T_STRPTR; break;
00412                 default:         assert(false); // can't happen
00413         }
00414 }
00415 
00416 void ConvertNode::print() const
00417 {
00418         assert(node!=0);
00419 
00420         switch(ctype)
00421         {
00422                 case WORD_DWORD: printf("(dword) to_dword("); break;
00423                 case DWORD_WORD: printf("(word) to_word(");  break;
00424                 case STR_PTR:    printf("(dword) to_ptr(");  break;
00425                 default:         assert(false); // can't happen
00426         }
00427         node->print();
00428         printf(")");
00429 }*/
00430 
00431 /****************************************************************************
00432         BinOperatorNode
00433  ****************************************************************************/
00434 
00435 void BinOperatorNode::print_unk(Console &o, const uint32 isize) const
00436 {
00437         assert(rtype().type()!=Type::T_INVALID);
00438         assert(lnode!=0);
00439         assert(rnode!=0);
00440         
00441         lnode->print_unk(o, isize);
00442         Node::print_linenum_unk(o, isize);
00443         switch(otype)
00444         {
00445                 case M_ADD: o.Printf(" + ");  break;
00446                 case M_SUB: o.Printf(" - ");  break;
00447                 case M_MUL: o.Printf(" * ");  break;
00448                 case M_CMP: o.Printf(" == "); break;
00449                 case M_LT:  o.Printf(" < ");  break;
00450                 case M_LE:  o.Printf(" <= "); break;
00451                 case M_GT:  o.Printf(" > ");  break;
00452                 case M_AND:  o.Printf(" and "); break;
00453                 case M_OR:  o.Printf(" or "); break;
00454                 case M_NE: o.Printf(" != "); break;
00455                 case M_IMPLIES: o.Printf(" <=> "); break;
00456                 default: assert(false); // can't happen
00457         }
00458         rnode->print_unk(o, isize);
00459 }
00460 
00461 void BinOperatorNode::print_asm(Console &o) const
00462 {
00463         assert(rtype().type()!=Type::T_INVALID);
00464         assert(lnode!=0);
00465         assert(rnode!=0);
00466         
00467         Node::print_linenum_asm(o);
00468         lnode->print_asm(o);
00469         o.Putchar('\n');
00470         rnode->print_asm(o);
00471         o.Putchar('\n');
00472         Node::print_asm(o);
00473         switch(otype)
00474         {
00475                 case M_ADD: o.Printf("add"); break;
00476                 case M_SUB: o.Printf("sub"); break;
00477                 case M_MUL: o.Printf("mul"); break;
00478                 case M_CMP: o.Printf("cmp"); break;
00479                 case M_LT:  o.Printf("lt");  break;
00480                 case M_LE:  o.Printf("le");  break;
00481                 case M_GT:  o.Printf("gt");  break;
00482                 case M_AND:  o.Printf("and");  break;
00483                 case M_OR:  o.Printf("or");  break;
00484                 case M_NE:  o.Printf("ne");  break;
00485                 case M_IMPLIES: o.Printf("implies\t\t01 01"); break;
00486                 default: assert(false); // can't happen
00487         }
00488 }
00489 
00490 void BinOperatorNode::print_bin(ODequeDataSource &o) const
00491 {
00492         assert(rtype().type()!=Type::T_INVALID);
00493         assert(lnode!=0);
00494         assert(rnode!=0);
00495         
00496         Node::print_linenum_bin(o);
00497         lnode->print_bin(o);
00498         rnode->print_bin(o);
00499         switch(otype)
00500         {
00501                 case M_ADD: o.write1(0x14); break;
00502                 case M_SUB: o.write1(0x1C); break;
00503                 case M_MUL: o.write1(0x1E); break;
00504                 case M_CMP: o.write1(0x24); break;
00505                 case M_LT:  o.write1(0x28); break;
00506                 case M_LE:  o.write1(0x2A); break;
00507                 case M_GT:  o.write1(0x2C); break;
00508                 case M_AND: o.write1(0x32); break;
00509                 case M_OR:  o.write1(0x34); break;
00510                 case M_NE:  o.write1(0x36); break;
00511                 case M_IMPLIES: o.write1(0x54); o.write2(0x0101); break;
00512                 default: assert(false); // can't happen
00513         }
00514 }
00515 
00516 bool BinOperatorNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00517 {
00518         switch(otype)
00519         {
00520                 case M_ADD:     case M_SUB:     case M_MUL:
00521                 case M_CMP:     case M_LT:      case M_LE:      case M_GT:  case M_NE:
00522                 case M_AND: case M_OR:
00523                         assert(acceptType(nodes.back()->rtype(), Type::T_WORD, Type::T_BYTE));
00524                         grab_r(nodes);
00525                         //fold_linenum(nodes);
00526                         assert(acceptType(nodes.back()->rtype(), Type::T_WORD, Type::T_BYTE));
00527                         grab_l(nodes);
00528                         fold_linenum(nodes);
00529                         rtype(Type::T_WORD);
00530                         break;
00531                 case M_IMPLIES:
00532                         assert(acceptType(nodes.back()->rtype(), Type::T_WORD, Type::T_BYTE, Type::T_PID) || print_assert(this, unit));
00533                         grab_r(nodes);
00534                         //fold_linenum(nodes);
00535                         assert(acceptType(nodes.back()->rtype(), Type::T_WORD, Type::T_BYTE, Type::T_PID) || print_assert(nodes.back(), unit) || print_assert(this, unit));
00536                         grab_l(nodes);
00537                         fold_linenum(nodes);
00538                         rtype(Type::T_WORD);
00539                         break;
00540                 default: assert(print_assert(this, unit));
00541         }
00542         return true;
00543 };
00544 

Generated on Fri Jul 27 22:27:28 2007 for pentagram by  doxygen 1.4.7