support encoding instructions with indexed and scaled memory offsets

This commit is contained in:
Joel Dice 2007-12-13 18:59:56 -07:00
parent ec8fc80ebe
commit b3918a0d7d
3 changed files with 58 additions and 56 deletions

View File

@ -118,7 +118,6 @@ nextPowerOfTwo(unsigned n)
inline unsigned inline unsigned
log(unsigned n) log(unsigned n)
{ {
if (n < 3) return 1;
unsigned r = 0; unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1; for (unsigned i = 1; i < n; ++r) i <<= 1;
return r; return r;

View File

@ -255,10 +255,7 @@ class MemoryOperand: public MyOperand {
displacement(displacement), displacement(displacement),
index(index), index(index),
scale(scale) scale(scale)
{ { }
assert(static_cast<System*>(0), index == 0); // todo
assert(static_cast<System*>(0), scale == 1); // todo
}
virtual Register asRegister(Context*); virtual Register asRegister(Context*);
@ -863,36 +860,51 @@ rex(Context* c)
} }
void void
encode(Context* c, uint8_t instruction, uint8_t zeroPrefix, encode(Context* c, uint8_t instruction, int a, Register b,
uint8_t bytePrefix, uint8_t wordPrefix, int32_t displacement, int index, unsigned scale)
Register a, Register b, int32_t offset)
{ {
c->code.append(instruction); c->code.append(instruction);
uint8_t prefix; uint8_t width;
if (offset == 0 and b != rbp) { if (displacement == 0 and b != rbp) {
prefix = zeroPrefix; width = 0;
} else if (isInt8(offset)) { } else if (isInt8(displacement)) {
prefix = bytePrefix; width = 0x40;
} else { } else {
prefix = wordPrefix; width = 0x80;
} }
c->code.append(prefix | (a << 3) | b); if (index == -1) {
c->code.append(width | (a << 3) | b);
if (b == rsp) { if (b == rsp) {
c->code.append(0x24); c->code.append(0x24);
}
} else {
assert(c, b != rsp);
c->code.append(width | (a << 3) | 4);
c->code.append((log(scale) << 6) | (index << 3) | b);
} }
if (offset == 0 and b != rbp) { if (displacement == 0 and b != rbp) {
// do nothing // do nothing
} else if (isInt8(offset)) { } else if (isInt8(displacement)) {
c->code.append(offset); c->code.append(displacement);
} else { } else {
c->code.append4(offset); c->code.append4(displacement);
} }
} }
void
encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex)
{
Register r = b->base->asRegister(c);
int index = b->index ? b->index->asRegister(c) : -1;
if (rex) {
::rex(c);
}
encode(c, instruction, a, r, b->displacement, index, b->scale);
}
void void
RegisterOperand::apply(Context* c, Operation operation) RegisterOperand::apply(Context* c, Operation operation)
{ {
@ -1017,15 +1029,11 @@ RegisterOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case cmp: { case cmp: {
Register r = operand->base->asRegister(c); encode(c, 0x3b, value, operand, true);
rex(c);
encode(c, 0x3b, 0, 0x40, 0x80, value, r, operand->displacement);
} break; } break;
case mov: { case mov: {
Register r = operand->base->asRegister(c); encode(c, 0x8b, value, operand, true);
rex(c);
encode(c, 0x8b, 0, 0x40, 0x80, value, r, operand->displacement);
} break; } break;
default: abort(c); default: abort(c);
@ -1038,27 +1046,24 @@ RegisterOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case mov: { case mov: {
Register r = operand->base->asRegister(c);
switch (selection) { switch (selection) {
case S1Selection: case S1Selection:
c->code.append(0x0f); c->code.append(0x0f);
encode(c, 0xbe, 0, 0x40, 0x80, value, r, operand->displacement); encode(c, 0xbe, value, operand, false);
break; break;
case S2Selection: case S2Selection:
c->code.append(0x0f); c->code.append(0x0f);
encode(c, 0xbf, 0, 0x40, 0x80, value, r, operand->displacement); encode(c, 0xbf, value, operand, false);
break; break;
case Z2Selection: case Z2Selection:
c->code.append(0x0f); c->code.append(0x0f);
encode(c, 0xb7, 0, 0x40, 0x80, value, r, operand->displacement); encode(c, 0xb7, value, operand, false);
break; break;
case S4Selection: case S4Selection:
rex(c); encode(c, 0x63, value, operand, true);
encode(c, 0x63, 0, 0x40, 0x80, value, r, operand->displacement);
break; break;
default: abort(c); default: abort(c);
@ -1254,15 +1259,19 @@ MemoryOperand::apply(Context* c, Operation operation)
{ {
switch (operation) { switch (operation) {
case call: case call:
encode(c, 0xff, 0x10, 0x50, 0x90, rax, base->asRegister(c), displacement); encode(c, 0xff, 2, this, false);
break;
case neg:
encode(c, 0xf7, 2, this, true);
break; break;
case pop: case pop:
encode(c, 0x8f, 0, 0x40, 0x80, rax, base->asRegister(c), displacement); encode(c, 0x8f, 0, this, false);
break; break;
case push: case push:
encode(c, 0xff, 0x30, 0x70, 0xb0, rax, base->asRegister(c), displacement); encode(c, 0xff, 6, this, false);
break; break;
default: abort(c); default: abort(c);
@ -1290,21 +1299,19 @@ MemoryOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case add: { case add: {
Register r = base->asRegister(c); encode(c, 0x01, operand->value, this, true);
rex(c);
encode(c, 0x01, 0, 0x40, 0x80, operand->value, r, displacement);
} break; } break;
// case div: {
// // todo
// } break;
case mov: { case mov: {
Register r = base->asRegister(c); encode(c, 0x89, operand->value, this, true);
rex(c);
encode(c, 0x89, 0, 0x40, 0x80, operand->value, r, displacement);
} break; } break;
case sub: { case sub: {
Register r = base->asRegister(c); encode(c, 0x29, operand->value, this, true);
rex(c);
encode(c, 0x29, 0, 0x40, 0x80, operand->value, r, displacement);
} break; } break;
default: abort(c); default: abort(c);
@ -1317,11 +1324,9 @@ MemoryOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case add: { case add: {
Register r = base->asRegister(c);
unsigned i = (isInt8(operand->value) ? 0x83 : 0x81); unsigned i = (isInt8(operand->value) ? 0x83 : 0x81);
rex(c); encode(c, i, 0, this, true);
encode(c, i, 0, 0x40, 0x80, rax, r, displacement);
if (isInt8(operand->value)) { if (isInt8(operand->value)) {
c->code.append(operand->value); c->code.append(operand->value);
} else if (isInt32(operand->value)) { } else if (isInt32(operand->value)) {
@ -1334,9 +1339,7 @@ MemoryOperand::accept(Context* c, Operation operation,
case mov: { case mov: {
assert(c, isInt32(operand->value)); // todo assert(c, isInt32(operand->value)); // todo
Register r = base->asRegister(c); encode(c, 0xc7, 0, this, true);
rex(c);
encode(c, 0xc7, 0, 0x40, 0x80, rax, r, displacement);
c->code.append4(operand->value); c->code.append4(operand->value);
} break; } break;

View File

@ -464,10 +464,10 @@ class Context {
system(system), system(system),
client(client), client(client),
ageMap(&gen1, log(TenureThreshold), 1, 0, false), ageMap(&gen1, max(1, log(TenureThreshold)), 1, 0, false),
gen1(this, &ageMap, 0, 0), gen1(this, &ageMap, 0, 0),
nextAgeMap(&nextGen1, log(TenureThreshold), 1, 0, false), nextAgeMap(&nextGen1, max(1, log(TenureThreshold)), 1, 0, false),
nextGen1(this, &nextAgeMap, 0, 0), nextGen1(this, &nextAgeMap, 0, 0),
pointerMap(&gen2, 1, 1, 0, true), pointerMap(&gen2, 1, 1, 0, true),
@ -589,7 +589,7 @@ inline void
initNextGen1(Context* c, unsigned footprint) initNextGen1(Context* c, unsigned footprint)
{ {
new (&(c->nextAgeMap)) Segment::Map new (&(c->nextAgeMap)) Segment::Map
(&(c->nextGen1), log(TenureThreshold), 1, 0, false); (&(c->nextGen1), max(1, log(TenureThreshold)), 1, 0, false);
unsigned minimum unsigned minimum
= (c->gen1.position() - c->tenureFootprint) + footprint + c->gen1padding; = (c->gen1.position() - c->tenureFootprint) + footprint + c->gen1padding;