0

For research I'm building a basic x86-64 emulator in Node.js, like so:

const registerContainers = {
    GPR: [],
}
for (let i = 0; i < 16; i++) {
    registerContainers.GPR.push(new Uint8Array(8))
}

const registers = {}

class Register {
    constructor(name, container, offset, bytes){
        registers[name] = this
        this.container = container
        this.bytes = bytes
        this.offset = offset
    }
    read(){
        if (this.bytes === this.container.byteLength) return this.container
        else return this.container.subarray(this.offset, this.container.length)
    }
    set(value){
        this.container.set(value, this.offset)
    }
}

new Register('rax', registerContainers.GPR[0], 0, 8) // Register A Extended
new Register('eax', registerContainers.GPR[0], 4, 4)
new Register('ax', registerContainers.GPR[0], 6, 2)
new Register('ah', registerContainers.GPR[0], 6, 1)
new Register('al', registerContainers.GPR[0], 7, 1)

new Register('rbx', registerContainers.GPR[1], 0, 8) // Register B Extended
new Register('ebx', registerContainers.GPR[1], 4, 4)
new Register('bx', registerContainers.GPR[1], 6, 2)
new Register('bh', registerContainers.GPR[1], 6, 1)
new Register('bl', registerContainers.GPR[1], 7, 1)

// ... and so on ...

console.log('registers', registers)
console.log('registerContainers', registerContainers)

registers.eax.set(Uint8Array.from([0x1f, 0x1f, 0x1f, 0x1f]))
console.log('updated GPR', registerContainers.GPR[0])

But the challenge I'm of course faced with is that JavaScript doesn't normally play nice with 64 bit math. My next task is to make an ALU class which performs all the possible math operations between any two registers on x86-64 architecture. I assume that 64 bit math problem will hold true for trying to use them with > 32 bit TypedArrays as operands, right?

In the MDN documentation for bitwise operators it says:

Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.

So I believe doing registerContainers.GPR[0] ^ registerContainers.GPR[1] in the context of the above code would not perform proper math. Correct?

What I tried:

I saw Atomics as being a native module in JS which supports shared but also unshared memory bitwise operations. However I don't see a statement in the docs about any maximum math size requirements.

Rather than trial and error, I thought I should just ask: What's the proper way to handle bitwise operations between >32 bit typed arrays in JavaScript?

J.Todd
  • 707
  • 1
  • 12
  • 34
  • [BigInt](https://stackoverflow.com/q/45908777/1048572), Math.imul, [WebAssembly](https://v8.dev/features/wasm-bigint) – Bergi May 19 '21 at 00:23
  • @Bergi of course BigInt I was aware of but it seems really bad to convert my Uint8Array(s) to BigInt every time I want to do math. I mean look at these conversions, `toString`, gross :( We have our beautiful register Typed Arrays then that ugliness, not to mention the computational efficiency expense, we may as well do the old high and low float two part math if that's the best I can do.. Now WebAssembly, that I didnt look into. Thanks. Edit: Oh god I have to learn a new language to do this and still have to use BigInt D': Let's try This Math.imul.. Nope that's only 32 bit.. – J.Todd May 19 '21 at 00:32
  • There's [`Big[Uint|Int]64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array) so you wouldn't have to go through `toString`. (Not sure if `BigInt` is fast enough for your purposes, but it might do) – Bergi May 19 '21 at 00:37
  • @Bergi Ok that lets me fill a typed array with bigints, that doesnt help me represent an x86 register, rather I need array of 8 individually addressable bytes to work with: Uint8Array. But it's good to know there's no built in solution then, I guess that's my answer. – J.Todd May 19 '21 at 00:44
  • @Bergi But wait... Still it looks to me like [Atomics documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/xor) shows it can work with 64 bit UInt8Array natively... Or am I misunderstanding the docs?? – J.Todd May 19 '21 at 00:46
  • 1
    You can have a single `BigUint64Array` and an `Uint8Array` as views on the same array buffer. – Bergi May 19 '21 at 01:05
  • @Bergi teaching me new JS for 8 years now Bergi – J.Todd May 19 '21 at 08:49

0 Answers0