xlar54 wrote:
Im working on a simple 8086 emulator for the 65816 (supercpu on the c64/128). right now, the opcodes are just a bunch of statements such as:
jsr fetch_op
cmp #$xx
beq doXX
cmp #$xy
beq doXY
...
...
I dont care for this. For one, im pretty sure im going to have problems with the short branches. and two, i know there is a more elegant way with tables. the problem is, 8086 opcodes can be multi-byte. Was looking for some thoughts around how best to set up such a structure. Thanks for your ideas in advance.
I know nothing of the 8086 ISA but are the multi-byte instructions simply a modification of a base opcode? ie. data to it such as loading a byte or word, or is it more complex than that?
FWIW: In my bytecode interpreter for my '816 BCPL system I have the following code which does the table-lookup thing:
Code:
lda [regPC] ; Load 16-bit value from 24-bit address ( 7)
and #$00FF ; We only want the bottom 8-bits... (+3)
asl ; Double for indexing in 16-bit wide jump table (+2)
tax ; X used to index into jump table (+2)
; Increment the PC
inc regPC+0 ; Low word (+7)
beq incH ; 2 cycles + 1 when branch taken (+2) = 23
jmp (opcodeJumpTable,x) ; (+6) = 29
incH: inc regPC+2 ; Top word (23 + 1 + 7)
jmp (opcodeJumpTable,x) ; (+6) = 37
Numbers in ()'s are the cycles it will take to execute. You may wish to ignore the bits about incrementing the PC here and bear in-mind this has the CPU in 16-bit mode.
My bytecode VM does feature multi-byte instructions, but the following bytes are purely data for that instruction - e.g. load byte, halfword or full word, (1, 2 or 4 extra bytes) or a relative branch (1 extra byte) and so on.
This code is a macro and is in-lined with every single decoded instruction (there are 254 of them). It pushes the size up a little, but saving those cycles rather than jsr/jmp back are very worth it.
-Gordon
_________________
--
Gordon Henderson.
See my
Ruby 6502 and 65816 SBC projects here:
https://projects.drogon.net/ruby/