00001 /* 00002 * VarNodes.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 "VarNodes.h" 00024 00025 /**************************************************************************** 00026 PopVarNode 00027 ****************************************************************************/ 00028 00029 /*void PopVarNode::fold(const uint32 end) 00030 { 00031 PTRACE(("(PopVar)\tPOS: %4d\tOP: %04X offset: %04X\n", end, foldops[end].op(), 00032 foldops[end].offset)); 00033 assert(foldops[end].deleted==false); 00034 00035 _opcode = foldops[end].op(); // store the op locally 00036 _offset = foldops[end].offset; // store the offset locally 00037 00038 switch(_opcode) 00039 { 00040 case 0x00: // popping a byte (1 byte) 00041 lnode = new PushVarNode(PushVarNode::VT_BYTE, PushVarNode::DT_BP, 00042 foldops[end].i0); 00043 rtype=Type::T_VOID; 00044 break; 00045 case 0x01: // popping a word (2 bytes) 00046 lnode = new PushVarNode(PushVarNode::VT_WORD, PushVarNode::DT_BP, 00047 foldops[end].i0); 00048 rtype=Type::T_VOID; 00049 break; 00050 case 0x02: // popping a dword (4 bytes) 00051 lnode = new PushVarNode(PushVarNode::VT_DWORD, PushVarNode::DT_BP, 00052 foldops[end].i0); 00053 rtype=Type::T_VOID; 00054 break; 00055 case 0x08: // popping a result (4 bytes) 00056 lnode = new PushVarNode(PushVarNode::VT_DWORD, PushVarNode::DT_RESULT, 0); 00057 rtype=Type::T_VOID; 00058 break; 00059 default: // die if we don't know the op 00060 printf("\nopcode %02X not supported in call to PopVarNode from offset %04X\n", 00061 _opcode, _offset); 00062 //printfolding(); 00063 assert(false); 00064 break; 00065 } 00066 00067 sint32 tempsize = lnode->rtype.size(); 00068 assert(tempsize>0); 00069 grab_r(tempsize, end); 00070 assert(tempsize==0); 00071 }*/ 00072 00073 00074 void PopVarNode::print_unk(Console &o, const uint32 isize) const 00075 { 00076 assert(node!=0); 00077 Node::print_linenum_unk(o, isize); 00078 #if 0 00079 _dtype.print_type_unk(o); 00080 o.Putchar(' '); 00081 #endif 00082 _dtype.print_value_unk(o); 00083 o.Print(" = "); 00084 node->print_unk(o, isize); 00085 } 00086 00087 void PopVarNode::print_asm(Console &o) const 00088 { 00089 assert(node!=0); 00090 Node::print_linenum_asm(o); 00091 node->print_asm(o); 00092 o.Putchar('\n'); 00093 Node::print_asm(o); 00094 switch(_dtype.dtype()) 00095 { 00096 case DataType::DT_BP: 00097 switch(_dtype.type().type()) 00098 { 00099 case Type::T_WORD: o.Printf("pop\t\t"); _dtype.print_value_asm(o); break; 00100 //case Type::T_DWORD: o.Printf("pop dword\t"); _dtype.print_value_asm(o); break; 00101 default: assert(false); 00102 } 00103 break; 00104 case DataType::DT_TEMP: 00105 switch(_dtype.type().type()) 00106 { 00107 case Type::T_WORD: o.Printf("pop\t\ttemp"); break; 00108 default: assert(false); 00109 } 00110 break; 00111 default: assert(false); 00112 } 00113 } 00114 00115 void PopVarNode::print_bin(ODequeDataSource &o) const 00116 { 00117 assert(node!=0); 00118 Node::print_linenum_bin(o); 00119 node->print_bin(o); 00120 switch(_dtype.dtype()) 00121 { 00122 case DataType::DT_BP: 00123 switch(_dtype.type().type()) 00124 { 00125 case Type::T_WORD: o.write1(0x01); _dtype.print_value_bin(o); break; 00126 default: assert(false); 00127 } 00128 break; 00129 case DataType::DT_TEMP: 00130 switch(_dtype.type().type()) 00131 { 00132 case Type::T_WORD: o.write1(0x12); break; 00133 default: assert(false); 00134 } 00135 break; 00136 default: assert(false); 00137 } 00138 } 00139 00140 bool PopVarNode::fold(DCUnit *unit, std::deque<Node *> &nodes) 00141 { 00142 //con.Printf("RTypes: %d %d", nodes.back()->rtype().type(), rtype().type()); 00143 assert(nodes.back()->rtype()==rtype() || print_assert(this, unit)); 00144 grab_n(nodes); 00145 fold_linenum(nodes); 00146 return true; 00147 } 00148 00149 00150 /**************************************************************************** 00151 PushVarNode 00152 ****************************************************************************/ 00153 00154 /*void PushVarNode::fold(const uint32 end) 00155 { 00156 PTRACE(("(PushVar)\tPOS: %4d\tOP: %04X offset: %04X\n", end, foldops[end].op(), 00157 foldops[end].offset)); 00158 assert(foldops[end].deleted==false);*/ 00159 00160 /* _opcode = foldops[end].op(); // store the op locally 00161 _offset = foldops[end].offset; // store the offset locally 00162 */ 00163 /* switch(_opcode) 00164 { 00165 case 0x0D: // pushing a string (2 bytes) 00166 _vtype = VT_STRING; 00167 _dtype = DT_CHARS; 00168 strval = foldops[end].str; 00169 rtype=Type::T_STRING; 00170 break; 00171 case 0x3E: // pushing a byte var (2 bytes) 00172 _vtype = VT_BYTE; 00173 _dtype = DT_BP; 00174 value = foldops[end].i0; 00175 rtype=Type::T_BYTE; 00176 break; 00177 case 0x3F: // pushing a word var (2 bytes) 00178 _vtype = VT_WORD; 00179 _dtype = DT_BP; 00180 value = foldops[end].i0; 00181 rtype=Type::T_WORD; 00182 break; 00183 case 0x41: // pushing a string var (2 bytes) 00184 _vtype = VT_STRING; 00185 _dtype = DT_BP; 00186 value = foldops[end].i0; 00187 rtype=Type::T_STRING; 00188 break; 00189 case 0x42: // pushing a list (2 bytes?) 00190 _vtype = VT_LIST; 00191 _dtype = DT_BPLIST; 00192 value = foldops[end].i0; 00193 value2 = foldops[end].i1; 00194 assert(value2==2); // FIXME: incorrect, but a quick hack for my purposes 00195 rtype=Type::T_LIST; 00196 break; 00197 case 0x43: // pushing a slist (2 bytes?) 00198 _vtype = VT_SLIST; 00199 _dtype = DT_BP; 00200 value = foldops[end].i0; 00201 rtype=Type::T_SLIST; 00202 break; 00203 case 0x4E: // pushing a global (x bytes - round up to an even pair of bytes 00204 _dtype = DT_GLOBAL; 00205 global_offset = foldops[end].i0; 00206 global_size = foldops[end].i1; 00207 switch(global_size) 00208 { 00209 case 0x01: _vtype = VT_BYTE; rtype=Type::T_BYTE; break; 00210 case 0x02: _vtype = VT_WORD; rtype=Type::T_WORD; break; 00211 case 0x03: _vtype = VT_DWORD; rtype=Type::T_DWORD; break; 00212 // case 0x04: _vtype = DWORD; rtype=Type::T_DWORD; break; 00213 // debugging, remove this and replace it with a _vtype=VAR when finished 00214 default: assert(false); 00215 } 00216 break; 00217 case 0x59: // pushing a pid (2 bytes - maybe) 00218 _vtype = VT_VPID; 00219 _dtype = DT_DPID; 00220 value = 0; // unused 00221 rtype=Type::T_PID; 00222 break; 00223 case 0x69: // pushing a string ptr (4 bytes) 00224 _vtype = VT_DWORD; 00225 _dtype = DT_BPSTRPTR; 00226 value = 0x100-foldops[end].i0; 00227 rtype=Type::T_DWORD; 00228 break; 00229 case 0x6D: // pushing an address of a SP (4 bytes) 00230 _vtype = VT_DWORD; 00231 _dtype = DT_PRESULT; 00232 value = 0; // unused 00233 rtype=Type::T_DWORD; 00234 break; 00235 case 0x6F: // pushing an address of a SP (4 bytes) 00236 _vtype = VT_DWORD; 00237 _dtype = DT_SPADDR; 00238 value = 0x100-foldops[end].i0; 00239 rtype=Type::T_DWORD; 00240 break; 00241 case 0x79: // pushing a global address (4 bytes) 00242 if(crusader) // we're only a global for crusader 00243 { 00244 _vtype = VT_DWORD; 00245 _dtype = DT_SPADDR; 00246 value = 0x100-foldops[end].i0; 00247 rtype=Type::T_DWORD; 00248 } 00249 else // not for u8 00250 assert(false); 00251 break; 00252 default: // die if we don't know the op 00253 printf("\nopcode %02X not supported in call to PushVarNode from offset %04X\n", 00254 _opcode, _offset); 00255 //printfolding(); 00256 assert(false); 00257 break; 00258 } 00259 }*/ 00260 00261 void PushVarNode::print_unk(Console &o, const uint32 /*isize*/) const 00262 { 00263 #if 0 00264 _dtype.print_type_unk(o); 00265 o.Putchar(' '); 00266 #endif 00267 _dtype.print_value_unk(o); 00268 } 00269 00270 void PushVarNode::print_asm(Console &o) const 00271 { 00272 Node::print_asm(o); 00273 switch(_dtype.dtype()) 00274 { 00275 case DataType::DT_BYTES: 00276 switch(_dtype.type().type()) 00277 { 00278 case Type::T_BYTE: o.Printf("push byte\t"); _dtype.print_value_asm(o); break; 00279 case Type::T_WORD: o.Printf("push\t\t"); _dtype.print_value_asm(o); break; 00280 case Type::T_DWORD: o.Printf("push dword\t"); _dtype.print_value_asm(o); break; 00281 default: assert(false); // can't happen 00282 } 00283 break; 00284 case DataType::DT_BP: 00285 switch(_dtype.type().type()) 00286 { 00287 case Type::T_WORD: o.Printf("push\t\t"); _dtype.print_value_asm(o); break; 00288 case Type::T_DWORD: o.Printf("push dword\t"); _dtype.print_value_asm(o); break; 00289 default: assert(false); 00290 } 00291 break; 00292 case DataType::DT_BPADDR: 00293 switch(_dtype.type().type()) 00294 { 00295 case Type::T_DWORD: o.Printf("push addr\t"); _dtype.print_value_asm(o); break; 00296 default: assert(false); // can't happen 00297 } 00298 break; 00299 case DataType::DT_STRING: 00300 switch(_dtype.type().type()) 00301 { 00302 case Type::T_STRING: o.Printf("push string\t"); _dtype.print_value_asm(o); break; 00303 default: assert(false); // can't happen 00304 } 00305 break; 00306 case DataType::DT_PID: 00307 //assert(_dtype.type().type()==Type::T_PID); 00308 o.Printf("push\t\tpid"); 00309 break; 00310 case DataType::DT_GLOBAL: 00311 assert(_dtype.type().type()==Type::T_WORD); 00312 o.Printf("push\t\tglobal "); 00313 _dtype.print_value_asm(o); 00314 break; 00315 default: assert(false); 00316 } 00317 } 00318 00319 void PushVarNode::print_bin(ODequeDataSource &o) const 00320 { 00321 switch(_dtype.dtype()) 00322 { 00323 case DataType::DT_BYTES: 00324 switch(_dtype.type().type()) 00325 { 00326 case Type::T_BYTE: o.write1(0x0A); _dtype.print_value_bin(o); break; 00327 case Type::T_WORD: o.write1(0x0B); _dtype.print_value_bin(o); break; 00328 case Type::T_DWORD: o.write1(0x0C); _dtype.print_value_bin(o); break; 00329 default: assert(false); // can't happen 00330 } 00331 break; 00332 case DataType::DT_BP: 00333 switch(_dtype.type().type()) 00334 { 00335 case Type::T_WORD: o.write1(0x3F); _dtype.print_value_bin(o); break; 00336 case Type::T_DWORD: o.write1(0x40); _dtype.print_value_bin(o); break; 00337 default: assert(false); 00338 } 00339 break; 00340 case DataType::DT_BPADDR: 00341 switch(_dtype.type().type()) 00342 { 00343 case Type::T_DWORD: o.write1(0x4B); _dtype.print_value_bin(o); break; 00344 default: assert(false); // can't happen 00345 } 00346 break; 00347 case DataType::DT_STRING: 00348 switch(_dtype.type().type()) 00349 { 00350 case Type::T_STRING: o.write1(0x0D); _dtype.print_value_bin(o); break; 00351 default: assert(false); // can't happen 00352 } 00353 break; 00354 case DataType::DT_PID: 00355 o.write1(0x59); 00356 break; 00357 case DataType::DT_GLOBAL: 00358 assert(_dtype.type().type()==Type::T_WORD); 00359 o.write1(0x4E); 00360 _dtype.print_value_bin(o); break; 00361 break; 00362 default: assert(false); 00363 } 00364 } 00365