Skip to content
Snippets Groups Projects
Commit 62f97a54 authored by iftach's avatar iftach
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
emulate: emulate.c
gcc -g -Wall -Werror -pedantic emulate.c -o emulate
Spec idea:
struct ProcessorState
Represents a processor; registers and memory.
Let's keep the PC incremented to the actual value it's supposed to have in a real arm processor (current instruction +8).
If the first instruction after a jump is another jump (or if the first instruction of a program is a jump) this might cause a problem (?)
since in an actual execution the offset starts at 0 and moves to +8 after two instructions. decode() should probably account for this.
IMPLEMENTED
main
uses: loadBinary(...), step(...)
void step(struct ProcessorState *processor)
Decodes the next instruction and calls the appropriate method to execute it. Handles the PC's offset.
uses: dataProcessingInstr(...), multiplyInstr(...), dataTransferInstr(...), branchInstr(...)
void dataProcessingInstr(struct ProcessorState *processor, int address)
Executes a data processing instruction
uses: isValidCond(...), barrelShift(...)
void multiplyInstr(struct ProcessorState *processor, int address)
Executes a multiplication instruction
uses: isValidCond(...),
void dataTransferInstr(struct ProcessorState *processor, int address)
Executes a single data transfer instruction
uses: isValidCond(...), barrelShift(...)
void branchInstr(stuct ProcessorState *processor, int address)
uses: isValidCond(...),
struct ProcessorState *loadBinary(char* src)
creates a new processor and loads its memory from a binary file.
Helper functions (used in more than one method):
int32_t getBits(int source, int start, int end)
Reads bits from source in the range [start, end] (inclusive). Returns a uint32_t with the result as its least significant bits.
(e.g. getBits(8, 2, 3) == 2)
IMPLEMENTED
int isSet(int source, int index)
Shorthand for getBits(source, index, index)
IMPLEMENTED
int validCond(int cond, struct ProcessorState *processor)
Returns 1 if the condition code 'cond' is satisfied by the processor's current state, and 0 otherwise.
IMPLEMENTED
int32_t barrelShift(int immediate, int32_t operand, int *carry, struct ProcessorState *processor)
Implements the functionality of the barrel shifter
NOTE: for some reason the I bit is used in opposite ways for data processing instructions vs for data transfer instructions. Arbitrarily, let this method
assume that the data processing instruction interpretation is the right one (so for data transfer instructions just call this method with NOT i).
int32_t *accessMemory(struct ProcessorState *processor, int address)
Gets an address from memory while ensuring it's not out of bounds
(use if you want, you can always do bounds checking manually)
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#define MEMORY_SIZE 65536
// Helpful stuff (things that will probably be used to implement more than one instruction type)
// struct representing a processor:
struct ProcessorState
{
int32_t registers[17];
int32_t memory[MEMORY_SIZE];
};
// Reads bits from source in the range [start, end] (inclusive). Returns a uint32_t with the result as its least significant bits.
// (e.g. getBits(8, 2, 3) == 2)
int32_t getBits(int source, int start, int end)
{
return (source & ((2 << end) - (1 << start))) >> start;
}
// Shorthand for getBits(source, index, index)
int isSet(int source, int index)
{
return (source & (1 << index));
}
// Returns 1 if the condition code 'cond' is satisfied by the processor's current state, and 0 otherwise.
// Any condition code not listed in the spec will cause this to return 0.
int validCond(int32_t cond, struct ProcessorState *processor)
{
int32_t cprs = (*processor).registers[16];
int n = isSet(cprs, 31);
int z = isSet(cprs, 30);
int c = isSet(cprs, 29);
int v = isSet(cprs, 28);
switch (cond)
{
case 0:
return z != 0;
case 1:
return z == 0;
case 10:
return n == z;
case 11:
return n != z;
case 12:
return !z && (n == v);
case 13:
return z || (n != v);
case 14:
return 1;
default:
return 0;
}
}
/* (not finished):
int32_t barrelShift(int immediate, int32_t operand, int *carry, struct ProcessorState *processor)
{
if (immediate)
{
unsigned int rotate = (unsigned int)getBits(operand, 8, 11);
uint32_t imm = (uint32_t)getBits(operand, 0, 7);
return (imm >> (2 * rotate)) | (imm << (32 - 2 * rotate));
}
uint32_t reg = (uint32_t)(*processor).registers[getBits(operand, 8, 11)];
unsigned int shift = getBits(operand, 5, 6);
}
*/
// TODO: applyOperation(int opcode, int32_t operator1, int32_t operator2, int *carry)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment