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
log(unsigned n)
{
if (n < 3) return 1;
unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1;
return r;

View File

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

View File

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