Skip to content Skip to sidebar Skip to footer

How Can I Properly Add These Two Simulated General Purpose Registers In Javascript?

In JavaScript, for some research I'm trying to simulate the process of following some x86-64 Assembly instructions from scratch. The first step is to properly initiate and be able

Solution 1:

Don't make it so complicated. joinArrayBuffers and padArrayBufferTo64 are very inefficient, notice that buffers and typed arrays have quite some overhead in JS - they are designed to hold large binary data, not individual values, and you should try to create them once and only read/write to them afterwards.

Instead of trying to use BigUint64Array for all your operands, and moving around buffers, I would recommend to use the appropriately sized typed arrays for your smaller registers, and just cast the number to a bigint after accessing the array (if you need bigints for all your ALU operations at all - a 32 bit ALU is probably much more efficient to implement).

const gprBuffer = newArrayBuffer(16 * 8);

classRegister {
    constructor(type, offset) {
        this.container = newtype(gprBuffer, offset, 1);
        this.byteArray = newUint8Array(gprBuffer, offset, type.BYTES_PER_ELEMENT);
    }
}
classNumberRegisterextendsRegister {
    constructor(type, offset) {
        super(type, offset);
        this.mod = 2n ** BigInt(8 * type.BYTES_PER_ELEMENT);
    }
    read() {
        returnBigInt(this.container[0]);
    }
    write(val) {
        this.container[0] = Number(val % this.mod);
    }
}
classBigIntRegisterextendsRegister {
    constructor(type, offset) {
        console.assert(type == BigUint64Array);
        super(type, offset);
    }
    read() {
        returnthis.container[0];
    }
    write(val) {
        this.container[0] = val;
    }
}

functionmakeRegister(base, bitsize, byteoffset) {
    const arrayType = {8: Uint8Array, 16: Uint16Array, 32: Uint32Array, 64: BigUint64Array}[bitsize];
    const registerType = bitsize > 53 ? BigIntRegister : NumberRegisterreturnnewregisterType(arrayType, base * 8 + byteoffset);
}
const registers = {
    rax: makeRegister(0, 64, 0),
    eax: makeRegister(0, 32, 4),
    ax: makeRegister(0, 16, 6),
    ah: makeRegister(0, 8, 6),
    al: makeRegister(0, 8, 7),
    rbx: makeRegister(1, 64, 0),
    ebx: makeRegister(1, 32, 4),
    bx: makeRegister(1, 16, 6),
    bh: makeRegister(1, 8, 6),
    bl: makeRegister(1, 8, 7),
    // …
};
console.log(registers)

However, notice that typed arrays have arbitrary endianness, which you probably don't want for an emulator. Instead, consider using a (single) DataView where you control endianness, and can use different methods to write single values into your gprBuffer at arbitrary offsets.

Post a Comment for "How Can I Properly Add These Two Simulated General Purpose Registers In Javascript?"