📄 armia_iacxl10_2004_3_16.cpp
字号:
#include "armia_IAcxl10_2004_3_16.h"#include <iostream.h>#include <stdlib.h>#include <stdio.h>#include <assert.h>/************************************************************************************************************* For IA ISS there is a problem: When a instruct need to read a register and the number is 15(PC),the operand must be PC+8, because the ARM is a 3_level fluviation struct;but in IA ISS, PC is update after a instruct being executed completed;So we must keep the PC's vaule while give PC+8 to the instrut which need to read it;*************************************************************************************************************/void ARMISS_stru::init(){ static int done; if(!done) { for( int i=0;i<=14;i++) r_gen[i] = 0; reset(); CPSR.M = 16; pc_changed = false; mas = 2; i = 0; Emulate = true; CPSR.C=CPSR.V=CPSR.Z=CPSR.N=0; done=1; }}void ARMISS_stru::reset(){ r_gen[PC] = 0x0; nrw = false; nirq = true; nfiq = true; abort = false; instruct_reg = (UNL)0; data_abt = false; undef_abt = false; irq_ext = false; fiq_ext = false; prefetch_abt = false; }void ARMISS_stru::fetch(){ static int i=0; nrw = false; (*pmemfun)(r_gen[PC],&data,nrw,2,&abort); instruct_reg = (unsigned long)data; if( abort ) instruct_reg = (bool)false; }//Fetch instructions from memory unit; if abort happend, the instruct is set to be invalid;void ARMISS_stru::decode(){ set_decoder_stru( instruct_reg ); if( instruct_reg.valid ) switch(common_dec.mcoder) { case 0: ARM_t0_decode(); break; case 1: ARM_t1_decode(); break; case 2: ARM_t2_decode(); break; case 3: ARM_t3_decode(); break; case 4: ARM_t4_decode(); break; case 5: ARM_t5_decode(); break; case 6: ARM_t6_decode(); break; case 7: ARM_t7_decode(); break; } else prefetch_abt = true; }//First decode - it determine which type the instruct is;int ARMISS_stru::ARM_t0_decode(){ ARM_type0_stru& tmp = ARM_type0; if( tmp.b4 == 0 ) { if( ((tmp.opcode & 0xc) != 0x8) || (tmp.S==1) ) data_pro_imm_shift_decode(); else miscell_instr_decode(); return 0; } if( (tmp.b4 == 1) && (tmp.b7 == 0) ) { if( ((tmp.opcode & 0xc) != 0x8) || (tmp.S==1) ) data_pro_reg_shift_decode(); else miscell_instr_decode(); return 0; } if( (tmp.b4 == 1) && (tmp.b7 == 1) ) { mul_ext_decode(); return 0; } }//ARM type 0 - including data-process-immediate shift, miscellaneous instructs,data-process-register shift,//mutiples,extra load/stroe instructs which can be found from the ARM's reference manual; void ARMISS_stru::data_pro_imm_shift_decode(){ ARM_type0_stru& tmp = ARM_type0; UNL& r = getreg(tmp.Rd); Addressing_mod1( 2 ); oper = getregd( tmp.Rn ) + ( (tmp.Rn==15? 1:0) * 8);//if operand need PC,then return PC+8; update_flags = ( tmp.S == 1 )? 1:0; des_reg = tmp.Rd; if( executable() ) { switch( tmp.opcode ) { case 0: r = AND(); break; case 1: r = EOR(); break; case 2: r = SUB(); break; case 3: r = RSB(); break; case 4: r = ADD(); break; case 5: r = ADC(); break; case 6: r = SBC(); break; case 7: r = RSC(); break; case 8: TST(); break; case 9: TEQ(); break; case 10: CMP(); break; case 11: CMN(); break; case 12: r = ORR(); break; case 13: r = MOV(); break; case 14: r = BIC(); break; case 15: r = MVN(); break; default: break; } //data process instructs immediate shift; if( tmp.Rd == PC ) pc_changed = true; }}//data-process-immediate shift instructions execute;void ARMISS_stru::data_pro_reg_shift_decode(){ ARM_type0_stru& tmp = ARM_type0; UNL& r = getreg(tmp.Rd); oper = getregd( tmp.Rn ) + ( (tmp.Rn==15? 1:0) * 8); update_flags = ( tmp.S == 1 )? true:false; des_reg = tmp.Rd; Addressing_mod1( 1 ); if( executable() ) { switch( tmp.opcode ) { case 0: r = AND(); break; case 1: r = EOR(); break; case 2: r = SUB(); break; case 3: r = RSB(); break; case 4: r = ADD(); break; case 5: r = ADC(); break; case 6: r = SBC(); break; case 7: r = RSC(); break; case 8: TST(); break; case 9: TEQ(); break; case 10: CMP(); break; case 11: CMN(); break; case 12: r = ORR(); break; case 13: r = MOV(); break; case 14: r = BIC(); break; case 15: r = MVN(); break; default: break; } //data process instructs immediate shift; if( tmp.Rd == PC ) pc_changed = true; }}void ARMISS_stru::miscell_instr_decode(){ ARM_type0_stru& tmp = ARM_type0; UNL& rd = getreg( tmp.Rd ); switch( tmp.mis.b7 ) { case 0 : if( tmp.mis.b21 == 0 ) rd = MRS(); else { oper = getregd( tmp.mis.Rm); MSR(); } break; case 1 : if( tmp.mis.op == 1 ) BX(); break; default: break; } }void ARMISS_stru::mul_ext_decode(){ ARM_type0_stru& tmp = ARM_type0; switch( tmp.mul_ext.b7 ) { case 9 : switch( tmp.mul_ext.b23 + tmp.mul_ext.b24 ) { case 0 : if( tmp.mul_ext.A == 1 ) MLA(); else MUL(); break; case 1 : switch( tmp.mul_ext.U1 + tmp.mul_ext.A ) { case 0 : UMULL(); break; case 1 : UMLAL(); break; case 2 : SMULL(); break; case 3 : SMLAL(); break; } break; case 2 : if( tmp.mul_ext.B == 0 ) SWP(); else SWPB(); break; } break; case 11 : if( tmp.mul_ext.L==1) LDRH(); else STRH(); break; case 15 : if( tmp.mul_ext.S1 == 1 ) LDRSH(); break; } }int ARMISS_stru::ARM_t1_decode(){ ARM_type1_stru& tmp = ARM_type1; if( (tmp.S==1) || ((tmp.opcode & 0xc)!= 0x8) ) { data_pro_imm_decode(); return 0; } if( tmp.b21 == 2 ) { oper = rotate_shift(tmp.imm,tmp.rotate*2); MSR(); return 0; } }void ARMISS_stru::data_pro_imm_decode(){ ARM_type1_stru& tmp = ARM_type1; UNL& rd = getreg( tmp.Rd ); if( executable() ) { barrel_shifter_rotate_imm(tmp.rotate,tmp.imm); oper = getregd( tmp.Rn ); if( tmp.Rn == 15 ) oper = oper + 8; if( tmp.Rd == 15 ) des_reg = 15; update_flags = (tmp.S == 1)? true:false; switch( tmp.opcode ) { case 0: rd = AND(); break; case 1: rd = EOR(); break; case 2: rd = SUB(); break; case 3: rd = RSB(); break; case 4: rd = ADD(); break; case 5: rd = ADC(); break; case 6: rd = SBC(); break; case 7: rd = RSC(); break; case 8: TST(); break; case 9: TEQ(); break; case 10: CMP(); break; case 11: CMN(); break; case 12: rd = ORR(); break; case 13: rd = MOV(); break; case 14: rd = BIC(); break; case 15: rd = MVN(); break; defaults: break; } if( tmp.Rd == PC ) pc_changed = true; } }int ARMISS_stru::ARM_t2_decode(){ ARM_type2_stru& tmp = ARM_type2; UNL op; op = (tmp.B << 1) + tmp.L; switch( op ) { case 0 : if( (tmp.P==0)&&(tmp.W==1) ) STRT(0); else STR(0); break; case 1 : if( (tmp.P==0)&&(tmp.W==1) ) LDRT(0); else LDR(0); break; case 2 : STRB(0); break; case 3 : if( (tmp.P==0)&&(tmp.W==1) ) LDRBT(0); else LDRB(0); break; } return 0;}int ARMISS_stru::ARM_t3_decode(){ ARM_type3_stru& tmp = ARM_type3; UNL op,code; code = common_dec.mcoder; code = (code << 25) + tmp;//用于识别断点指令; if( common_dec.flags != 0xf ) { if( tmp.b4 == 0 ) { op = (tmp.B << 1) + tmp.L; switch( op ) { case 0 : STR(1); break; case 1 : LDR(1); break; case 2 : STRB(1); break; case 3 : LDRB(1); break; } } else if( code == 0x7ffdefe ) Endcond = 143; else undef_abt = true; } else undef_abt = true; return 0;}void ARMISS_stru::ARM_t4_decode(){ ARM_type4_stru& tmp = ARM_type4; bit32_stru bit; if( common_dec.flags != 0xf ) { if( tmp.L == 1 ) { if( tmp.S==0) LDM1(); else { bit = tmp.reg_list; if( bit[15] == 0 ) LDM2(); else LDM3(); } } else { if( tmp.S == 0 ) STM1(); else STM2(); } } else undef_abt = true; }void ARMISS_stru::ARM_t5_decode(){ BL();}void ARMISS_stru::ARM_t6_decode(){ ARM_type6_stru& tmp = ARM_type6; if( tmp.L == 1 ) LDC(); else STC();}void ARMISS_stru::ARM_t7_decode(){ ARM_type7_stru& tmp = ARM_type7; if( common_dec.flags != 0xf ) { if( tmp.b24 == 1 ) SWI(); else if( tmp.b4 == 0 ) CDP(); else { if( tmp.L == 0 ) MCR(); else MRC(); } } else undef_abt = true;}UNL ARMISS_stru::AND(){ long rst; rst = oper & shifter.operand ; if( ( update_flags ) && ( des_reg==PC ) ) { if( getid() != -1 ) CPSR = SPSR[getid()]; } else if ( update_flags ) { CPSR.N = rst >> 31; CPSR.Z = ( rst == 0 )? 1 : 0; CPSR.C = shifter.carry_out; } return ( rst );}UNL ARMISS_stru::EOR(){ long rst; rst = oper ^ shifter.operand ; if( ( update_flags ) && ( des_reg == PC ) ) CPSR = SPSR[getid()]; else if ( update_flags ) { CPSR.N = rst >> 31; CPSR.Z = ( rst == 0 )? 1 : 0; CPSR.C = shifter.carry_out; } return ( rst );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -