Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

I want to write an 8086 CPU emulator in javascript, functional style. How would one conceptualise / design an 8086 emulator, or any CPU emulator that has registers and realmode memory access in a functional way?

I can't wrap my head around how an emulator that is pure / mostly side effect free in the core parts, like memory IO and registers, would work.

I have seen this Code Golf: Emulate an Intel 8086 CPU - In it, someone gave an answer in Haskell, so it seems possible.

share|improve this question

closed as too broad by GlenH7, Mason Wheeler, Kilian Foth, MichaelT, Bart van Ingen Schenau Nov 23 '14 at 9:45

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs. If this question can be reworded to fit the rules in the help center, please edit the question.

    
What makes you say Monads are non-functional? –  KChaloux Nov 19 '14 at 14:45
1  
Referring specifically to Haskell's Monads, I've read over many tutorials that they're used for all side-effect code (as well as other things, of course) –  wie Nov 19 '14 at 14:46
    
So, is the real question here “how can monads be functional if they're used for side effects?” or “how do I program a CPU emulator using FP?” (which would be far too broad a question to be answerable here). I'd also like to note that besides some dogmatic Haskellers few think that immutability and side effect free functions are absolutely necessary for functional programming – I and many FP languages such as Lisp or ML treat those as a “nice to have”, not as a necessity. –  amon Nov 19 '14 at 15:11
    
The latter. I can't wrap my head around how to start writing an emulator that is pure / mostly side effect free in the core parts, like memory IO and registers. –  wie Nov 19 '14 at 15:14
    
@wie Purity, the way Haskell deals with it, isn't about never having side effects. It's about tracking and isolating side-effecting code from non-side-effecting code. This is accomplished with the IO Monad in Haskell, but Monads are a much more abstract and general concept that are applied to a lot of other things that are completely unrelated to side-effects (such as modelling Lists). –  KChaloux Nov 19 '14 at 15:33

1 Answer 1

up vote 5 down vote accepted

You have a couple of stateful properties. Those are the registers and memory. And we have a transition between states. This is each CPU cycle. We can therefore model this architecture in a straightforward fashion:

function cycle(state: State) -> State { ... }

Our cycle function will treat the input state as an immutable object, and create a new state to return. This involves copying most data over to the new state. This is not a problem until you start caring about performance.

The CPU cycles until some halting state is reached. This could be expressed as a loop:

while(! state.isHaltingState()) {
    state = cycle(state);
}

which could of course also be expressed as infinite recursion.

Inside our cycle function, we locate, decode, and perform the current instruction. All instructions will at least mutate the instruction pointer. In JavaScript (which is not a pure functional language), the approach would be:

  1. Make a copy of the old registers
  2. Execute the current instruction, which possible mutates the current registers
  3. Treat the registers as immutable and add them to the next state
  4. Return the next state.

Unlike registers, memory (= an array of memory cells, e.g. bytes) will not necessarily be mutated during each instruction. If memory was not touched, we don't have to perform a copy and can simply reference the old memory in the next state. If we do change any cell, we have to create an updated copy for use in the new state. The impact of this can be reduced by dividing memory into pages, and only replacing pages that were actually touched. Effectively, this approach turns the array into an n-ary tree of arrays of fixed depth.

I would model each instruction as a function that calculates a delta from the current state. This way, the code for applying the delta to the current state and returning a new state in an effective manner does not have to be repeated throughout the code. A delta could be a small object such as { registers: { eax: 0x42}, memory: {0x1234: 0x00} }.

share|improve this answer
    
This would work well, and has an additional benefit - on modern (2 GHz+) CPUs, it'd come quite close to emulating the performance of a (5 to 10 MHz) 8086. ;-) –  Brendan Nov 19 '14 at 20:50
    
Actually, since ECMAScript now has Proper Tail Calls (yay!), it would be quite easy to get rid of that ugly imperative while loop. –  Jörg W Mittag Nov 20 '14 at 3:26
    
Seems like my answer is too broad for programmers (though I thought programmers was the place for quite-broad questions!), could you point towards some reading material to stimulate my thinking about the subject? –  wie Nov 23 '14 at 14:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.