2012-03-27 11:02:57 +00:00
|
|
|
bool ARM::condition(uint4 condition) {
|
|
|
|
switch(condition) {
|
|
|
|
case 0: return cpsr().z == 1; //EQ (equal)
|
|
|
|
case 1: return cpsr().z == 0; //NE (not equal)
|
|
|
|
case 2: return cpsr().c == 1; //CS (carry set)
|
|
|
|
case 3: return cpsr().c == 0; //CC (carry clear)
|
|
|
|
case 4: return cpsr().n == 1; //MI (negative)
|
|
|
|
case 5: return cpsr().n == 0; //PL (positive)
|
|
|
|
case 6: return cpsr().v == 1; //VS (overflow)
|
|
|
|
case 7: return cpsr().v == 0; //VC (no overflow)
|
|
|
|
case 8: return cpsr().c == 1 && cpsr().z == 0; //HI (unsigned higher)
|
|
|
|
case 9: return cpsr().c == 0 || cpsr().z == 1; //LS (unsigned lower or same)
|
|
|
|
case 10: return cpsr().n == cpsr().v; //GE (signed greater than or equal)
|
|
|
|
case 11: return cpsr().n != cpsr().v; //LT (signed less than)
|
|
|
|
case 12: return cpsr().z == 0 && cpsr().n == cpsr().v; //GT (signed greater than)
|
|
|
|
case 13: return cpsr().z == 1 || cpsr().n != cpsr().v; //LE (signed less than or equal)
|
|
|
|
case 14: return true; //AL (always)
|
|
|
|
case 15: return false; //NV (never)
|
|
|
|
}
|
|
|
|
}
|
2012-03-29 11:58:10 +00:00
|
|
|
|
|
|
|
uint32 ARM::bit(uint32 result) {
|
|
|
|
if(cpsr().t || instruction() & (1 << 20)) {
|
|
|
|
cpsr().n = result >> 31;
|
|
|
|
cpsr().z = result == 0;
|
|
|
|
cpsr().c = carryout();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::add(uint32 source, uint32 modify, bool carry) {
|
|
|
|
uint32 result = source + modify + carry;
|
|
|
|
if(cpsr().t || instruction() & (1 << 20)) {
|
|
|
|
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
|
|
|
cpsr().n = result >> 31;
|
|
|
|
cpsr().z = result == 0;
|
|
|
|
cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result);
|
|
|
|
cpsr().v = (1u << 31) & (overflow);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::sub(uint32 source, uint32 modify, bool carry) {
|
|
|
|
return add(source, ~modify, carry);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) {
|
|
|
|
//Modified Booth Encoding
|
|
|
|
bool carry = 0;
|
|
|
|
unsigned place = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
step(1);
|
|
|
|
signed factor = (int2)multiplier + carry;
|
|
|
|
|
|
|
|
if(factor == -2) product -= multiplicand << (place + 1);
|
|
|
|
if(factor == -1) product -= multiplicand << (place + 0);
|
|
|
|
if(factor == +1) product += multiplicand << (place + 0);
|
|
|
|
if(factor == +2) product += multiplicand << (place + 1);
|
|
|
|
|
|
|
|
carry = multiplier & 2;
|
|
|
|
place += 2;
|
|
|
|
multiplier >>= 2;
|
|
|
|
} while(multiplier + carry && place < 32);
|
|
|
|
|
|
|
|
if(cpsr().t || instruction() & (1 << 20)) {
|
|
|
|
cpsr().n = product >> 31;
|
|
|
|
cpsr().z = product == 0;
|
|
|
|
cpsr().c = carry;
|
|
|
|
}
|
|
|
|
|
|
|
|
return product;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::lsl(uint32 source, uint32 shift) {
|
|
|
|
while(shift--) {
|
|
|
|
carryout() = source >> 31;
|
|
|
|
source <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cpsr().t) {
|
|
|
|
cpsr().n = source >> 31;
|
|
|
|
cpsr().z = source == 0;
|
|
|
|
cpsr().c = carryout();
|
|
|
|
}
|
|
|
|
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::lsr(uint32 source, uint32 shift) {
|
|
|
|
while(shift--) {
|
|
|
|
carryout() = source & 1;
|
|
|
|
source >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cpsr().t) {
|
|
|
|
cpsr().n = source >> 31;
|
|
|
|
cpsr().z = source == 0;
|
|
|
|
cpsr().c = carryout();
|
|
|
|
}
|
|
|
|
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::asr(uint32 source, uint32 shift) {
|
|
|
|
while(shift--) {
|
|
|
|
carryout() = source & 1;
|
|
|
|
source = (int32)source >> 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cpsr().t) {
|
|
|
|
cpsr().n = source >> 31;
|
|
|
|
cpsr().z = source == 0;
|
|
|
|
cpsr().c = carryout();
|
|
|
|
}
|
|
|
|
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::ror(uint32 source, uint32 shift) {
|
|
|
|
while(shift--) {
|
|
|
|
carryout() = source & 1;
|
|
|
|
source = (source << 31) | (source >> 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cpsr().t) {
|
|
|
|
cpsr().n = source >> 31;
|
|
|
|
cpsr().z = source == 0;
|
|
|
|
cpsr().c = carryout();
|
|
|
|
}
|
|
|
|
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 ARM::rrx(uint32 source) {
|
|
|
|
carryout() = source & 1;
|
|
|
|
source = (cpsr().c << 31) | (source >> 1);
|
|
|
|
}
|