⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynamicarmcode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      next_set = true;
   }
   virtual void MoveBack(){ move_back = true; }      //was: MB()
   //void DS(){ delay_slot = true; }

   void InstPost(S_instruction *p){
      InstAdd(p);
      InstInit();
   }

//----------------------------

   virtual void *Label(bool do_post){
      S_instruction *p = InstCreate(NULL, 0, NONE, NONE, NONE, 0, 0);
      p->branch = true;
      if(do_post)
         InstPost(p);
      return p;
   }

//----------------------------

   virtual void PutLabel(void *label){
      S_instruction *ins = (S_instruction*)label;
                              //make sure it was not already posted
      assert(!ins->next);
      InstPost(ins);
   }

//----------------------------

   virtual void *DeclareData(void *data, dword data_size){
      S_instruction *p = InstCreate(data, data_size, NONE, NONE, NONE, 0, 0);
      p->branch = true;
      return p;
   }

//----------------------------

   virtual void StoreLabelAddress(void *label){

      S_instruction *p = InstCreate32(NULL, NONE, NONE, NONE, 0, 0);
      p->realloc = (S_instruction*)label;
      p->branch = true;
      InstPost(p);
   }

//----------------------------

   virtual void Align(dword bytes){
      S_instruction *p = InstCreate(NULL, -(int)bytes, NONE, NONE, NONE, 0, 0);
      p->branch = true;
      InstPost(p);
      max_align = Max(max_align, bytes);
   }

//----------------------------

   /*
   void Break(){

      S_instruction *p = InstCreate32((next_cond << 28) | (15 << 24));
      p->branch = true;
      InstPost(p);
   }
   */

//----------------------------

   virtual void FunctionBegin(dword _local_vars_size){
                              // stmfd sp!, { r4 - r11, lr }
      S_instruction *p = InstCreate32(0xe92d4ff0, sp);
      p->is_function = true;
      for(int i=4; i<16; ++i)
         p->read_regs |= 1 << i;
      InstPost(p);
                              //allocate space for local variables
      local_vars_size = _local_vars_size;
      if(local_vars_size)
         I2C(SUB, sp, sp, local_vars_size);
   }

//----------------------------

   virtual void FunctionEnd(){

      if(local_vars_size){
         I2C(ADD, sp, sp, local_vars_size);
         local_vars_size = 0;
      }
                              // ldmfd sp!, { r4 - r11, pc }
      S_instruction *p = InstCreate32(0xe8bd8ff0, sp);
      for(int i=4;i<16;++i)
         p->write_regs |= 1 << i;
      InstPost(p);
   }

//----------------------------

   virtual void CodeBuild();

//----------------------------

   virtual void I3C(int code, byte Dest, byte op_1, byte Op2, int constant);
   virtual void I3(int code, byte Dest, byte op_1, byte Op2);
   virtual void I3S(int code, byte Dest, byte op_1, byte Op2, E_SHIFT_TYPE ShiftType, int Shift);
   virtual void I4(int code, byte Dest, byte op_1, byte Op2, byte Op3);
   virtual void IConst(byte Dest, int constant);
   virtual void I2(int code, byte Dest, byte op_1);
   virtual void I2C(int code, byte Dest, byte op_1, int constant);
   virtual void I1P(int code, byte Dest, void *block, int Ofs);
   virtual void I0P(int code, int Cond, void *target);

   virtual void MulC(E_REGISTER dst, E_REGISTER src, int constant);

//----------------------------

   virtual void *Code(dword fnc_index) const{

      if(fnc_index >= dynamic_code.functions.Size())
         return NULL;
      return dynamic_code.functions[fnc_index];
   }
};

//----------------------------

void C_dyn_code_imp::InstInit(){
   next_cond = AL;
   next_set = false;
   next_byte = false;
   next_half = false;
   next_sign = false;
}

//----------------------------

