Untitled
unknown
c_cpp
5 months ago
16 kB
3
Indexable
#include <stdbool.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include "armemu.h" // Analysis functions void analysis_init(struct analysis_st *ap) { ap->i_count = 0; ap->dp_count = 0; ap->mem_count = 0; ap->b_count = 0; ap->b_taken = 0; ap->b_not_taken = 0; } // Project04: Print results of dynamic analysis void analysis_print(struct analysis_st *ap) { printf("=== Analysis\n"); printf("I_count = %d\n", ap->i_count); printf("DP_count = %d (%.2f%%)\n", ap->dp_count, ((double)ap->dp_count / (double)ap->i_count) * 100.0); printf("SDT_count = %d (%.2f%%)\n", ap->mem_count, ((double)ap->mem_count / (double)ap->i_count) * 100.0); printf("B_count = %d (%.2f%%)\n", ap->b_count, ((double)ap->b_count / (double)ap->i_count) * 100.0); printf("B_taken = %d (%.2f%%)\n", ap->b_taken, ((double)ap->b_taken / (double)ap->b_count) * 100.0); printf("B_not_taken = %d (%.2f%%)\n", ap->b_not_taken, ((double)ap->b_not_taken / (double)ap->b_count) * 100.0); } // Project04: Print results of dynamic analysis and cache sim void armemu_print(struct arm_state *asp) { if (asp->analyze) { analysis_print(&(asp->analysis)); } if (asp->cache_sim) { cache_print((&asp->cache)); } } void armemu_init(struct arm_state *asp, uint32_t *func, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { int i; // Zero out registers for (i = 0; i < NREGS; i += 1) { asp->regs[i] = 0; } // Zero out the CPSR asp->cpsr = 0; // Zero out the stack for (i = 0; i < STACK_SIZE; i += 1) { asp->stack[i] = 0; } // Initialize the Program Counter asp->regs[PC] = (uint32_t)func; // Initialize the Link Register to a sentinel value asp->regs[LR] = 0; // Initialize Stack Pointer to the logical bottom of the stack asp->regs[SP] = (uint32_t)&asp->stack[STACK_SIZE]; // Initialize the first 4 arguments in emulated r0-r3 asp->regs[0] = a0; asp->regs[1] = a1; asp->regs[2] = a2; asp->regs[3] = a3; // Project04: Initialize dynamic analysis analysis_init(&asp->analysis); // Project04: Initialize cache simulator cache_init(&asp->cache); } bool check_flags(struct arm_state *asp, unsigned int iw) { uint32_t cond = (iw >> 28) & 0b1111; uint32_t z_flag = asp->cpsr >> 30 & 0b1; uint32_t n_flag = asp->cpsr >> 31 & 0b1; uint32_t v_flag = asp->cpsr >> 28 & 0b1; //EQ equal if (cond == 0b0000) { return z_flag == 1; } //NE not equal if (cond == 0b0001) { return z_flag == 0; } //GE greater or equal if (cond == 0b1010) { return (n_flag == v_flag); } //LT less than if (cond == 0b1011) { return (n_flag != v_flag); } //GT greater than if (cond == 0b1100) { return ((z_flag == 0) && (n_flag == v_flag)); } //LE less or equal if (cond == 0b1101) { return ((z_flag == 1) || (n_flag != v_flag)); } //AL always if (cond == 0b1110) { return true; } //not supported, default return false else { return false; } } void armemu_cmp(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rn = (iw >> 16) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; uint32_t result; int result2; uint32_t oper1; if (!i_bit) { oper2 = asp->regs[rm]; } else { oper2 = imm; } oper1 = asp->regs[rn]; result = asp->regs[rn] - oper2; result2 = asp->regs[rn] - oper2; //set overflow if (((oper1 << 31 == 0) && (oper2 << 31 == 0) && (result << 31 == 1)) || ((oper2 << 31 == 0) && (oper1 << 31 == 1) && (result2 > 0))) { asp->cpsr = asp->cpsr | 0b00010000000000000000000000000000; } else { asp->cpsr = asp->cpsr & 0b11101111111111111111111111111111; } //set carry if (oper2 > oper1) { asp->cpsr = asp->cpsr | 0b00100000000000000000000000000000; } else { asp->cpsr = asp->cpsr & 0b11011111111111111111111111111111; } //set zero, clear negative if (result == 0) { asp->cpsr = asp->cpsr | 0b01000000000000000000000000000000; asp->cpsr = asp->cpsr & 0b01111111111111111111111111111111; } //set negative, clear zero if (result2 < 0) { asp->cpsr = asp->cpsr | 0b10000000000000000000000000000000; asp->cpsr = asp->cpsr & 0b10111111111111111111111111111111; } //clear negative and zero if (result2 > 0) { asp->cpsr = asp->cpsr & 0b01111111111111111111111111111111; asp->cpsr = asp->cpsr & 0b10111111111111111111111111111111; } asp->regs[PC] = asp->regs[PC] + 4; } bool armemu_is_cmp(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b1010); } bool armemu_is_bx(uint32_t iw) { uint32_t bxcode; bxcode = (iw >> 4) & 0xFFFFFF; // 0x12fff1 == 0b000100101111111111110001 return bxcode == 0x12fff1; } void armemu_bx(struct arm_state *asp, uint32_t iw) { uint32_t rn = iw & 0b1111; // Project04: increment dynamic analysis asp->analysis.b_count += 1; asp->analysis.b_taken += 1; asp->regs[PC] = asp->regs[rn]; } bool armemu_is_data_transfer(uint32_t iw) { uint32_t check = (iw >> 26) & 0b11; return (check == 0b01); } void armemu_data_transfer(struct arm_state *asp, uint32_t iw) { asp->analysis.mem_count += 1; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rn = (iw >> 16) & 0b1111; uint32_t offset_value; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t l_bit = (iw >> 20) & 0b1; uint32_t b_bit = (iw >> 22) & 0b1; uint32_t rm; uint32_t transfer_value; //check if operand needs to be shifted if (i_bit == 1) { uint32_t shifttype = (iw >> 5) & 0b11; uint32_t rs = (iw >> 8) & 0b1111; uint32_t shiftamount; uint32_t oper2; if ((((iw >> 7) & 0b1) == 0) && (((iw >> 4) & 0b1) == 1)) { shiftamount = asp->regs[rs]; } else { shiftamount = (iw >> 7) & 0b11111; } rm = iw & 0b1111; oper2 = asp->regs[rm]; offset_value = asp->regs[rm]; //lsl, shift left if (shifttype == 0b00) { oper2 = oper2 << shiftamount; } //lsr, logical shift right else if (shifttype == 0b01) { oper2 = oper2 >> shiftamount; } //asr, arithmetic shift right else if (shifttype == 0b10) { if ((oper2 >> 31) == 1) { oper2 = oper2 >> shiftamount; uint32_t bitmask2 = 0b11111111111111111111111111111111; bitmask2 = bitmask2 - ((1 << (shiftamount)) - 1); oper2 = oper2 | bitmask2; } //rotate right?? else { oper2 = oper2 >> shiftamount; } } offset_value = oper2; } //immediate operand else { offset_value = iw & 0b111111111111; } //check if load, then if as a byte if (l_bit == 1) { if ((b_bit == 1)) { transfer_value = *((uint8_t *)(asp->regs[rn] + offset_value)); } else { transfer_value = *((uint32_t *)(asp->regs[rn] + offset_value)); } asp->regs[rd] = transfer_value; } //store else { transfer_value = asp->regs[rd]; if (b_bit == 1) { *(uint8_t *)(asp->regs[rn] + offset_value) = transfer_value; } else { *(uint32_t *)(asp->regs[rn] + offset_value) = transfer_value; } } if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } bool armemu_is_add(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b0100); } bool armemu_is_mul(uint32_t iw) { uint32_t check1 = (iw >> 22) & 0b111111; uint32_t check2 = (iw >> 4) & 0b1111; return (check1 == 0b000000) & (check2 == 0b1001); } bool armemu_is_mov(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b1101); } bool armemu_is_branch(uint32_t iw) { uint32_t check = (iw >> 25) & 0b101; return (check == 0b101); } void armemu_branch(struct arm_state *asp, uint32_t iw) { uint32_t link_bit = (iw >> 24) & 0b1; uint32_t offset = iw & 0b111111111111111111111111; if ((offset >> 23) == 1) { offset = offset | 0b11111111000000000000000000000000; } offset = offset << 2; if (link_bit == 1) { asp->regs[LR] = asp->regs[PC] + 4; } asp->regs[PC] = asp->regs[PC] + (offset + 8); } void armemu_mov(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; uint32_t shiftamount; uint32_t shifttype = (iw >> 5) & 0b11; uint32_t rs = (iw >> 8) & 0b1111; //determine shift amount if shift is required if ((((iw >> 7) & 0b1) == 0) && (((iw >> 4) & 0b1) == 1)) { shiftamount = asp->regs[rs]; } else { shiftamount = (iw >> 7) & 0b11111; } if (!i_bit) { oper2 = asp->regs[rm]; if (shifttype == 0b00) { oper2 = oper2 << shiftamount; } else if (shifttype == 0b01) { oper2 = oper2 >> shiftamount; } else if (shifttype == 0b10) { if ((oper2 >> 31) == 1) { oper2 = oper2 >> shiftamount; uint32_t bitmask2 = 0b11111111111111111111111111111111; bitmask2 = bitmask2 - ((1 << (shiftamount)) - 1); oper2 = oper2 | bitmask2; } else { oper2 = oper2 >> shiftamount; } } } else { oper2 = imm; } asp->regs[rd] = oper2; if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } void armemu_add(struct arm_state *asp, uint32_t iw) { uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rn = (iw >> 16) & 0b1111; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; // Project04: Increment analysis count asp->analysis.dp_count += 1; if (!i_bit) { oper2 = asp->regs[rm]; } else { oper2 = imm; } asp->regs[rd] = asp->regs[rn] + oper2; if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } void armemu_mul(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t a_bit = (iw >> 21) & 0b1; uint32_t rd = (iw >> 16) & 0b1111; uint32_t rn = (iw >> 12) & 0b1111; uint32_t rs = (iw >> 8) & 0b1111; uint32_t rm = iw & 0b1111; asp->regs[rd] = asp->regs[rm] * asp->regs[rs]; if (a_bit) { asp->regs[rd] = asp->regs[rd] + asp->regs[rn]; } if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } void armemu_sub(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rn = (iw >> 16) & 0b1111; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; if (!i_bit) { oper2 = asp->regs[rm]; } else { oper2 = imm; } asp->regs[rd] = asp->regs[rn] - oper2; if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } void armemu_revsub(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rn = (iw >> 16) & 0b1111; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; if (!i_bit) { oper2 = asp->regs[rm]; } else { oper2 = imm; } asp->regs[rd] = oper2 - asp->regs[rn]; if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } bool armemu_is_sub(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b0010); } bool armemu_is_rsub(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b0011); } bool armemu_is_and(uint32_t iw) { uint32_t dp_bits = (iw >> 26) & 0b11; uint32_t opcode = (iw >> 21) & 0b1111; return (dp_bits == 0b00) & (opcode == 0b0000); } void armemu_and(struct arm_state *asp, uint32_t iw) { asp->analysis.dp_count += 1; uint32_t i_bit = (iw >> 25) & 0b1; uint32_t rn = (iw >> 16) & 0b1111; uint32_t rd = (iw >> 12) & 0b1111; uint32_t rm = iw & 0b1111; uint32_t imm = iw & 0b11111111; uint32_t oper2; if (!i_bit) { oper2 = asp->regs[rm]; } else { oper2 = imm; } asp->regs[rd] = asp->regs[rn] & oper2; if (rd != PC) { asp->regs[PC] = asp->regs[PC] + 4; } } void armemu_one(struct arm_state *asp) { /* Project04: get instruction word from instruction cache instead of the PC pointer directly uint32_t iw = *((uint32_t *) asp->regs[PC]); */ uint32_t iw = cache_lookup(&asp->cache, asp->regs[PC]); asp->analysis.i_count += 1; // Order matters: more constrained to least constrained if (armemu_is_bx(iw)) { armemu_bx(asp, iw); } else if (armemu_is_mul(iw)) { armemu_mul(asp, iw); } else if (armemu_is_branch(iw)) { asp->analysis.b_count += 1; if (check_flags(asp, iw)) { asp->analysis.b_taken += 1; armemu_branch(asp, iw); } else { asp->analysis.b_not_taken += 1; asp->regs[PC] = asp->regs[PC] + 4; } } else if (armemu_is_mov(iw)) { armemu_mov(asp, iw); } else if (armemu_is_cmp(iw)) { armemu_cmp(asp, iw); } else if (armemu_is_sub(iw)) { armemu_sub(asp, iw); } else if (armemu_is_rsub(iw)) { armemu_revsub(asp, iw); } else if (armemu_is_and(iw)) { armemu_and(asp, iw); } else if (armemu_is_add(iw)) { armemu_add(asp, iw); } else if (armemu_is_data_transfer(iw)) { armemu_data_transfer(asp, iw); } else { printf("armemu_one() invalid instruction\n"); exit(-1); } } int armemu(struct arm_state *asp) { while (asp->regs[PC] != 0) { armemu_one(asp); } return (int)asp->regs[0]; }
Editor is loading...
Leave a Comment