Manael Lama Impérial
| Sujet: [JOUR 6] Suite du codage des fonctions Data-Processing etc... Lun 8 Jan - 16:19 | |
| Yo !
On a vu avant les fonctions de data processing, d'autres fonctions annexes ont été implémentés pour factoriser les calculs :
set_ZNCV_CPSR(arm_core p, uint32_t Zbit, uint32_t Nbit, uint32_t Cbit, uint32_t Vbit) : Permet de modifier les Flags du CPSR par les flags donnés en paramètre. ON EST PAS OBLIGE DE CHANGER TOUS LES FLAGS ! Mettez une valeur au pif (je choisis toujours 9 moi.) si vous voulez pas changer le flag. Exemple : set_ZNCV_CPSR(p, 0, 1, 9, 9) permet d'ignorer C et V.
int carry_from(uint32_t op1, uint32_t op2) : Prend 2 opérandes en paramètre et retourne 1 si il y a une retenue sortante (utile pour le C flag), 0 sinon.
borrow_from(uint32_t op1, uint32_t op2) : (A CONFIRMER) Utile pour le C flag.
overflow_from(uint32_t op1, uint32_t op2, uint8_t operation) : Permet de voir si l'opération (avec des opérandes SIGNES) émet un dépassement. Utile pour le V flag.Il retourne 1 si il y a un dépassement, 0 sinon.
void Is_S(arm_core p, uint32_t ins, int Cbit, int Vbit) : Regarde la valeur de S et modifie les flags si celui-ci est à 1. Il n'est important QUE dans les opérateurs qui modifient les flags de façon facultatif (ADD, AND, ORR, MOV etc...). Les opérateurs de test (TST, TEQ, CMP, CMN) ignorent cette fonction car ils modifient obligatoirement les flags.
uint32_t shiftval(arm_core p, uint32_t ins, int *shifter_carry_out) : Permet d'extraire la valeur du shifter_operand, en prenant en compte si c'est un registre ou une valeur immédiate, les rotations etc... Voir la suite.
--------------------------------------------------------------------------------------------------------------------------
Dernière édition par Manael le Mar 9 Jan - 16:10, édité 2 fois | |
|
Elisagh Petit Lama de la Cambrousse
| Sujet: Re: [JOUR 6] Suite du codage des fonctions Data-Processing etc... Lun 8 Jan - 19:05 | |
| - Code:
-
#include "arm_data_processing.h" #include "arm_exception.h" #include "arm_constants.h" #include "arm_branch_other.h" #include "arm_load_store.h" #include "util.h" #include "debug.h"
#define AND 0x00 #define EOR 0x01 #define SUB 0x02 #define RSB 0x03 #define ADD 0x04 #define ADC 0x05 #define SBC 0x06 #define RSC 0x07 #define TST 0x08 #define TEQ 0x09 #define CMP 0x0A #define CMN 0x0B #define ORR 0x0C #define MOV 0x0D #define BIC 0x0E #define MVN 0x0F
int traitement(arm_core p, uint32_t ins); uint8_t overflow_from(uint32_t op1, uint32_t op2, uint8_t operation); uint8_t carry_from(uint32_t op1, uint32_t op2); uint8_t borrow(uint32_t op1, uint32_t op2);
//----------------------------------------------------------------------------------------------------// /* Decoding functions for different classes of instructions */ int arm_data_processing_shift(arm_core p, uint32_t ins) { if((get_bit(ins,4) == 1) && (get_bit(ins,7) == 1)) return arm_load_store(p,ins); else return traitement(p,ins); }
int arm_data_processing_immediate_msr(arm_core p, uint32_t ins) { return UNDEFINED_INSTRUCTION; }
//----------------------------------------------------------------------------------------------------// /*Fonction qui donne la valeur de Shift_op : cas valeur immédiate / cas registre */ uint32_t shiftval(arm_core p, uint32_t ins, int *shifter_carry_out) { uint32_t rotate_imm, shifter_operand, immed_8; uint32_t I; uint32_t shift,shift_imm,Rs; uint32_t Rm,Rm_val; uint32_t Rs_val8, Rs_val5; uint32_t Cflag = 0; uint32_t CPSRflag = 0;
if (shifter_carry_out != NULL) { CPSRflag = arm_read_cpsr(p); // On récupère CPSR Cflag = get_bit(CPSRflag,C); // On récupère le flag C de CPSR }
rotate_imm = get_bits(ins,11,8); immed_8 = get_bits(ins,7,0); I = get_bit(ins,25); Rm = get_bits(ins,3,0); Rm_val = arm_read_usr_register(p,Rm);
//[Valeur immédiate]// if (I == 1){ shifter_operand = ror(immed_8, (rotate_imm * 2)); if (shifter_carry_out != NULL) { if (rotate_imm == 0){ *shifter_carry_out = Cflag; } else { *shifter_carry_out = get_bit(shifter_operand,31); } } return shifter_operand; } //[Registre]// else if (I == 0){ //immediate shifts <=> bit 4 à 0 if(((ins >> 4)& 1)== 0){ shift = get_bits(ins,6,5); shift_imm = get_bits(ins,11,7);
if (shift == 00){ //LSL if (shift_imm == 0){ shifter_operand = Rm; *shifter_carry_out = Cflag; } else if (shift_imm > 0){ shifter_operand = Rm << shift_imm; *shifter_carry_out = get_bit(Rm_val,(32 - shift_imm)); } }
else if (shift == 01){ //LSR if (shift_imm == 0){ shifter_operand = 0; *shifter_carry_out = get_bit(Rm_val,31); } else if (shift_imm > 0){ shifter_operand = Rm_val >> shift_imm; *shifter_carry_out = get_bit(Rm_val,(shift_imm - 1)); } }
else if (shift == 10){ //ASR if (shift_imm == 0){ if (get_bit(Rm_val,31) == 0){ shifter_operand = 0; *shifter_carry_out = get_bit(Rm_val,31); } else if (get_bit(Rm_val,31) == 1){ shifter_operand = 0xFFFFFFFF; *shifter_carry_out = get_bit(Rm_val,31); } } else if (shift_imm > 0){ shifter_operand = asr(Rm_val,(uint8_t)shift_imm); *shifter_carry_out = get_bit(Rm_val,(shift_imm - 1)); } }
else if (shift == 11){ //ROR if (shift_imm == 0){ shifter_operand = (Cflag << 31) | (Rm_val >> 1); *shifter_carry_out = get_bit(Rm_val,0); } else { shifter_operand = ror(Rm_val,shift_imm); *shifter_carry_out = get_bit(Rm_val,(shift_imm - 1)); } }
return shifter_operand; } //register shifts <=> bit 4 à 1 else if (((ins >> 4)& 1)!= 0) { shift = get_bits(ins,7,5); Rs = get_bits(ins,11,8); Rs_val8 = arm_read_usr_register(p,Rs) & 0xFF; // récupérer les 8 premiers bits de Rs Rs_val5 = arm_read_usr_register(p,Rs) & 0x1F; // récupérer les 5 premiers bits de Rs
if (shift == 000){ //LSL if (Rs_val8 == 0){ shifter_operand = Rm_val; *shifter_carry_out = Cflag; } else if (Rs_val8 < 32){ shifter_operand = Rm_val << Rs_val8; *shifter_carry_out = get_bit(Rm_val,(32 - Rs_val8)); } else if (Rs_val8 == 32){ shifter_operand = 0; *shifter_carry_out = get_bit(Rm_val,0); } else if (Rs_val8 > 32){ shifter_operand = 0; *shifter_carry_out = 0; } } else if (shift == 001){ //LSR if (Rs_val8 == 0){ shifter_operand = Rm_val; *shifter_carry_out = Cflag; } else if (Rs_val8 < 32){ shifter_operand = Rm_val >> Rs_val8; *shifter_carry_out = get_bit(Rm_val,(Rs_val8 - 1)); } else if (Rs_val8 == 32){ shifter_operand = 0; *shifter_carry_out = get_bit(Rm_val,31); } else if (Rs_val8 > 32){ shifter_operand = 0; *shifter_carry_out = 0; } } else if (shift == 010){ //ASR if (Rs_val8 == 0){ shifter_operand = Rm_val; *shifter_carry_out = Cflag; } else if (Rs_val8 < 32){ shifter_operand = asr(Rm_val, (uint8_t)Rs_val8); *shifter_carry_out = get_bit(Rm_val,(Rs_val8 - 1)); } else if (Rs_val8 >= 32){ if (get_bit(Rm_val,31) == 0){ shifter_operand = 0; *shifter_carry_out = get_bit(Rm_val,31); } else if(get_bit(Rm_val,31) == 1){ shifter_operand = 0xFFFFFFFF; *shifter_carry_out = get_bit(Rm_val,31); } } } else if (shift == 011){ //ROR if (Rs_val8 == 0){ shifter_operand = Rm_val; *shifter_carry_out = Cflag; } else if (Rs_val5 == 0){ shifter_operand = Rm_val; *shifter_carry_out = get_bit(Rm_val,31); } else if (Rs_val5 > 0){ shifter_operand = ror(Rm_val, Rs_val5); *shifter_carry_out = get_bit(Rm_val,(Rs_val5 - 1)); } } return shifter_operand; } } return 0; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } //----------------------------------------------------------------------------------------------------// /* TRAITEMENT INSTRUCTIONS DE TRAITEMENT DE DONNÉES */ int traitement(arm_core p, uint32_t ins){ int Rn, Rd; uint32_t Rn_val, Rd_val,Shift_op; int S, code_op; int shifter_carry_out; uint32_t CPSRflag = 0;
S = get_bit(ins,20); //I = get_bit(ins,25); code_op = get_bits(ins,24,21);
Rn = get_bits(ins,19,16); //La 1ère opérande (un registre) Rn_val = arm_read_register(p,Rn);
Rd = get_bits(ins,15,12); //Le registre résultat Rd_val = arm_read_register(p,Rd);
Shift_op = shiftval(p, ins, &shifter_carry_out);
CPSRflag = arm_read_cpsr(p); // On récupère CPSR
if (code_op == AND){ Rd_val = Rn_val & Shift_op; if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C CPSRflag = (CPSRflag & ~(1 << C)) | ((shifter_carry_out) << C); // flag V (UNAFFECTED) } }
else if (code_op == EOR){ Rd_val = Rn_val ^ Shift_op; if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | (get_bit(Rd_val,31) << N); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C CPSRflag = (CPSRflag & ~(1 << C)) | ((shifter_carry_out) << C); // flag V (UNAFFECTED) } }
else if (code_op == SUB){ Rd_val = Rn_val - Shift_op; if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (!(borrow(Rn_val, Shift_op))) { arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Rn_val, Shift_op, 0)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == RSB){ //(reverse SUB) Rd_val = Shift_op - Rn_val; if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (!(borrow(Shift_op, Rn_val))){ arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Shift_op,Rn_val,0)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == ADD){ Rd_val = Rn_val + Shift_op; if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (carry_from(Rn_val, Shift_op)){ arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Rn_val, Shift_op, 1)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == ADC){ //(ADD + Carry) Rd_val = Rn_val + Shift_op + get_bit(CPSRflag, C); if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (carry_from(Rn_val, (Shift_op + get_bit(CPSRflag, C)))){ arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Rn_val, (Shift_op + get_bit(CPSRflag, C)), 1)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == SBC){ //(SUB + Carry) Rd_val = Rn_val - Shift_op - !(get_bit(CPSRflag, C)); if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | (get_bit(Rd_val,31) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (!borrow(Rn_val, (Shift_op +(!get_bit(CPSRflag, C))))){ arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Rn_val, (Shift_op +(!get_bit(CPSRflag, C))), 0)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == RSC){ //(Reverse SUB + Carry) Rd_val = Shift_op - Rn_val - !(get_bit(CPSRflag, C)); if ((S == 1) && (Rd == 15)){ if (arm_current_mode_has_spsr(p)){ arm_write_cpsr(p, arm_read_spsr(p)); } else{ //UNPREDICTABLE } } else if (S==1){ // flag N CPSRflag = (CPSRflag & ~(1 << N)) | ((get_bit(Rd_val,31)) << N ); // flag Z if (Rd_val == 0){ arm_write_cpsr(p, set_bit(CPSRflag, Z)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, Z)); } // flag C if (!borrow(Shift_op, (Rn_val +(!get_bit(CPSRflag, C))))){ arm_write_cpsr(p, set_bit(CPSRflag, C)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, C)); } // flag V if (overflow_from (Shift_op, (Rn_val +(!get_bit(CPSRflag, C))), 0)){ arm_write_cpsr(p, set_bit(CPSRflag, V)); } else { arm_write_cpsr(p, clr_bit(CPSRflag, V)); } } }
else if (code_op == TST){ }
else if (code_op == TEQ){ }
else if (code_op == CMP){ }
else if (code_op == CMN){ }
else if (code_op == ORR){ }
else if (code_op == MOV){ }
else if (code_op == BIC){ }
else if (code_op == MVN){ }
else { return UNDEFINED_INSTRUCTION; } return 0; /////////////////////////////////////////////////////////////////; } //----------------------------------------------------------------------------------------------------// /* GESTION DE CARRY */ uint8_t carry_from(uint32_t op1, uint32_t op2){ uint64_t resultat; resultat = op1 + op2; return get_bit(resultat,32); } uint8_t borrow(uint32_t op1, uint32_t op2){ if(op1-op2 < 0) return 1; return 0; } //----------------------------------------------------------------------------------------------------// /*GESTION DE OVERFLOW, operation = 1 si c'est une addition, 0 si c'est une soustraction */ /* cas d'une addition : overflow si les 2 opérandes sont de même signe, mais le resultat de signe différent */ /* cas d'un soustraction : overflow si les 2 opérandes sont de signes différents et le résultat de signe différent de l'opérande de gauche */ uint8_t overflow_from(uint32_t op1, uint32_t op2, uint8_t operation){ uint32_t resultat; if (operation == 1){ resultat = op1 + op2; if (get_bit(op1,N) == get_bit(op2,N)){ if (get_bit(op1,N) != get_bit(resultat,N)){ return 1; } else { return 0; } } else { return 0; } } else { resultat = op1 - op2; if (get_bit(op1,N) != get_bit(op2,N)){ if (get_bit(op1,N) != get_bit(resultat,N)){ return 1; } else { return 0; } } else { return 0; } } }
| |
|