C_dyn_code_imp::S_instruction *C_dyn_code_imp::InstCreate(const void *code, int code_size, byte write_reg, byte read_reg_1, byte read_reg_2, int read_flags, int write_flags){

   S_instruction *p = new(true) S_instruction();
   p->read_flags = read_flags;
   p->write_flags = write_flags;

   p->code_size = code_size;
   if(code_size <= (int)sizeof(p->code_small)){
      if(code)
         p->code_small = *(dword*)code;
   }else{
      p->code_large = new(true) byte[code_size];
      if(code)
         MemCpy(p->code_large, code, code_size);
      else
         MemSet(p->code_large, 0, code_size);
   }
      
   StoreReg(p->write_regs, write_reg);
   StoreReg(p->read_regs, read_reg_1);
   StoreReg(p->read_regs, read_reg_2);
   /*
   if(write_reg != NONE){
      if(write_reg<32)
         p->write_regs |= 1 << write_reg;
      else
         p->write_flags |= 256 << (write_reg-32); 
   }
   if(read_reg_1 != NONE){
      if(read_reg_1<32)
         p->read_regs |= 1 << read_reg_1;
      else
         p->read_flags |= 256 << (read_reg_1-32);
   }
   if(read_reg_2 != NONE){
      if(read_reg_2<32)
         p->read_regs |= 1 << read_reg_2;
      else
         p->read_flags |= 256 << (read_reg_2-32);
   }
   */
   return p;
}

//----------------------------

void C_dyn_code_imp::FreeInstructions(){

   for(S_instruction *p = inst_begin; p; ){
      S_instruction *q = p;
      p = p->next;
      if(q->code_large)
         delete[] q->code_large;
      delete q;
   }
   inst_begin = NULL;
   inst_end = NULL;
}

//----------------------------

bool C_dyn_code_imp::InstReAlloc(S_instruction *p, const S_instruction *realloc){

   int Diff = realloc->address - (p->address+8);
   int *code = (int*)InstCode(p);

   if(((*code >> 25) & 7) == 6){ //wldr,wstr
      int Ofs = Diff + p->tag;
      int OfsUnsigned = 1;
      if(Ofs < 0){
         Ofs = -Ofs;
         OfsUnsigned = 0;
      }
      if(*code & 256){
         if(Ofs & 3)
            Ofs = 256;
         else
            Ofs >>= 2;
      }
      if(Ofs < 256){
         *code &= ~(1<<23);
         *code |= OfsUnsigned<<23;
         *code &= ~255;
         *code |= Ofs;
         return true;
      }
      //DEBUG_MSG1(-1,T("Realloc failed for wldr,wstr %d"),Ofs);
   }else
   if(((*code >> 25) & 7) == 5){
                           //branch
      *code &= 0xff000000;
      *code |= (Diff >> 2) & ~0xff000000;
      return true;
   }else
   if(((*code >> 25) & 7) == 1){ //add dest,pc,#const
      int Shift;
      int Ofs = Diff + p->tag;

      *code &= ~((15 << 21)|4095);

      if(Ofs < 0){
         Ofs = -Ofs;
         *code |= (SUB << 21);
      }else
         *code |= (ADD << 21);

      for(Shift = 0;Shift<32;Shift+=2){
         if (Ofs >= 0 && Ofs <= 255)
            break;
         Ofs = (Ofs << 2) | ((Ofs >> 30) & 3);
      }
      if(Ofs >= 0 && Ofs <= 255){
         *code |= (Shift << 7) | Ofs;
         return true;
      }
      //DEBUG_MSG1(-1,T("Realloc failed for add dest,pc,#const %d"),Ofs);
   }else
   if(((*code >> 25) & 7) == 2){ //ldr,str
      int Ofs = Diff + p->tag;
      int OfsUnsigned = 1;
      if(Ofs < 0){
         Ofs = -Ofs;
         OfsUnsigned = 0;
      }
      if(Ofs < 4096){
         *code &= ~(1<<23);
         *code |= OfsUnsigned<<23;
         *code &= ~4095;
         *code |= Ofs;
         return true;
      }
      //DEBUG_MSG1(-1,T("Realloc failed for ldr,str %d"),Ofs);
   }else
   if(!*code){
                              //plain address instantiation
      *code = (int)realloc->address;
      return true;
   }
   return false;
}

//----------------------------

void C_dyn_code_imp::IPLD(int *code, byte *dest){

   switch(*code){
   case PLD:
      next_cond = NV; next_byte = true; *code = LDR; *dest = pc; break;
   case PLD_PRE:
      next_cond = NV; next_byte = true; *code = LDR_PRE; *dest = pc; break;
   case PLD_POST:
      next_cond = NV; next_byte = true; *code = LDR_POST; *dest = pc; break;
   case PLD_PRESUB:
      next_cond = NV; next_byte = true; *code = LDR_PRESUB; *dest = pc; break;
   case PLD_POSTSUB:
      next_cond = NV; next_byte = true; *code = LDR_POSTSUB; *dest = pc; break;
   }
}

//----------------------------

#define MODE(x) ((dword)(x) >> 28)
#define MODEMASK ~0xF0000000

void C_dyn_code_imp::I3C(int code, byte Dest, byte op_1, byte Op2, int constant){

   S_instruction *p = NULL;
   if(MODE(code) == 8 && constant>=0 && constant<8){
      p = InstCreate32((next_cond << 28) | (code & MODEMASK) | ((Dest & 15) << 12) | ((op_1 & 15) << 16) | ((Op2 & 15) << 0) | (constant << 20), 
         Dest, op_1, Op2, (next_cond != AL)?1:0, 0);
   }
   InstPost(p);
}

//----------------------------

void C_dyn_code_imp::I3(int code, byte Dest, byte op_1, byte Op2){

   if(MODE(code) == 4){
      S_instruction *p = InstCreate32((next_cond << 28) | (code & MODEMASK) | ((Dest & 15) << 0) | ((op_1 & 15) << 12) | ((Op2 & 15) << 16),
            Dest, op_1, Op2, (next_cond != AL)?1:0, 0);
      InstPost(p);
   }else
   if(MODE(code) == 7){
      S_instruction *p = InstCreate32((next_cond << 28) | (code & MODEMASK) | ((Dest & 15) << 12) | ((op_1 & 15) << 16) | ((Op2 & 15) << 0),
            Dest, op_1, Op2, (next_cond != AL)?1:0, 0);
      InstPost(p);
   }else
      I3S(code,Dest,op_1,Op2, LSL, 0);
}

//----------------------------

void C_dyn_code_imp::I3S(int code, byte Dest, byte op_1, byte Op2, E_SHIFT_TYPE ShiftType, int Shift){

   S_instruction *p = NULL;

   //if(Shift == 0)
      //ShiftType = LSL;

   if(ShiftType == LSL && Shift < 0){
      ShiftType = LSR;
      Shift = -Shift;
   }
   if((ShiftType == LSR || ShiftType == ASR) && Shift < 0){
      ShiftType = LSL;
      Shift = -Shift;
   }
   if(ShiftType == ROR && Shift < 0)
      Shift = Shift & 31;

   assert(Shift >= 0 && Shift < 32);
   if(code >= 0 && code < 16){
      if (code == CMP || code == TST || code == CMN || code == TEQ) 
         next_set = 1;

      p = InstCreate32((next_cond << 28) | (code << 21) | ((next_set?1:0)<<20) |
         ((op_1==NONE ? r0 : op_1) << 16) | ((Dest==NONE ? r0 : Dest) << 12) | (Shift << 7) | (ShiftType << 5) | (Op2),
         Dest, op_1, Op2, (next_cond != AL)?1:0, next_set?1:0);
   }
   if (Shift == 0){
      if (code == MUL && Dest != op_1){
         p = InstCreate32((next_cond << 28) | ((next_set?1:0)<<20) |
            (Dest << 16) | (Op2 << 8) | 0x90 | (op_1),
            Dest, op_1, Op2, (next_cond != AL)?1:0, next_set?1:0);
      }
      if (code >= QADD && code <= QDSUB){
         p = InstCreate32((next_cond << 28) | 
            (Dest << 12) | (op_1) | (Op2 << 16) | (0x5 << 4) | (1<<24) | ((code-QADD)<<21),
            Dest, op_1, Op2, (next_cond != AL)?1:0, next_set?1:0);
      }
   }

   IPLD(&code, &Dest);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -