00001 #include <Instruction.h>
00002 #include <SectHeader.h>
00003 #include <SymbolTable.h>
00004 #include <DemangleWrapper.h>
00005 #include <LoaderSection.h>
00006 #include <RawSection.h>
00007 #include <Iterator.h>
00008 #include <Function.h>
00009 #include <XCoffFile.h>
00010 #include <BinaryFile.h>
00011
00014 Operand Operand::IntegerOperand0 = IntegerOperand(0);
00015
00016 Operand* Operand::GPRegisterOperands = initGPRegisterOperands();
00017
00018 Operand* Operand::initGPRegisterOperands(){
00019 Operand* ret = new Operand[NUM_OF_GPR_REGS];
00020 for(uint32_t i=0;i<NUM_OF_GPR_REGS;i++)
00021 ret[i] = GPRegisterOperand(i);
00022 return ret;
00023 }
00024
00025 BitSet<>* Instruction::memoryOperationXops = Instruction::initMemoryOperationXops();
00026
00027 BitSet<>* Instruction::initMemoryOperationXops(){
00028 BitSet<>* ret = new BitSet<>(INVALID_XOP);
00029 uint32_t xops[] = { xcode_Lwarx,xcode_Ldx,xcode_Lwzx,xcode_Ldux,xcode_Lwzux,xcode_Ldarx,
00030 xcode_Lbzx,xcode_Lbzux,xcode_Stdx,xcode_Stwcxc,xcode_Stwx,xcode_Stdux,
00031 xcode_Stwux,xcode_Stdcxc,xcode_Stbx,xcode_Stbux,xcode_Lhzx,xcode_Lhzux,
00032 xcode_Lwax,xcode_Lhax,xcode_Lwaux,xcode_Lhaux,xcode_Sthx,xcode_Sthux,
00033 xcode_Lswx,xcode_Lwbrx,xcode_Lfsx,xcode_Lfsux,xcode_Lswi,xcode_Lfdx,
00034 xcode_Lfdux,xcode_Stswx,xcode_Stwbrx,xcode_Stfsx,xcode_Stfsux,xcode_Stswi,
00035 xcode_Stfdx,xcode_Stfdux,xcode_Lhbrx,xcode_Sthbrx,xcode_Stfiwx,
00036 xcode_LscbxC,
00037 INVALID_XOP };
00038
00039 for(uint32_t i=0;xops[i] != INVALID_XOP;i++)
00040 ret->insert(xops[i]);
00041
00042 return ret;
00043 }
00044
00045 bool Instruction::isCondBranch() {
00046 if(!ppci.lk.lk &&
00047 IS_BC(ppci) &&
00048 !BRANCH_ALWAYS(ppci.b.bo))
00049 return true;
00050 return false;
00051 }
00052
00053 bool Instruction::isJump() {
00054 if(!ppci.lk.lk){
00055 if(IS_B(ppci))
00056 return true;
00057 if(IS_BC(ppci) &&
00058 BRANCH_ALWAYS(ppci.b.bo))
00059 return true;
00060 }
00061 return false;
00062 }
00063
00064 bool Instruction::isReturn() {
00065 if(!ppci.lk.lk){
00066 if(IS_BCLR(ppci) &&
00067 BRANCH_ALWAYS(ppci.xl.bt_bo) &&
00068 !GET_BH(ppci))
00069 return true;
00070 }
00071 return isCondReturn();
00072 }
00073
00074 bool Instruction::isCondReturn(){
00075 if(!ppci.lk.lk){
00076 if(IS_BCLR(ppci) &&
00077 !BRANCH_ALWAYS(ppci.xl.bt_bo))
00078 return true;
00079 }
00080 return false;
00081 }
00082
00083 bool Instruction::isCall() {
00084 if(ppci.lk.lk){
00085 if(IS_B(ppci))
00086 return true;
00087 if(IS_BC(ppci) && BRANCH_ALWAYS(ppci.b.bo))
00088 return true;
00089 if(IS_BC(ppci) && !BRANCH_ALWAYS(ppci.b.bo))
00090 return true;
00091 if((IS_BCLR(ppci) || IS_BCCTR(ppci)) && BRANCH_ALWAYS(ppci.xl.bt_bo))
00092 return true;
00093 }
00094 return false;
00095 }
00096
00097 uint64_t Instruction::getTargetAddress(uint64_t insnAddr){
00098
00099 ASSERT((isCondBranch() || isJump()) &&
00100 "FATAL : getTargetAddress can oly be called for cond branch and jump");;
00101
00102 int32_t offset = 0x0;
00103
00104 if(IS_B(ppci)){
00105 offset = ppci.i.li;
00106 } else if(IS_BC(ppci)){
00107 offset = ppci.b.bd;
00108 }
00109 offset <<= 2;
00110
00111 if(ppci.lk.aa){
00112 return (uint64_t)offset;
00113 }
00114
00115 return insnAddr+offset;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 bool Instruction::isIndirectJump() {
00147 return (isIndirectJumpCtr() || isIndirectJumpLnk());
00148 }
00149
00150 bool Instruction::isIndirectJumpCtr(){
00151 if(!ppci.lk.lk &&
00152 IS_BCCTR(ppci) &&
00153 BRANCH_ALWAYS(ppci.xl.bt_bo))
00154 return true;
00155 return false;
00156 }
00157 bool Instruction::isIndirectJumpLnk(){
00158 if(!ppci.lk.lk &&
00159 IS_BCLR(ppci) &&
00160 BRANCH_ALWAYS(ppci.xl.bt_bo) &&
00161 GET_BH(ppci))
00162 return true;
00163 return false;
00164 }
00165
00166 bool Instruction::isOtherBranch(){
00167 if(ppci.lk.lk){
00168 if(IS_BCLR(ppci) && !BRANCH_ALWAYS(ppci.xl.bt_bo)){
00169 return true;
00170 }
00171 if(IS_BCCTR(ppci) && !BRANCH_ALWAYS(ppci.xl.bt_bo)){
00172 return true;
00173 }
00174 } else {
00175 if(IS_BCCTR(ppci) && !BRANCH_ALWAYS(ppci.xl.bt_bo)){
00176 return true;
00177 }
00178 }
00179 return false;
00180 }
00181
00182 bool Instruction::definesJTBaseAddress(){
00183 if(IS_LWZ(ppci) && (ppci.d.ra == REG_TOC))
00184 return true;
00185 if(IS_LD(ppci) && (ppci.ds.ra == REG_TOC))
00186 return true;
00187 return false;
00188 }
00189 int32_t Instruction::getJTBaseOffsetTOC(){
00190 ASSERT(definesJTBaseAddress());
00191 if(IS_LWZ(ppci))
00192 return ppci.d.d_ui_si;
00193 if(IS_LD(ppci))
00194 return (ppci.ds.ds << 2);
00195 return 0;
00196 }
00197 uint32_t Instruction::getJTBaseAddrTarget(){
00198 return ppci.d.rt_s_bf;
00199 }
00200
00201 bool Instruction::definesJTEntryCount(){
00202 return IS_CMPLI(ppci);
00203 }
00204 uint32_t Instruction::getJTEntryCount(){
00205 return (uint32_t)(ppci.d.d_ui_si & 0x0000ffff);
00206 }
00207
00208 bool Instruction::isAddBeforeJump(){
00209 return IS_ADD(ppci);
00210 }
00211
00212 bool Instruction::isLoadBeforeJump(){
00213 return (IS_LDX(ppci) || IS_LWZX(ppci));
00214 }
00215
00216 uint32_t Instruction::getLoadBeforeJumpSrc1(){
00217 return ppci.x.ra_sr;
00218 }
00219
00220 bool Instruction::definesJTBaseAddrIndir(){
00221 return IS_ADDI(ppci);
00222 }
00223
00224 int32_t Instruction::getJTBaseAddrIndirOffset(){
00225 ASSERT(definesJTBaseAddrIndir());
00226 return ppci.d.d_ui_si;
00227 }
00228
00229 uint32_t Instruction::getJTBaseAddrIndirSrc(){
00230 return ppci.d.ra;
00231 }
00232
00233
00234 #ifdef USE_DISASSEMBLER
00235 extern "C" int32_t print_insn_powerpc_for_meminst(uint64_t memaddr, uint32_t insn, int32_t dialect,char* buffer);
00236 #else
00237 int32_t print_insn_powerpc_for_meminst(uint64_t memaddr, uint32_t insn, int32_t dialect,char* buffer){
00238 if(buffer) strcpy(buffer,"no_insn");
00239 return 0;
00240 }
00241 #endif
00242
00243 void Instruction::print(uint64_t insnAddr,bool is64Bit){
00244
00245 #ifdef USE_DISASSEMBLER
00246 char buffer[1024];
00247 fprintf(stdout,"\t%#18llx : ",insnAddr);
00248 if(is64Bit){
00249 print_insn_powerpc_for_meminst(insnAddr,ppci.bits,67169,buffer);
00250 } else {
00251 print_insn_powerpc_for_meminst(insnAddr,ppci.bits,2,buffer);
00252 }
00253 fprintf(stdout,buffer);
00254
00255 if(isCondBranch()){
00256 PRINT_DEBUG("\tisCondBranch");
00257 } else if(isJump()){
00258 PRINT_DEBUG("\tisJump");
00259 } else if(isCondReturn()){
00260 PRINT_DEBUG("\tisCondReturn");
00261 } else if(isReturn()){
00262 PRINT_DEBUG("\tisReturn");
00263 } else if(isCall()){
00264 PRINT_DEBUG("\tisCall");
00265 } else if(isIndirectJump()){
00266 PRINT_DEBUG("\tisIndirectJump");
00267 } else if(isMemoryDForm()){
00268 PRINT_DEBUG("\tisMemoryDForm");
00269 } else if(isMemoryDsForm()){
00270 PRINT_DEBUG("\tisMemoryDsForm");
00271 } else if(isMemoryXForm()){
00272 PRINT_DEBUG("\tisMemoryXForm");
00273 } else if(isUnhandledMemoryOp()){
00274 PRINT_DEBUG("\tisUnhandledMemoryOp");
00275 } else if(isFloatAForm()){
00276 PRINT_DEBUG("\tisFloatAForm");
00277 } else if(isFloatXForm()){
00278 PRINT_DEBUG("\tisFloatXForm");
00279 }
00280 #endif
00281 }
00282
00283 void Instruction::print(char* buffer,uint64_t baseAddress,uint32_t sizeInBytes,bool is64Bit){
00284 #ifdef USE_DISASSEMBLER
00285 for(uint32_t i=0;i<sizeInBytes;i+=sizeof(uint32_t)){
00286 uint64_t insnAddr = baseAddress + i;
00287 uint32_t insnBits = 0;
00288 memcpy(&insnBits,buffer+i,sizeof(uint32_t));
00289 Instruction insn(insnBits);
00290 insn.print(insnAddr,is64Bit);
00291 }
00292 #endif
00293 }
00294
00295 bool Instruction::isMemoryDForm(){
00296 return ((ppci.opc.opc >= opcode_Lwz) &&
00297 (ppci.opc.opc <= opcode_Stfdu));
00298 }
00299 bool Instruction::isMemoryDsForm(){
00300 return ((ppci.opc.opc == opcode_Ld) ||
00301 (ppci.opc.opc == opcode_Std));
00302 }
00303 bool Instruction::isMemoryXForm(){
00304 return ((ppci.opc.opc == opcode_Lwarx) &&
00305 memoryOperationXops->contains(ppci.x.xo));
00306 }
00307 bool Instruction::isUnhandledMemoryOp(){
00308 return ((ppci.opc.opc == opcode_Lwarx) &&
00309 !memoryOperationXops->contains(ppci.x.xo) &&
00310 ((ppci.x.xo & MEMORY_MASK) == MEMORY_MATCH));
00311 }
00312
00313 bool Instruction::isFloatAForm(){
00314 return ((ppci.opc.opc == opcode_FdivsC) ||
00315 ((ppci.opc.opc == opcode_Fcmpu) &&
00316 ((ppci.x.xo & FOP_AFORM_MASK) == FOP_AFORM_MATCH)));
00317 }
00318 bool Instruction::isFloatXForm(){
00319 return ((ppci.opc.opc == opcode_Fcmpu) &&
00320 ((ppci.x.xo & FOP_AFORM_MASK) != FOP_AFORM_MATCH) &&
00321 ((ppci.x.xo & FOP_CONDREG_MASK) != FOP_CONDREG_MATCH) &&
00322 (ppci.x.xo != xcode_Mcrfs));
00323 }
00324
00325 uint32_t Instruction::getDFormSrc1()
00326 {
00327 return ppci.d.ra;
00328 }
00329 uint32_t Instruction::getDFormTgt()
00330 {
00331 return ppci.d.rt_s_bf;
00332 }
00333 int32_t Instruction::getDFormImmediate()
00334 {
00335 return ppci.d.d_ui_si;
00336 }
00337 int32_t Instruction::getDsFormImmediate()
00338 {
00339 return (ppci.ds.ds << 2);
00340 }
00341 uint32_t Instruction::getXFormSrc1()
00342 {
00343 return ppci.x.ra_sr;
00344 }
00345 uint32_t Instruction::getXFormSrc2()
00346 {
00347 return ppci.x.rb_sh;
00348 }
00349 bool Instruction::isMemoryXFormButNoSrc2()
00350 {
00351 return (IS_LSWI(ppci) || IS_STSWI(ppci));
00352 }
00353
00354 bool Instruction::isInLoadOffsetInsnRange(int32_t value){
00355 int32_t max = 0x7fff;
00356 int32_t min = -(max+1);
00357 if((min <= value) && (value <= max))
00358 return true;
00359 return false;
00360 }
00361
00362 bool Instruction::isInJumpInsnRange(uint64_t from,uint64_t to){
00363 int32_t distance = to - from;
00364 ASSERT(!(distance & 0x3));
00365 distance >>= 2;
00366 int32_t max = 0x7fffff;
00367 int32_t min = -(max+1);
00368 if((min <= distance) && (distance <= max))
00369 return true;
00370 return false;
00371 }
00372 Instruction Instruction::generateJumpInsn(uint64_t from,uint64_t to){
00373 Instruction ret;
00374 ASSERT(isInJumpInsnRange(from,to));
00375 int32_t distance = to - from;
00376 distance >>= 2;
00377 ret.ppci.i.opc = opcode_BLA;
00378 ret.ppci.i.li = distance;
00379 ret.ppci.i.aa = 0;
00380 ret.ppci.i.lk = 0;
00381 return ret;
00382 }
00383 Instruction Instruction::generateAdd(uint32_t tgt,uint32_t src1,uint32_t src2){
00384 Instruction ret;
00385 ret.ppci.xo.opc = opcode_AddOC;
00386 ret.ppci.xo.xo = xcode_AddOC;
00387 ret.ppci.xo.oe = 0;
00388 ret.ppci.xo.rc = 0;
00389 ret.ppci.xo.rt = tgt;
00390 ret.ppci.xo.ra = src1;
00391 ret.ppci.xo.rb = src2;
00392 return ret;
00393 }
00394
00395 Instruction Instruction::generateAddImm(uint32_t tgt,uint32_t src,int32_t value){
00396 Instruction ret;
00397 ret.ppci.d.opc = opcode_Addi;
00398 ret.ppci.d.rt_s_bf = tgt;
00399 ret.ppci.d.ra = src;
00400 ASSERT(isInLoadOffsetInsnRange(value));
00401 ret.ppci.d.d_ui_si = value;
00402 return ret;
00403 }
00404
00405 Instruction Instruction::generateIncrement(uint32_t reg,int32_t value){
00406 return generateAddImm(reg,reg,value);
00407 }
00408 Instruction Instruction::generateLoadImmediate(uint32_t reg,int32_t value){
00409 return generateAddImm(reg,0,value);
00410 }
00411
00412 Instruction Instruction::generateAddImmShifted(uint32_t tgt,uint32_t src,int32_t imm){
00413 Instruction ret;
00414 ret.ppci.d.opc = opcode_Addis;
00415 ret.ppci.d.rt_s_bf = tgt;
00416 ret.ppci.d.ra = src;
00417 ASSERT(isInLoadOffsetInsnRange(imm));
00418 ret.ppci.d.d_ui_si = imm;
00419 return ret;
00420 }
00421 Instruction Instruction::generateLoad32BitHigh(uint32_t reg,int32_t value){
00422 return generateAddImmShifted(reg,0,(value >> 16));
00423 }
00424 Instruction Instruction::generateOrImm(uint32_t tgt,uint32_t src,int32_t imm){
00425 Instruction ret;
00426 ret.ppci.d.opc = opcode_Ori;
00427 ret.ppci.d.rt_s_bf = src;
00428 ret.ppci.d.ra = tgt;
00429 ret.ppci.d.d_ui_si = imm;
00430 return ret;
00431 }
00432 Instruction Instruction::generateLoad32BitLow(uint32_t reg,int32_t value){
00433 return generateOrImm(reg,reg,(value & 0xffff));
00434 }
00435
00436 Instruction Instruction::generateAnd(uint32_t tgt,uint32_t src1,uint32_t src2){
00437 Instruction ret;
00438 ret.ppci.x.opc = opcode_AndC;
00439 ret.ppci.x.xo = xcode_AndC;
00440 ret.ppci.x.rt_s_bf = src1;
00441 ret.ppci.x.ra_sr = tgt;
00442 ret.ppci.x.rb_sh = src2;
00443 ret.ppci.x.rc = 0;
00444 return ret;
00445 }
00446
00447 Instruction Instruction::generateXorImm(uint32_t tgt,uint32_t src,int32_t imm){
00448 Instruction ret;
00449 ret.ppci.d.opc = opcode_Xori;
00450 ret.ppci.d.rt_s_bf = src;
00451 ret.ppci.d.ra = tgt;
00452 ret.ppci.d.d_ui_si = imm;
00453 return ret;
00454 }
00455 Instruction Instruction::generateXorImmShifted(uint32_t tgt,uint32_t src,int32_t imm){
00456 Instruction ret;
00457 ret.ppci.d.opc = opcode_Xoris;
00458 ret.ppci.d.rt_s_bf = src;
00459 ret.ppci.d.ra = tgt;
00460 ret.ppci.d.d_ui_si = imm;
00461 return ret;
00462 }
00463 Instruction Instruction::multiplyImmediate(uint32_t tgt,uint32_t src,int32_t imm){
00464 Instruction ret;
00465 ret.ppci.d.opc = opcode_Mulli;
00466 ret.ppci.d.rt_s_bf = tgt;
00467 ret.ppci.d.ra = src;
00468 ASSERT(isInLoadOffsetInsnRange(imm));
00469 ret.ppci.d.d_ui_si = imm;
00470 return ret;
00471 }
00472
00473 Instruction Instruction::generateStoreDoubleFloat(uint32_t src,uint32_t base,int32_t offset){
00474 Instruction ret;
00475 ASSERT(!(offset & 0x3));
00476 ASSERT(isInLoadOffsetInsnRange(offset));
00477 ret.ppci.d.opc = opcode_Stfd;
00478 ret.ppci.d.rt_s_bf = src;
00479 ret.ppci.d.ra = base;
00480 ret.ppci.d.d_ui_si = offset;
00481 return ret;
00482 }
00483 Instruction Instruction::generateLoadDoubleFloat(uint32_t tgt,uint32_t base,int32_t offset){
00484 Instruction ret;
00485 ASSERT(!(offset & 0x3));
00486 ASSERT(isInLoadOffsetInsnRange(offset));
00487 ret.ppci.d.opc = opcode_Lfd;
00488 ret.ppci.d.rt_s_bf = tgt;
00489 ret.ppci.d.ra = base;
00490 ret.ppci.d.d_ui_si = offset;
00491 return ret;
00492 }
00493 Instruction Instruction::generateStoreWordFloat(uint32_t src,uint32_t base,int32_t offset){
00494 Instruction ret;
00495 ASSERT(!(offset & 0x3));
00496 ASSERT(isInLoadOffsetInsnRange(offset));
00497 ret.ppci.d.opc = opcode_Stfs;
00498 ret.ppci.d.rt_s_bf = src;
00499 ret.ppci.d.ra = base;
00500 ret.ppci.d.d_ui_si = offset;
00501 return ret;
00502 }
00503 Instruction Instruction::generateLoadWordFloat(uint32_t tgt,uint32_t base,int32_t offset){
00504 Instruction ret;
00505 ASSERT(!(offset & 0x3));
00506 ASSERT(isInLoadOffsetInsnRange(offset));
00507 ret.ppci.d.opc = opcode_Lfs;
00508 ret.ppci.d.rt_s_bf = tgt;
00509 ret.ppci.d.ra = base;
00510 ret.ppci.d.d_ui_si = offset;
00511 return ret;
00512 }
00513
00514 Instruction Instruction::generateStoreDouble(uint32_t src,uint32_t base,int32_t offset){
00515 Instruction ret;
00516 ret.ppci.ds.opc = opcode_Std;
00517 ret.ppci.ds.xo = xcode_Std;
00518 ret.ppci.ds.rt_s = src;
00519 ret.ppci.ds.ra = base;
00520 ASSERT(!(offset & 0x3));
00521 ASSERT(isInLoadOffsetInsnRange(offset));
00522 offset >>= 2;
00523 ret.ppci.ds.ds = offset;
00524 return ret;
00525 }
00526 Instruction Instruction::generateLoadDouble(uint32_t tgt,uint32_t base,int32_t offset){
00527 Instruction ret;
00528 ret.ppci.ds.opc = opcode_Ld;
00529 ret.ppci.ds.xo = xcode_Ld;
00530 ret.ppci.ds.rt_s = tgt;
00531 ret.ppci.ds.ra = base;
00532 ASSERT(!(offset & 0x3));
00533 ASSERT(isInLoadOffsetInsnRange(offset));
00534 offset >>= 2;
00535 ret.ppci.ds.ds = offset;
00536 return ret;
00537 }
00538
00539 Instruction Instruction::generateStoreWord(uint32_t src,uint32_t base,int32_t offset){
00540 Instruction ret;
00541 ret.ppci.d.opc = opcode_Stw;
00542 ret.ppci.d.rt_s_bf = src;
00543 ret.ppci.d.ra = base;
00544 ASSERT(!(offset & 0x3));
00545 ASSERT(isInLoadOffsetInsnRange(offset));
00546 ret.ppci.d.d_ui_si = offset;
00547 return ret;
00548 }
00549 Instruction Instruction::generateLoadWordIndx(uint32_t tgt,uint32_t base1,uint32_t base2){
00550 Instruction ret;
00551 ret.ppci.x.opc = opcode_Lwzx;
00552 ret.ppci.x.xo = xcode_Lwzx;
00553 ret.ppci.x.rt_s_bf = tgt;
00554 ret.ppci.x.ra_sr = base1;
00555 ret.ppci.x.rb_sh = base2;
00556 ret.ppci.x.rc = 0;
00557 return ret;
00558 }
00559 Instruction Instruction::generateStoreWordIndx(uint32_t src,uint32_t base1,uint32_t base2){
00560 Instruction ret;
00561 ret.ppci.x.opc = opcode_Stwx;
00562 ret.ppci.x.xo = xcode_Stwx;
00563 ret.ppci.x.rt_s_bf = src;
00564 ret.ppci.x.ra_sr = base1;
00565 ret.ppci.x.rb_sh = base2;
00566 ret.ppci.x.rc = 0;
00567 return ret;
00568 }
00569
00570 Instruction Instruction::generateLoadDoubleIndx(uint32_t tgt,uint32_t base1,uint32_t base2){
00571 Instruction ret;
00572 ret.ppci.x.opc = opcode_Ldx;
00573 ret.ppci.x.xo = xcode_Ldx;
00574 ret.ppci.x.rt_s_bf = tgt;
00575 ret.ppci.x.ra_sr = base1;
00576 ret.ppci.x.rb_sh = base2;
00577 ret.ppci.x.rc = 0;
00578 return ret;
00579 }
00580 Instruction Instruction::generateStoreDoubleIndx(uint32_t src,uint32_t base1,uint32_t base2){
00581 Instruction ret;
00582 ret.ppci.x.opc = opcode_Stdx;
00583 ret.ppci.x.xo = xcode_Stdx;
00584 ret.ppci.x.rt_s_bf = src;
00585 ret.ppci.x.ra_sr = base1;
00586 ret.ppci.x.rb_sh = base2;
00587 ret.ppci.x.rc = 0;
00588 return ret;
00589 }
00590
00591 Instruction Instruction::generateLoadWord(uint32_t tgt,uint32_t base,int32_t offset){
00592 Instruction ret;
00593 ret.ppci.d.opc = opcode_Lwz;
00594 ret.ppci.d.rt_s_bf = tgt;
00595 ret.ppci.d.ra = base;
00596 ASSERT(!(offset & 0x3));
00597 ASSERT(isInLoadOffsetInsnRange(offset));
00598 ret.ppci.d.d_ui_si = offset;
00599 return ret;
00600 }
00601 Instruction Instruction::generateMoveToSPR(uint32_t tgt,uint32_t regcode){
00602 Instruction ret;
00603 ret.ppci.xfx.opc = opcode_Mtspr;
00604 ret.ppci.xfx.xo = xcode_Mtspr;
00605 ret.ppci.xfx.rt_rs = tgt;
00606 ret.ppci.xfx.spr_tbr = regcode;
00607 return ret;
00608 }
00609
00610 Instruction Instruction::generateMoveFromSPR(uint32_t src,uint32_t regcode){
00611 Instruction ret;
00612 ret.ppci.xfx.opc = opcode_Mfspr;
00613 ret.ppci.xfx.xo = xcode_Mfspr;
00614 ret.ppci.xfx.rt_rs = src;
00615 ret.ppci.xfx.spr_tbr = regcode;
00616 return ret;
00617 }
00618 Instruction Instruction::generateMoveFromCR(uint32_t tgt){
00619 Instruction ret;
00620 ret.ppci.xfx.opc = opcode_Mfcr;
00621 ret.ppci.xfx.xo = xcode_Mfcr;
00622 ret.ppci.xfx.rt_rs = tgt;
00623 ret.ppci.xfx.spr_tbr = 0x0;
00624 return ret;
00625 }
00626 Instruction Instruction::generateMoveToCR(uint32_t src){
00627 Instruction ret;
00628 ret.ppci.xfx.opc = opcode_Mtcrf;
00629 ret.ppci.xfx.xo = xcode_Mtcrf;
00630 ret.ppci.xfx.rt_rs = src;
00631 ret.ppci.xfx.spr_tbr = 0x1fe;
00632 return ret;
00633 }
00634 Instruction Instruction::generateMoveFromFPSCR(uint32_t tgt){
00635 Instruction ret;
00636 ret.ppci.x.opc = opcode_MffsC;
00637 ret.ppci.x.xo = xcode_MffsC;
00638 ret.ppci.x.rt_s_bf = tgt;
00639 ret.ppci.x.rc = 0;
00640 return ret;
00641 }
00642 Instruction Instruction::generateMoveToFPSCR(uint32_t src){
00643 Instruction ret;
00644 ret.ppci.xfl.opc = opcode_MtfsfC;
00645 ret.ppci.xfl.xo = xcode_MtfsfC;
00646 ret.ppci.xfl.frb = src;
00647 ret.ppci.xfl.flm = 0xff;
00648 ret.ppci.xfl.rc = 0;
00649 return ret;
00650 }
00651
00652 Instruction Instruction::generateCallToCTR(){
00653 Instruction ret;
00654 ret.ppci.xl.opc = opcode_BcctrL;
00655 ret.ppci.xl.xo = xcode_BcctrL;
00656 ret.ppci.xl.lk = 1;
00657 ret.ppci.xl.bt_bo = 0x14;
00658 ret.ppci.xl.ba_bi = 0x0;
00659 ret.ppci.xl.bb = 0x0;
00660 return ret;
00661 }
00662
00663 Instruction Instruction::generateReturnToLnk(){
00664 Instruction ret;
00665 ret.ppci.xl.opc = opcode_BclrL;
00666 ret.ppci.xl.xo = xcode_BclrL;
00667 ret.ppci.xl.lk = 0;
00668 ret.ppci.xl.bt_bo = 0x14;
00669 ret.ppci.xl.ba_bi = 0x0;
00670 ret.ppci.xl.bb = 0x0;
00671 return ret;
00672 }
00673
00674 Instruction Instruction::generateCallToImmediate(uint64_t from,uint64_t to){
00675 Instruction ret = generateJumpInsn(from,to);
00676 ret.ppci.i.lk = 1;
00677 return ret;
00678 }
00679
00680 Instruction Instruction::generateMoveReg(uint32_t from,uint32_t to){
00681 Instruction ret;
00682 ret.ppci.x.opc = opcode_OrC;
00683 ret.ppci.x.xo = xcode_OrC;
00684 ret.ppci.x.rt_s_bf = from;
00685 ret.ppci.x.ra_sr = to;
00686 ret.ppci.x.rb_sh = from;
00687 ret.ppci.x.rc = 0;
00688 return ret;
00689 }
00690
00691 Instruction Instruction::generateSPIncrementWord(int32_t offset){
00692 Instruction ret;
00693 ret.ppci.d.opc = opcode_Stwu;
00694 ret.ppci.d.rt_s_bf = REG_SP;
00695 ret.ppci.d.ra = REG_SP;
00696 ASSERT(!(offset & 0x3));
00697 ASSERT(isInLoadOffsetInsnRange(offset));
00698 ret.ppci.d.d_ui_si = offset;
00699 return ret;
00700 }
00701 Instruction Instruction::generateSPIncrementDouble(int32_t offset){
00702 Instruction ret;
00703 ret.ppci.ds.opc = opcode_Stdu;
00704 ret.ppci.ds.xo = xcode_Stdu;
00705 ret.ppci.ds.rt_s = REG_SP;
00706 ret.ppci.ds.ra = REG_SP;
00707 ASSERT(!(offset & 0x3));
00708 ASSERT(isInLoadOffsetInsnRange(offset));
00709 offset >>= 2;
00710 ret.ppci.ds.ds = offset;
00711 return ret;
00712 }
00713
00714 Instruction Instruction::generateCompare(uint32_t reg1,uint32_t reg2,uint32_t field){
00715 Instruction ret;
00716 ret.ppci.x.opc = opcode_Cmpl;
00717 ret.ppci.x.xo = xcode_Cmpl;
00718 ret.ppci.x.rt_s_bf = field << 2;
00719 ret.ppci.x.ra_sr = reg1;
00720 ret.ppci.x.rb_sh = reg2;
00721 return ret;
00722 }
00723
00724 Instruction Instruction::generateCondBranch(uint32_t field,uint32_t op,uint32_t tf,int32_t offset){
00725 Instruction ret;
00726 ret.ppci.b.opc = opcode_BcLA;
00727 ret.ppci.b.bo = (0x7 | (tf << 3));
00728 ret.ppci.b.bi = (field << 2) + op;
00729 ASSERT(!(offset & 0x3));
00730 ASSERT(isInLoadOffsetInsnRange(offset));
00731 offset >>= 2;
00732 ret.ppci.b.bd = offset;
00733 ret.ppci.b.aa = 0x0;
00734 ret.ppci.b.lk = 0x0;
00735 return ret;
00736 }
00737
00738 bool Instruction::isMemoryDFormFloat(){
00739 return ((ppci.opc.opc >= opcode_Lfs) &&
00740 (ppci.opc.opc <= opcode_Stfdu));
00741 }