Skip to content
Snippets Groups Projects
Commit 023792ac authored by iftach's avatar iftach
Browse files

implemented barrelShift (untested)

parent 130d6289
Branches e2e-benchmark
No related tags found
No related merge requests found
......@@ -13,7 +13,7 @@ struct ProcessorState
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.
// Reads bits from source in the range [start, end] (inclusive). Returns an int32_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)
{
......@@ -57,21 +57,84 @@ int validCond(int32_t cond, struct ProcessorState *processor)
}
}
/* (not finished):
/*
Implements the barrel shifter.
immediate: the I bit from the spec. Determines whether to shift by immediate value. Boolean type.
operand: the entire shift instruction (12 bits long). Operand2 on the spec.
carry: the carry-out bit (in case flags need to be updated).
processor: the processor (needed for reading from the registers).
this is completely untested and probably buggy, for all I know this becomes self-aware at runtime so don't trust anything it tells you
also, this doesn't cast return types; i don't think it's a problem but this is C so who knows what it's thinking
*/
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));
//*** shift using immediate value ***//
unsigned int shiftCount = (unsigned int)getBits(operand, 8, 11);
uint32_t operandVal = (uint32_t)getBits(operand, 0, 7);
// shifting an int32_t by 32 bits is undefined behaviour in C, and this if statement prevents it.
if(shiftCount == 0){
return operandVal;
}
// set operandVal to the result after rotation
operandVal = (operandVal >> (2 * shiftCount )) | (operandVal << (32 - 2 * shiftCount));
// set c to the last bit of operandVal (the last bit to be rotated)
(*carry) = isSet(operandVal, 31);
return operandVal;
}
uint32_t reg = (uint32_t)(*processor).registers[getBits(operand, 8, 11)];
unsigned int shift = getBits(operand, 5, 6);
uint32_t operandVal = (uint32_t)(*processor).registers[getBits(operand, 0, 3)];
unsigned int shiftType = getBits(operand, 5, 6);
unsigned int shiftCount;
if (isSet(operand, 4))
{
//*** shift using shift count stored in a register ***//
uint32_t shiftReg = getBits(operand, 8, 11);
// register should not be the PC
assert((shiftReg != 15));
// the spec says that the bottom byte of the register defines the shift amount... but this allows values much bigger than 31 (which is the max shift of all the other shift operation types)
// I'm not sure if it's a mistake or intentional - for now I'm just loading the bottom 5 bytes (2^5 = 32), since shifting an int32_t by more than 32 is undefined for C's bitwise operators.
shiftCount = getBits((*processor).registers[shiftReg], 0, 4);
}
else
{
//*** shift using immediate shift count ***//
shiftCount = getbits(operand, 7, 11);
}
// Exit early if not shifting. This makes some of the upcoming logic simpler.
if (shiftCount == 0)
{
return operandVal;
}
//*** perform the shift ***//
switch (shiftType)
{
case 0:
// logical left shift
(*carry) = isSet(operandVal, 32 - shiftCount);
return operandVal << shiftCount;
case 1:
// logical right shift
// operandVal is a uint32_t, so C shouldn't sign-extend it
(*carry) = isSet(operandVal, shiftCount - 1);
return operandVal >> shiftCount;
case 2:
// arithmetic right shift
(*carry) = isSet(operandVal, shiftCount - 1);
// convert operandVal to a signed type, then shift it
return (int32_t)operandVal >> shiftCount;
case 3:
// rotate right
(*carry) = isSet(operand, shiftCount - 1);
return (operandVal >> shiftCount) | (operandVal << (32 - shiftCount));
}
}
*/
// TODO: applyOperation(int opcode, int32_t operator1, int32_t operator2, int *carry)
// TODO: applyOperation(int opcode, int32_t operator1, int32_t operator2, int *carry)
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