mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
fix shift instruction implementations on ARM
Unlike x86, ARM does not implicitly mask the shift value, so we must do so explicitly.
This commit is contained in:
parent
2687333a37
commit
69ffa28e1b
92
src/arm.cpp
92
src/arm.cpp
@ -634,72 +634,118 @@ write4(uint8_t* dst, uint32_t v)
|
||||
memcpy(dst, &v, 4);
|
||||
}
|
||||
|
||||
void
|
||||
andC(Context* con, unsigned size, Assembler::Constant* a,
|
||||
Assembler::Register* b, Assembler::Register* dst);
|
||||
|
||||
void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
if (size == 8) {
|
||||
int tmp1 = newTemp(con), tmp2 = newTemp(con);
|
||||
emit(con, lsl(tmp1, b->high, a->low));
|
||||
emit(con, rsbi(tmp2, a->low, 32));
|
||||
int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con);
|
||||
ResolvedPromise maskPromise(0x3F);
|
||||
Assembler::Constant mask(&maskPromise);
|
||||
Assembler::Register dst(tmp3);
|
||||
andC(con, 4, &mask, a, &dst);
|
||||
emit(con, lsl(tmp1, b->high, tmp3));
|
||||
emit(con, rsbi(tmp2, tmp3, 32));
|
||||
emit(con, orrsh(tmp1, tmp1, b->low, tmp2, LSR));
|
||||
emit(con, SETS(subi(t->high, a->low, 32)));
|
||||
emit(con, SETS(subi(t->high, tmp3, 32)));
|
||||
emit(con, SETCOND(mov(t->high, tmp1), MI));
|
||||
emit(con, SETCOND(lsl(t->high, b->low, t->high), PL));
|
||||
emit(con, lsl(t->low, b->low, a->low));
|
||||
freeTemp(con, tmp1); freeTemp(con, tmp2);
|
||||
emit(con, lsl(t->low, b->low, tmp3));
|
||||
freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3);
|
||||
} else {
|
||||
emit(con, lsl(t->low, b->low, a->low));
|
||||
int tmp = newTemp(con);
|
||||
ResolvedPromise maskPromise(0x1F);
|
||||
Assembler::Constant mask(&maskPromise);
|
||||
Assembler::Register dst(tmp);
|
||||
andC(con, size, &mask, a, &dst);
|
||||
emit(con, lsl(t->low, b->low, tmp));
|
||||
freeTemp(con, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
moveRR(Context* con, unsigned srcSize, Assembler::Register* src,
|
||||
unsigned dstSize, Assembler::Register* dst);
|
||||
|
||||
void shiftLeftC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
assert(con, size == TargetBytesPerWord);
|
||||
emit(con, lsli(t->low, b->low, getValue(a)));
|
||||
if (getValue(a) & 0x1F) {
|
||||
emit(con, lsli(t->low, b->low, getValue(a) & 0x1F));
|
||||
} else {
|
||||
moveRR(con, size, b, size, t);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
if (size == 8) {
|
||||
int tmp1 = newTemp(con), tmp2 = newTemp(con);
|
||||
emit(con, lsr(tmp1, b->low, a->low));
|
||||
emit(con, rsbi(tmp2, a->low, 32));
|
||||
int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con);
|
||||
ResolvedPromise maskPromise(0x3F);
|
||||
Assembler::Constant mask(&maskPromise);
|
||||
Assembler::Register dst(tmp3);
|
||||
andC(con, 4, &mask, a, &dst);
|
||||
emit(con, lsr(tmp1, b->low, tmp3));
|
||||
emit(con, rsbi(tmp2, tmp3, 32));
|
||||
emit(con, orrsh(tmp1, tmp1, b->high, tmp2, LSL));
|
||||
emit(con, SETS(subi(t->low, a->low, 32)));
|
||||
emit(con, SETS(subi(t->low, tmp3, 32)));
|
||||
emit(con, SETCOND(mov(t->low, tmp1), MI));
|
||||
emit(con, SETCOND(asr(t->low, b->high, t->low), PL));
|
||||
emit(con, asr(t->high, b->high, a->low));
|
||||
freeTemp(con, tmp1); freeTemp(con, tmp2);
|
||||
emit(con, asr(t->high, b->high, tmp3));
|
||||
freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3);
|
||||
} else {
|
||||
emit(con, asr(t->low, b->low, a->low));
|
||||
int tmp = newTemp(con);
|
||||
ResolvedPromise maskPromise(0x1F);
|
||||
Assembler::Constant mask(&maskPromise);
|
||||
Assembler::Register dst(tmp);
|
||||
andC(con, size, &mask, a, &dst);
|
||||
emit(con, asr(t->low, b->low, tmp));
|
||||
freeTemp(con, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
assert(con, size == TargetBytesPerWord);
|
||||
emit(con, asri(t->low, b->low, getValue(a)));
|
||||
if (getValue(a) & 0x1F) {
|
||||
emit(con, asri(t->low, b->low, getValue(a) & 0x1F));
|
||||
} else {
|
||||
moveRR(con, size, b, size, t);
|
||||
}
|
||||
}
|
||||
|
||||
void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
emit(con, lsr(t->low, b->low, a->low));
|
||||
int tmpShift = newTemp(con);
|
||||
ResolvedPromise maskPromise(size == 8 ? 0x3F : 0x1F);
|
||||
Assembler::Constant mask(&maskPromise);
|
||||
Assembler::Register dst(tmpShift);
|
||||
andC(con, 4, &mask, a, &dst);
|
||||
emit(con, lsr(t->low, b->low, tmpShift));
|
||||
if (size == 8) {
|
||||
int tmpHi = newTemp(con), tmpLo = newTemp(con);
|
||||
emit(con, SETS(rsbi(tmpHi, a->low, 32)));
|
||||
emit(con, SETS(rsbi(tmpHi, tmpShift, 32)));
|
||||
emit(con, lsl(tmpLo, b->high, tmpHi));
|
||||
emit(con, orr(t->low, t->low, tmpLo));
|
||||
emit(con, addi(tmpHi, a->low, -32));
|
||||
emit(con, addi(tmpHi, tmpShift, -32));
|
||||
emit(con, lsr(tmpLo, b->high, tmpHi));
|
||||
emit(con, orr(t->low, t->low, tmpLo));
|
||||
emit(con, lsr(t->high, b->high, a->low));
|
||||
emit(con, lsr(t->high, b->high, tmpShift));
|
||||
freeTemp(con, tmpHi); freeTemp(con, tmpLo);
|
||||
}
|
||||
freeTemp(con, tmpShift);
|
||||
}
|
||||
|
||||
void unsignedShiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
|
||||
{
|
||||
assert(con, size == TargetBytesPerWord);
|
||||
emit(con, lsri(t->low, b->low, getValue(a)));
|
||||
if (getValue(a) & 0x1F) {
|
||||
emit(con, lsri(t->low, b->low, getValue(a) & 0x1F));
|
||||
} else {
|
||||
moveRR(con, size, b, size, t);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstantPoolEntry: public Promise {
|
||||
@ -909,10 +955,6 @@ jumpR(Context* con, unsigned size UNUSED, Assembler::Register* target)
|
||||
emit(con, bx(target->low));
|
||||
}
|
||||
|
||||
void
|
||||
moveRR(Context* con, unsigned srcSize, Assembler::Register* src,
|
||||
unsigned dstSize, Assembler::Register* dst);
|
||||
|
||||
void
|
||||
swapRR(Context* con, unsigned aSize, Assembler::Register* a,
|
||||
unsigned bSize, Assembler::Register* b)
|
||||
|
@ -1930,14 +1930,14 @@ interpret3(Thread* t, const int base)
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
|
||||
pushInt(t, a << b);
|
||||
pushInt(t, a << (b & 0x1F));
|
||||
} goto loop;
|
||||
|
||||
case ishr: {
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
|
||||
pushInt(t, a >> b);
|
||||
pushInt(t, a >> (b & 0x1F));
|
||||
} goto loop;
|
||||
|
||||
case istore:
|
||||
@ -1976,7 +1976,7 @@ interpret3(Thread* t, const int base)
|
||||
int32_t b = popInt(t);
|
||||
uint32_t a = popInt(t);
|
||||
|
||||
pushInt(t, a >> b);
|
||||
pushInt(t, a >> (b & 0x1F));
|
||||
} goto loop;
|
||||
|
||||
case ixor: {
|
||||
@ -2238,14 +2238,14 @@ interpret3(Thread* t, const int base)
|
||||
int32_t b = popInt(t);
|
||||
int64_t a = popLong(t);
|
||||
|
||||
pushLong(t, a << b);
|
||||
pushLong(t, a << (b & 0x3F));
|
||||
} goto loop;
|
||||
|
||||
case lshr: {
|
||||
int32_t b = popInt(t);
|
||||
int64_t a = popLong(t);
|
||||
|
||||
pushLong(t, a >> b);
|
||||
pushLong(t, a >> (b & 0x3F));
|
||||
} goto loop;
|
||||
|
||||
case lstore:
|
||||
@ -2284,7 +2284,7 @@ interpret3(Thread* t, const int base)
|
||||
int64_t b = popInt(t);
|
||||
uint64_t a = popLong(t);
|
||||
|
||||
pushLong(t, a >> b);
|
||||
pushLong(t, a >> (b & 0x3F));
|
||||
} goto loop;
|
||||
|
||||
case lxor: {
|
||||
|
@ -20,7 +20,7 @@ public class Integers {
|
||||
return m;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws Exception {
|
||||
{ int foo = 1028;
|
||||
foo -= 1023;
|
||||
expect(foo == 5);
|
||||
@ -266,5 +266,49 @@ public class Integers {
|
||||
expect((y + 0x8000) == (-11760768 + 0x8000));
|
||||
|
||||
expect(Math.min(796, 1069) == 796);
|
||||
|
||||
{ int b = 1;
|
||||
expect((b << 32) == 1); }
|
||||
|
||||
{ int b = 0xFFFFFFFF;
|
||||
expect((b >>> -1) == 1); }
|
||||
|
||||
{ int b = 0x10000000;
|
||||
expect((b >> -31) == 0x8000000); }
|
||||
|
||||
{ int b = 1; int s = 32;
|
||||
expect((b << s) == 1); }
|
||||
|
||||
{ int b = 0xFFFFFFFF; int s = -1;
|
||||
expect((b >>> s) == 1); }
|
||||
|
||||
{ int b = 0x10000000; int s = -31;
|
||||
expect((b >> s) == 0x8000000); }
|
||||
|
||||
{ int b = 0xBE;
|
||||
expect((b & 0xFF) == 0xBE); }
|
||||
|
||||
{ int b = 0xBE;
|
||||
expect((b >>> 0) == 0xBE); }
|
||||
|
||||
{ int b = 0xBE;
|
||||
expect((b >> 0) == 0xBE); }
|
||||
|
||||
{ int b = 0xBE;
|
||||
expect((b << 0) == 0xBE); }
|
||||
|
||||
{ int b = 0xBE;
|
||||
expect(((b >>> 0) & 0xFF) == 0xBE); }
|
||||
|
||||
{ java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
|
||||
java.io.DataOutputStream dout = new java.io.DataOutputStream(bout);
|
||||
dout.writeInt(0xCAFEBABE);
|
||||
dout.flush();
|
||||
byte[] array = bout.toByteArray();
|
||||
expect((array[0] & 0xFF) == 0xCA);
|
||||
expect((array[1] & 0xFF) == 0xFE);
|
||||
expect((array[2] & 0xFF) == 0xBA);
|
||||
expect((array[3] & 0xFF) == 0xBE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,6 +337,24 @@ public class Longs {
|
||||
expect(z[0] == 337192406);
|
||||
expect(z[1] == -437261072);
|
||||
}
|
||||
|
||||
{ long b = 1;
|
||||
expect((b << 64) == 1); }
|
||||
|
||||
{ long b = 0xFFFFFFFFFFFFFFFFL;
|
||||
expect((b >>> -1) == 1); }
|
||||
|
||||
{ long b = 0x10000000000L;
|
||||
expect((b >> -63) == 0x8000000000L); }
|
||||
|
||||
{ long b = 1; int s = 64;
|
||||
expect((b << s) == 1); }
|
||||
|
||||
{ long b = 0xFFFFFFFFFFFFFFFFL; int s = -1;
|
||||
expect((b >>> s) == 1); }
|
||||
|
||||
{ long b = 0x10000000000L; int s = -63;
|
||||
expect((b >> s) == 0x8000000000L); }
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user