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