00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "global.h"
00041 #include "proc.h"
00042 #include "prog.h"
00043 #include "decoder.h"
00044 #include "hppadecoder.h"
00045 #include "ss.h"
00046 #include "rtl.h"
00047 #include "csr.h"
00048 #include "hppa.pat.h"
00049 #include "hppa-names.h"
00050
00051 #include "BinaryFile.h"
00052
00053
00054 static const JCOND_TYPE hl_jcond_type = {
00055 HLJCOND_JNE,
00056 HLJCOND_JE,
00057 HLJCOND_JSL,
00058 HLJCOND_JSLE,
00059 HLJCOND_JUL,
00060 HLJCOND_JULE,
00061 HLJCOND_JOF,
00062 HLJCOND_JNE,
00063 HLJCOND_JE,
00064 HLJCOND_JNE,
00065 HLJCOND_JSGE,
00066 HLJCOND_JSG,
00067 HLJCOND_JUGE,
00068 HLJCOND_JUG,
00069 HLJCOND_JNOF,
00070 HLJCOND_JE
00071 };
00072
00073
00074 void c_addr(ADDRESS hostpc, SemStr* ssb, SemStr* ssx);
00075
00076 bool is_null(ADDRESS hostPC)
00077 {
00078 bool res;
00079 match hostPC to
00080 | c_br_nnull() => {
00081 res = false;
00082 }
00083 | c_br_null() => {
00084 res = true;
00085 }
00086 endmatch
00087
00088 return res;
00089 }
00090
00091
00092 DecodeResult& NJMCDecoder::decodeInstruction (ADDRESS pc, int delta,
00093 UserProc* proc )
00094 {
00095 static DecodeResult result;
00096 ADDRESS hostPC = pc+delta;
00097
00098
00099 result.reset();
00100
00101
00102 list<RT*>* RTs = NULL;
00103 preInstSem = NULL;
00104 postInstSem = NULL;
00105
00106 ADDRESS nextPC;
00107
00108
00109 ADDRESS saveHostPC = hostPC;
00110 int addr, locals, libstub;
00111 Logue* logue;
00112
00113 if ((logue = InstructionPatterns::std_call(csr,hostPC,addr)) != NULL) {
00114
00115
00116
00117 HLCall* newCall = new HLCall(pc, 0, RTs);
00118
00119
00120 newCall->setDest(addr + pc);
00121 result.numBytes = hostPC - saveHostPC;
00122
00123 const char* dest = prog.pBF->SymbolByAddress((ADDRESS)(addr + pc));
00124 if (dest && (strcmp(dest, "__main") == 0)) {
00125
00126 } else {
00127
00128 result.rtl = newCall;
00129 result.type = SD;
00130
00131
00132 newCall->setPrologue(logue);
00133
00134 SHOW_ASM("std_call 0x" << hex << addr-delta)
00135 }
00136 }
00137
00138
00139
00140
00141 else if ((logue = InstructionPatterns::gcc_frame(csr,hostPC, locals))
00142 != NULL) {
00143
00144
00145
00146
00147 if (proc != NULL) {
00148
00149
00150 assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00151 proc->setPrologue((CalleePrologue*)logue);
00152 }
00153
00154 result.numBytes = hostPC - saveHostPC;
00155 result.rtl = new RTL(pc,RTs);
00156 result.type = NCT;
00157 SHOW_ASM("gcc_frame " << dec << locals)
00158 }
00159 else if ((logue = InstructionPatterns::gcc_frameless(csr,hostPC, locals))
00160 != NULL) {
00161
00162
00163
00164 if (proc != NULL) {
00165
00166
00167 assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00168 proc->setPrologue((CalleePrologue*)logue);
00169 }
00170
00171 result.numBytes = hostPC - saveHostPC;
00172 result.rtl = new RTL(pc,RTs);
00173 result.type = NCT;
00174 SHOW_ASM("gcc_frameless " << dec << locals)
00175 }
00176 else if ((locals=8, logue = InstructionPatterns::param_reloc1(csr,hostPC,
00177 libstub, locals)) != NULL) {
00178
00179
00180
00181
00182 if (proc != NULL) {
00183
00184 assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00185 proc->setPrologue((CalleePrologue*)logue);
00186 }
00187
00188
00189
00190
00191
00192 SemStr* ssSrc = new SemStr;
00193 SemStr* ssDst = new SemStr;
00194 *ssSrc << idRegOf << idIntConst << 39;
00195 *ssDst << idMemOf << idAFP;
00196 RTs = new list<RT*>;
00197 RTAssgn* pRt = new RTAssgn(ssDst, ssSrc, 64); RTs->push_back(pRt);
00198
00199 ssSrc = new SemStr; ssDst = new SemStr;
00200 *ssSrc << idMemOf << idAFP;
00201 *ssDst << idRegOf << idIntConst << 23;
00202 pRt = new RTAssgn(ssDst, ssSrc, 32);
00203 RTs->push_back(pRt);
00204
00205 ssSrc = new SemStr; ssDst = new SemStr;
00206 *ssSrc << idMemOf << idPlus << idAFP << idIntConst << 4;
00207 *ssDst << idRegOf << idIntConst << 24;
00208 pRt = new RTAssgn(ssDst, ssSrc, 32); RTs->push_back(pRt);
00209
00210
00211
00212 ADDRESS dest = pc + 12 + libstub;
00213
00214 HLCall* newCall = new HLCall(pc, 0, RTs);
00215
00216 newCall->setDest(dest);
00217 newCall->setReturnAfterCall(true);
00218 result.numBytes = hostPC - saveHostPC;
00219 result.rtl = newCall;
00220 result.type = SU;
00221
00222
00223 newCall->setPrologue(logue);
00224 SHOW_ASM("param_reloc1 " << hex << dest)
00225 }
00226
00227
00228
00229
00230 else if ((logue = InstructionPatterns::gcc_unframe(csr, hostPC)) != NULL) {
00231
00232
00233
00234
00235 result.numBytes = hostPC - saveHostPC;
00236 result.rtl = new HLReturn(pc,RTs);
00237 result.type = DU;
00238
00239
00240 if (proc != NULL) {
00241 assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00242 proc->setEpilogue((CalleeEpilogue*)logue);
00243 }
00244
00245 SHOW_ASM("gcc_unframe");
00246 }
00247 else if ((logue = InstructionPatterns::gcc_unframeless1(csr, hostPC)) !=
00248 NULL) {
00249
00250
00251
00252 result.numBytes = hostPC - saveHostPC;
00253 result.rtl = new HLReturn(pc,RTs);
00254
00255
00256 result.type = DU;
00257
00258
00259 if (proc != NULL) {
00260 assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00261 proc->setEpilogue((CalleeEpilogue*)logue);
00262 }
00263
00264 SHOW_ASM("gcc_unframeless1");
00265 }
00266 else if ((logue = InstructionPatterns::gcc_unframeless2(csr, hostPC)) !=
00267 NULL) {
00268
00269
00270
00271 result.numBytes = hostPC - saveHostPC;
00272 result.rtl = new HLReturn(pc,RTs);
00273 result.type = DU;
00274
00275
00276 if (proc != NULL) {
00277 assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00278 proc->setEpilogue((CalleeEpilogue*)logue);
00279 }
00280
00281 SHOW_ASM("gcc_unframeless2");
00282 }
00283 else if ((logue = InstructionPatterns::bare_ret(csr, hostPC)) != NULL) {
00284
00285
00286
00287 result.numBytes = 8;
00288 result.rtl = new HLReturn(pc, RTs);
00289
00290
00291 result.type = DD;
00292
00293
00294 if (proc != NULL) {
00295 assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00296 proc->setEpilogue((CalleeEpilogue*)logue);
00297 }
00298
00299 SHOW_ASM("bare_ret");
00300 }
00301 else if ((logue = InstructionPatterns::bare_ret_anulled(csr, hostPC))
00302 != NULL) {
00303
00304
00305
00306 result.numBytes = 4;
00307 result.rtl = new HLReturn(pc, RTs);
00308 result.type = DU;
00309
00310
00311 if (proc != NULL) {
00312 assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00313 proc->setEpilogue((CalleeEpilogue*)logue);
00314 }
00315
00316 SHOW_ASM("bare_ret_anulled");
00317 }
00318
00319 else {
00320
00321 match hostPC to
00322 | BL (nulli, ubr_target, t_06) => {
00323 HLJump* jump;
00324
00325 if ((t_06 == 2) || (t_06 == 31))
00326 jump = new HLCall(pc, 0, RTs);
00327 if ((t_06 != 2) && (t_06 != 31))
00328 jump = new HLJump(pc, RTs);
00329 result.rtl = jump;
00330 bool isNull = is_null(nulli);
00331 if (isNull)
00332 result.type = SU;
00333 if (!isNull)
00334 result.type = SD;
00335 jump->setDest(ubr_target + pc);
00336 result.numBytes = 4;
00337 }
00338
00339 | bb_all(c_cmplt, null_cmplt, r, bit_cmplt, target) => {
00340 int condvalue;
00341 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00342 HLJcond* jump = new HLJcond(pc, RTs);
00343 jump->setDest(dis_Num(target + pc + 8));
00344 SemStr* reg = dis_Reg(r);
00345 SemStr* mask = dis_c_bit(bit_cmplt);
00346 SemStr* exp = new SemStr;
00347 *exp << idBitAnd << *mask << *reg;
00348 substituteCallArgs("c_c", cond_ss, mask, reg, exp);
00349 jump->setCondExpr(cond_ss);
00350 bool isNull = is_null(null_cmplt);
00351 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00352 result.rtl = jump;
00353 result.numBytes = 4;
00354 }
00355
00356 | cmpib_all(c_cmplt, null_cmplt, im5_11, r_06, target) => {
00357 int condvalue;
00358 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00359 HLJcond* jump = new HLJcond(pc, RTs);
00360 jump->setCondType(hl_jcond_type[condvalue]);
00361 jump->setDest(dis_Num(target + pc + 8));
00362 SemStr* imm = dis_Num(im5_11);
00363 SemStr* reg = dis_Reg(r_06);
00364 reg->prep(idRegOf);
00365 SemStr* exp = new SemStr;
00366 *exp << idMinus << *imm << *reg;
00367 substituteCallArgs("c_c", cond_ss, imm, reg, exp);
00368 jump->setCondExpr(cond_ss);
00369 bool isNull = is_null(null_cmplt);
00370
00371 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00372 result.rtl = jump;
00373 result.numBytes = 4;
00374 }
00375
00376 | cmpb_all(c_cmplt, null_cmplt, r1, r2, target) => {
00377 int condvalue;
00378 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00379 HLJcond* jump = new HLJcond(pc, RTs);
00380 jump->setCondType(hl_jcond_type[condvalue]);
00381 jump->setDest(dis_Num(target + pc + 8));
00382 SemStr* reg1 = dis_Reg(r1);
00383 SemStr* reg2 = dis_Reg(r2);
00384 reg1->prep(idRegOf);
00385 reg2->prep(idRegOf);
00386 SemStr* exp = new SemStr;
00387 *exp << idMinus << *reg1 << *reg2;
00388 substituteCallArgs("c_c", cond_ss, reg1, reg2, exp);
00389 jump->setCondExpr(cond_ss);
00390 bool isNull = is_null(null_cmplt);
00391
00392 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00393 result.rtl = jump;
00394 result.numBytes = 4;
00395 }
00396 | addib_all(c_cmplt, null_cmplt, im5_11, r_06, target) => {
00397 int condvalue;
00398 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00399
00400 RTs = instantiate(pc, name, dis_Num(im5_11), dis_Reg(r_06));
00401 HLJcond* jump = new HLJcond(pc, RTs);
00402 jump->setCondType(hl_jcond_type[condvalue]);
00403 jump->setDest(dis_Num(target + pc + 8));
00404 SemStr* imm = dis_Num(im5_11);
00405 SemStr* reg = dis_Reg(r_06);
00406 reg->prep(idRegOf);
00407 SemStr* tgt = new SemStr(*reg);
00408 substituteCallArgs("c_c", cond_ss, imm, reg, tgt);
00409 jump->setCondExpr(cond_ss);
00410 bool isNull = is_null(null_cmplt);
00411
00412 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00413 result.rtl = jump;
00414 result.numBytes = 4;
00415 }
00416 | MOVB (c_cmplt, null_cmplt, r1, r2, target) => {
00417 int condvalue;
00418 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00419 RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2));
00420 HLJcond* jump = new HLJcond(pc, RTs);
00421 jump->setCondType(hl_jcond_type[condvalue]);
00422 jump->setDest(dis_Num(target + pc + 8));
00423 SemStr* reg1 = dis_Reg(r1);
00424 SemStr* reg2 = dis_Reg(r2);
00425 reg1->prep(idRegOf);
00426 reg2->prep(idRegOf);
00427 SemStr* tgt = new SemStr(*reg2);
00428 substituteCallArgs("c_c", cond_ss, reg1, reg2, tgt);
00429 jump->setCondExpr(cond_ss);
00430 bool isNull = is_null(null_cmplt);
00431 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00432 result.rtl = jump;
00433 result.numBytes = 4;
00434 }
00435 | MOVIB (c_cmplt, null_cmplt, i, r, target) => {
00436 int condvalue;
00437 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00438 RTs = instantiate(pc, name, dis_Num(i), dis_Reg(r));
00439 HLJcond* jump = new HLJcond(pc, RTs);
00440 jump->setCondType(hl_jcond_type[condvalue]);
00441 jump->setDest(dis_Num(target + pc + 8));
00442 SemStr* imm = dis_Reg(i);
00443 SemStr* reg = dis_Reg(r);
00444 imm->prep(idIntConst);
00445 reg->prep(idRegOf);
00446 SemStr* tgt = new SemStr(*reg);
00447 substituteCallArgs("c_c", cond_ss, imm, reg, tgt);
00448 jump->setCondExpr(cond_ss);
00449 bool isNull = is_null(null_cmplt);
00450 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00451 result.rtl = jump;
00452 result.numBytes = 4;
00453 }
00454 | addb_all(c_cmplt, null_cmplt, r1, r2, target) => {
00455 int condvalue;
00456 SemStr* cond_ss = c_c(c_cmplt, condvalue);
00457
00458 RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2));
00459 HLJcond* jump = new HLJcond(pc, RTs);
00460 jump->setCondType(hl_jcond_type[condvalue]);
00461 jump->setDest(dis_Num(target + pc + 8));
00462 SemStr* reg1 = dis_Reg(r1);
00463 SemStr* reg2 = dis_Reg(r2);
00464 reg1->prep(idRegOf);
00465 reg2->prep(idRegOf);
00466 SemStr* tgt = new SemStr(*reg2);
00467 substituteCallArgs("c_c", cond_ss, reg1, reg2, tgt);
00468 jump->setCondExpr(cond_ss);
00469 bool isNull = is_null(null_cmplt);
00470
00471 result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00472 result.rtl = jump;
00473 result.numBytes = 4;
00474 }
00475
00476
00477 | arith(cmplt, r_11, r_06, t_27) => {
00478
00479 low_level(RTs, hostPC, pc, result, nextPC);
00480 int condvalue;
00481 c_c(cmplt, condvalue);
00482 if (condvalue != 0)
00483
00484
00485
00486
00487 result.type = NCTA;
00488 not_used(r_11); not_used(r_06); not_used(t_27);
00489 }
00490 | arith_imm(cmplt, imm11, r_06, t_11) => {
00491
00492 low_level(RTs, hostPC, pc, result, nextPC);
00493 int condvalue;
00494 c_c(cmplt, condvalue);
00495 if (condvalue != 0)
00496
00497
00498 result.type = NCTA;
00499 not_used(imm11); not_used(r_06); not_used(t_11);
00500 }
00501 else {
00502
00503 low_level(RTs, hostPC, pc, result, nextPC);
00504 }
00505 endmatch
00506 }
00507 return result;
00508 }
00509
00510
00511 void NJMCDecoder::low_level(list<RT*>*& RTs, ADDRESS hostPC, ADDRESS pc,
00512 DecodeResult& result, ADDRESS& nextPC)
00513 {
00514 RTs = decodeLowLevelInstruction(hostPC, pc, result);
00515 if (preInstSem && RTs)
00516 RTs->insert(RTs->begin(), preInstSem->begin(), preInstSem->end());
00517 if (postInstSem && RTs)
00518 RTs->insert(RTs->end(), postInstSem->begin(), postInstSem->end());
00519 result.rtl = new RTL(pc, RTs);
00520 nextPC = hostPC + 4;
00521 result.numBytes = 4;
00522 }
00523
00524 SemStr* NJMCDecoder::dis_c_bit(ADDRESS hostpc)
00525 {
00526 SemStr* result;
00527 match hostpc to
00528 | c_bitpos_w(p) => {
00529 result = instantiateNamedParam( "bitpos_fix", dis_Num(p));
00530 }
00531 | c_bitsar() => {
00532 result = instantiateNamedParam( "bitpos_sar", dis_Num(0));
00533 }
00534 endmatch
00535 return result;
00536 }
00537
00538 SemStr* NJMCDecoder::dis_xd(ADDRESS hostpc)
00539 {
00540 SemStr* result;
00541 match hostpc to
00542 | x_addr_nots(x) => {
00543 result = instantiateNamedParam( "x_addr_nots" , dis_Reg(x));
00544 }
00545 | x_addr_s_byte(x) => {
00546 result = instantiateNamedParam( "x_addr_s_byte" , dis_Reg(x));
00547 }
00548 | x_addr_s_hwrd(x) => {
00549 result = instantiateNamedParam( "x_addr_s_hwrd" , dis_Reg(x));
00550 }
00551 | x_addr_s_word(x) => {
00552 result = instantiateNamedParam( "x_addr_s_word" , dis_Reg(x));
00553 }
00554 | x_addr_s_dwrd(x) => {
00555 result = instantiateNamedParam( "x_addr_s_dwrd" , dis_Reg(x));
00556 }
00557 | s_addr_im_r(i) => {
00558 result = instantiateNamedParam( "s_addr_im_r" , dis_Num(i));
00559 }
00560 | s_addr_r_im(i) => {
00561 result = instantiateNamedParam( "s_addr_r_im" , dis_Num(i));
00562 }
00563 | l_addr_16_old(i) => {
00564 result = instantiateNamedParam( "l_addr_16_old" , dis_Num(i));
00565 }
00566 | l_addr_17_old(i) => {
00567 result = instantiateNamedParam( "l_addr_17_old" , dis_Num(i));
00568 }
00569 endmatch
00570 return result;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 SemStr* NJMCDecoder::dis_c_addr(ADDRESS hostPC)
00584 {
00585 SemStr* result = NULL;
00586 match hostPC to
00587 | c_s_addr_mb() =>
00588 { result = instantiateNamedParam( "c_s_addr_mb" ); }
00589 | c_s_addr_ma() =>
00590 { result = instantiateNamedParam( "c_s_addr_ma" ); }
00591 | c_s_addr_notm() =>
00592 { result = instantiateNamedParam( "c_s_addr_notm" ); }
00593 | c_x_addr_m() =>
00594 { result = instantiateNamedParam( "c_x_addr_m" ); }
00595 | c_x_addr_notm() =>
00596 { result = instantiateNamedParam( "c_x_addr_notm" ); }
00597 | c_y_addr_e() =>
00598 { result = instantiateNamedParam( "c_y_addr_e" ); }
00599 | c_y_addr_m() =>
00600 { result = instantiateNamedParam( "c_y_addr_m" ); }
00601 | c_y_addr_me() =>
00602 { result = instantiateNamedParam( "c_y_addr_me" ); }
00603 | c_y_addr_none() =>
00604 { result = instantiateNamedParam( "c_y_addr_none" ); }
00605 | c_l_addr_none() =>
00606 { result = instantiateNamedParam( "c_l_addr_none" ); }
00607 endmatch
00608 return result;
00609 }
00610
00611 SemStr* NJMCDecoder::dis_c_wcr(unsigned hostPC)
00612 {
00613 return 0;
00614 }
00615
00616 SemStr* NJMCDecoder::dis_ct(unsigned hostPC)
00617 {
00618 return 0;
00619 }
00620
00621 SemStr* NJMCDecoder::dis_Freg(int regNum, int fmt)
00622 {
00623 int r;
00624 switch (fmt) {
00625 case 0:
00626 r = regNum + 64;
00627 break;
00628 case 1:
00629 r = regNum + 32;
00630 break;
00631 case 2:
00632 r = regNum + 128;
00633 break;
00634 default:
00635 printf("Error decoding floating point register %d with format %d\n",
00636 regNum, fmt);
00637 r = 0;
00638 }
00639 SemStr* ss = new SemStr;
00640 *ss << idIntConst << r;
00641 return ss;
00642 }
00643
00644 SemStr* NJMCDecoder::dis_Creg(int regNum)
00645 {
00646 SemStr* ss = new SemStr;
00647 *ss << idIntConst << (regNum + 256);
00648 return ss;
00649 }
00650
00651 SemStr* NJMCDecoder::dis_Sreg(int regNum)
00652 {
00653 SemStr* ss = new SemStr;
00654 *ss << idIntConst << regNum;
00655 return ss;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 bool isFuncPrologue(ADDRESS hostPC)
00667 {
00668 #if 0
00669 int hiVal, loVal, reg, locals;
00670 if ((InstructionPatterns::new_reg_win(prog.csrSrc,hostPC, locals)) != NULL)
00671 return true;
00672 if ((InstructionPatterns::new_reg_win_large(prog.csrSrc, hostPC,
00673 hiVal, loVal, reg)) != NULL)
00674 return true;
00675 if ((InstructionPatterns::same_reg_win(prog.csrSrc, hostPC, locals))
00676 != NULL)
00677 return true;
00678 if ((InstructionPatterns::same_reg_win_large(prog.csrSrc, hostPC,
00679 hiVal, loVal, reg)) != NULL)
00680 return true;
00681 #endif
00682
00683 return false;
00684 }
00685