Jump to content
IGNORED

Bird's nest...


JohnPCAE
 Share

Recommended Posts

Okay, I added a LOOP   RD instruction, where RD can be in the range R0 ... R5. It decrements RD, and if RD is nonzero afterwards, acts as a branch (a displacement is added to R7).

 

So far today's additions are:

 

Unsigned multiplication (sets sign, zero, and overflow flags based on the result)

MUL     ADDR, RD         ; RD = low word of [ADDR] * RD
MUL@    RS, RD           ; RD = low word of [RS] * RD
MULI    DATA, RD         ; RD = low word of DATA * RD

Signed multiplication (sets sign, zero, and overflow flags based on the result)

IMUL    ADDR, RD         ; RD = low word of [ADDR] * RD
IMUL@   RS, RD           ; RD = low word of [RS] * RD
IMULI   DATA, RD         ; RD = low word of DATA * RD

; Vector copy

VMOV@   ADDR, RMD        ; Copies a 3-vector consisting of three DWORDS from [ADDR] to [RMD]
VMOV@@  RMS, RMD         ; Copies a 3-vector consisting of three DWORDS from [RMS] to [RMD]
VMOVI@  DATA, RMD        ; Copies an immediate 3-vector consisting of three DWORDS to [RMD]

; Vector add

VADD@   ADDR, RMD        ; Adds a 3-vector consisting of three DWORDS from [ADDR] to [RMD]
VADD@@  RMS, RMD         ; Adds a 3-vector consisting of three DWORDS from [RMS] to [RMD]
VADDI@  DATA, RMD        ; Adds an immediate 3-vector consisting of three DWORDS to [RMD]

; Vector subtract

VSUB@   ADDR, RMD        ; Subtracts a 3-vector consisting of three DWORDS in [ADDR] from [RMD]
VSUB@@  RMS, RMD         ; Subtracts a 3-vector consisting of three DWORDS in [RMS] from [RMD]
VSUBI@  DATA, RMD        ; Subtracts an immediate 3-vector consisting of three DWORDS from [RMD]

; Loop

LOOP    RD               ; Decements RD. If RD is nonzero afterward, branches (R7 += displacement). RD can be in the range R0 to R5.

; Conditional branches

BA      label            ; Branch if above ((C or Z) = 0)
BNA     label            ; Branch if not above ((C or Z) = 1)

; Add with carry

ADCR    RS, RD           ; RD = RD + RS + C

 

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

Here's what I've added so far. Opcode values are still subject to change. I have no idea if every one of these instructions can run in the time allotted to the Pi Pico, though. That will require testing. Now what would be REALLY awesome would be some enterprising individual making an FPGA-based CPU replacement that supported these extensions.

 

You'll note some simple division instructions here. Since the Pico only has a multiply instruction and not a divide instruction, I can't put in a generic division instruction because there is no way it will complete in time. However, I can use the Pico's multiplication ability to implement some simple division instructions where the divisor is fixed. They're mainly useful for converting binary to decimal, and I threw in the divide-by-three instruction since it might be useful for other things. The SUBGER0 instruction, however, is very useful for a generic division routine written in CP-1600 assembly (see the FastDivide routine in my raycasting demo source for an example of the algorithm).

 

000001 0000 ... ddd          ORx      Src, RD       ; RD |= Src
000001 0000 000 ddd          OR       RD, ADDR
000001 0000 sss ddd          OR@      RS, RD        ; RS = R1..R6
000001 0000 111 ddd          ORI      DATA, RD

000001 0001 ... ddd          ADCx     Src, RD       ; RD += Src + C
000001 0001 000 ddd          ADC      RD, ADDR
000001 0001 sss ddd          ADC@     RS, RD        ; RS = R1..R6
000001 0001 111 ddd          ADCI     DATA, RD

000001 0010 ... ddd          SBBx     Src, RD       ; RD -= (Src + C)
000001 0010 000 ddd          SBB      RD, ADDR
000001 0010 sss ddd          SBB@     RS, RD        ; RS = R1..R6
000001 0010 111 ddd          SBBI     DATA, RD

000001 0011 ... ddd          TSTx     Src, RD       ; Sets the S and Z flags based on RS & Src
000001 0011 000 ddd          TST      RS, ADDR
000001 0011 sss ddd          TST@     RS, RD        ; RS = R1..R6
000001 0011 111 ddd          TSTI     DATA, RS

000001 0100 ... ddd          SLLx     Src, RD       ; RD <<= Src
000001 0100 000 ddd          SLL      RD, ADDR
000001 0100 sss ddd          SLL@     RS, RD        ; RS = R1..R6
000001 0100 111 ddd          SLL      RD, DATA

000001 0101 ... ddd          SLRx     Src, RD       ; RD >>= Src
000001 0101 000 ddd          SLR      RD, ADDR
000001 0101 sss ddd          SLR@     RS, RD        ; RS = R1..R6
000001 0101 111 ddd          SLR      RD, DATA

000001 0110 ... ddd          SARx     Src, RD       ; RD = RD sar Src (arithmetic shift right)
000001 0110 000 ddd          SAR      RD, ADDR
000001 0110 sss ddd          SAR@     RS, RD        ; RS = R1..R6
000001 0110 111 ddd          SAR      RD, DATA

000001 0111 ... ddd          ROLx     Src, RD       ; RD = RD rol Src
000001 0111 000 ddd          ROL      RD, ADDR
000001 0111 sss ddd          ROL@     RS, RD        ; RS = R1..R6
000001 0111 111 ddd          ROL      RD, DATA

000001 1000 ... ddd          RORx     Src, RD       ; RD = RD ror Src
000001 1000 000 ddd          ROR      RD, ADDR
000001 1000 sss ddd          ROR@     RS, RD        ; RS = R1..R6
000001 1000 111 ddd          ROR      RD, DATA

000001 1001 ... ddd          MULx     Src, RD       ; RD *= Src (unsigned multiply)
000001 1001 000 ddd          MUL      ADDR, RD
000001 1001 sss ddd          MUL@     RS, RD        ; RS = R1..R6
000001 1001 111 ddd          MULI     DATA, RD

000001 1010 ... ddd          IMULx    Src, RD       ; RD *= Src (signed multiply)
000001 1010 000 ddd          IMUL     ADDR, RD
000001 1010 sss ddd          IMUL@    RS, RD        ; RS = R1..R6
000001 1010 111 ddd          IMULI    DATA, RD

000001 1011 sss ddd          ORR      RS, RD        ; RD |= RS

000001 1100 sss ddd          ADCR     RS, RD        ; RD += RS + C

000001 1101 sss ddd          SBBR     RS, RD        ; RD -= (RS + C)

000001 1110 ddd ddd          INCLR    RD            ; Increments only the low byte of RD.  If RD was 255, it rolls
                                                    ; over to 0 without affecting the high byte and sets the carry flag.

000001 1110 aaa bbb          TSTR     RA, RB        ; aaa<>bbb.  Sets the S and Z flags based on RA & RB

000001 1111 ddd aaa          SLLR     RD, RA        ; RD <<= RA

000010 0000 ddd aaa          SLRR     RD, RA        ; RD >>= RA

000010 0001 ddd aaa          SARR     RD, RA        ; RD = RD sar RA

000010 0010 ddd aaa          ROLR     RD, RA        ; RD = RD rol RA

000010 0011 ddd aaa          RORR     RD, RA        ; RD = RD ror RA

000010 0100 sss ddd          MULR     RS, RD        ; RD *= RS   (RD gets only the low word of the result)

000010 0101 aaa bbb          MULRW    RA, RB        ; R0:R1 = RA * RB   (R0 = low word, R1 = high word)

000010 0110 sss ddd          IMULR    RS, RD        ; RD *= RS   (RD gets only the low word of the result)

000010 0111 aaa bbb          IMULRW   RA, RB        ; R0:R1 = RA * RB   (R0 = low word, R1 = high word)

000010 1000 ... ddd          VMOVx    Src, RDM      ; sss <> ddd. v3d[RMD] = v3d[Src]
                                                    ; Copies a 3-vector from [Src] to [RMD].
                                                    ; Each vector component is 32 bits.
000010 1000 000 ddd PPPP     VMOV@    ADDR, RD      ; ddd <> 0.   alternate: VPSH    ADDR if ddd = 6
000010 1000 sss ddd          VMOV@@   RMS, RMD      ; sss <> ddd. alternate: VPSH@   RS   if ddd = 6
                                                    ;             alternate: VPUL@   RD   if sss = 6
000010 1000 111 ddd          VMVOI@   DATA, RD      ; ddd < 7.    alternate: VPSH@   DATA if ddd = 6

000010 1000 ddd ddd          LOOP     RD            ; ddd < 6. RD--, if RD is nonzero afterwards, R7 += disp

000010 1000 110 110 PPPP     BA       disp          ; Branch if above (unsigned compare): branch if ((C or Z) = 0)
                                                    ; alternate: BNBE (branch if not below or equal)
                                                    ; Equivalent to x86 JA/JNBE

000010 1000 111 111 PPPP     BNA      disp          ; Branch if not above (unsigned compare): branch if ((C or Z) = 1)
                                                    ; alternate: BBE (branch if below or equal)
                                                    ; Equivalent to x86 JNA/JBE

000010 1001 ... ddd          VADDx    Src, RMD      ; v3d[RMD] += v3d[Src]
                                                    ; Adds a 3-vector from [Src] to [RMD].
                                                    ; Each vector component is 32 bits.
000010 1001 000 ddd          VADD@    ADDR, RMD
000010 1001 sss ddd          VADD@@   RS, RMD
000010 1001 111 ddd          VADDI@   DATA, RMD

000010 1010 ... ddd          VSUBx    Src, RMD      ; v3d[RMD] += v3d[Src]
                                                    ; Subtracts a 3-vector in [Src] from [RMD].
                                                    ; Each vector component is 32 bits.
000010 1010 000 ddd          VSUB@    ADDR, RMD
000010 1010 sss ddd          VSUB@@   R1, RMD
000010 1010 111 ddd          VSUBI@   DATA, RMD

000010 1011 00b baa          UNPR     RB, RA        ; RB = RA >> 8, RA &= 0xFF       aa, bb = 0..3
                                                    ; Unpacks RA into RB:RA

000010 1011 01b baa          PCKR     RS, RD        ; RA = (RA & 0xFF) | (RB >> 8)   aa, bb = 0..3
                                                    ; Packs the low bytes of RB:RA into RA

000010 1011 100 ddd          LOOPE    RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if Z=1, R7 += disp

000010 1011 100 110          BREVR    R0            ; R0 = bit-reversed R0
000010 1011 100 111          BREVR    R1            ; R1 = bit-reversed R1

000010 1011 101 ddd          LOOPNE   RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if Z=0, R7 += disp

000010 1011 101 110          BREVR    R2            ; R2 = bit-reversed R2
000010 1011 101 111          BREVR    R3            ; R3 = bit-reversed R3

000010 1011 110 ddd          LOOPS    RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if S=1, R7 += disp

000010 1011 110 110          BREVR    R4            ; R4 = bit-reversed R4
000010 1011 110 111          BREVR    R5            ; R5 = bit-reversed R5

000010 1011 111 ddd          LOOPNS   RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if S=0, R7 += disp

000010 1011 111 110          COMC                   ; C = !C

000010 1011 111 111          STCP                   ; if R0 contains an odd number of 1 bits, C = 1, else C = 0
                                                    ; (sets carry as R0 parity)

000010 1100 00s sdd          MAXR     RS, RD        ; RD = unsigned maximum of RS and RD.   ss, dd = 0..3

000010 1100 01s sdd          MINR     RS, RD        ; RD = unsigned minimum of RS and RD.   ss, dd = 0..3

000010 1100 10s sdd          IMAXR    RS, RD        ; RD = signed maximum of RS and RD.     ss, dd = 0..3

000010 1100 11s sdd          IMINR    RS, RD        ; RD = signed minimum of RS and RD.     ss, dd = 0..3

000010 1101 000 ddd          SBBR     RD            ; RD -= C

000010 1101 001 ddd          B2AH     RD            ; RD = hexadecimal ASCII representation of the low byte of RD
                                                    ; (e.g. 0x0A --> 3041 "0A")

000010 1101 dd aaaa          SHLD     RD, IMM4      ; RD = high word of RD:R0 shifted left by 0 .. 15.
                                                    ; C = high bit of RD shifted out if amount > 0.  dd=1..3
                                                    ; Equivalent to x86 SHLD using 16-bit operands

000010 1110 000 ddd          AH2B     RD            ; RD = binary value (0..255) of hexadecimal ASCII characters
                                                    ; stored in RD.  Invalid characters in a byte result in that
                                                    ; byte being interpreted as 0 (e.g. 3041 --> 0x0A,
                                                    ; 2F41 --> 0x0A)

000010 1110 001 ddd          DIV5     RD            ; RD /= 5 (unsigned divide)

000010 1110 ss aaaa          SHRD     RS, IMM4      ; R0 = low word of RS:R0 shifted right by 0 .. 15.
                                                    ; C = low bit of R0 shifted out if amount > 0.  ss=1..3
                                                    ; Equivalent to x86 SHRD using 16-bit operands

000010 1111 000 ddd          CL0R     RD            ; RD = number of consecutive 0 bits in RD starting at the MSB

000010 1111 001 ddd          CL1R     RD            ; RD = number of consecutive 1 bits in RD starting at the MSB

000010 1111 010 ddd          CT0R     RD            ; RD = number of consecutive 0 bits in RD starting at the LSB

000010 1111 011 ddd          CT1R     RD            ; RD = number of consecutive 1 bits in RD starting at the LSB

000010 1111 100 ddd          SUBGER0  RD            ; if RD >= R0 (unsigned compare), RD -= R0.
                                                    ; Useful for speeding up division algorithms.

000010 1111 101 ddd          DIV3     RD            ; RD /= 3 (unsigned divide)

000010 1111 110 ddd          DIV100   RD            ; RD /= 100 (unsigned divide)

000010 1111 110 ddd          DUPLR    RD            ; RD = (RD & 0xFF) | (RD << 8)      Duplicates the low byte in RD.

000011 0000 ddd ddd          DECLR    RD            ; Decrements only the low byte of RD.  If RD was 0, it rolls
                                                    ; over to 255 without affecting the high byte and sets the carry flag.

000011 0000 aaa bbb          XCHGR    RA, RB        ; aaa<>bbb. Swaps the contents of RA and RB

000011 0001 mmm ddd PPPP     MVID@    RM, RD, disp  ; RD = [RM + disp]
                                                    ; Does ***not*** change R4 .. R6 if mmm=4..6. Supports SDBD.

000011 0010 mmm ddd PPPP     MVOD@    RM, RD, disp  ; [RM + disp] = RD
                                                    ; Does ***not*** change R4 .. R6 if mmm=4..6. Supports SDBD.

000011 0011 000 ddd          ABSR     RD            ; RD = |RD|

000011 0011 001 ddd          POW2R    RD            ; RD = 1 << RD      If RD > 15, result is 0

 

Edited by JohnPCAE
Link to comment
Share on other sites

Hmm. I'll have to remember to look at his opcodes to see if I can work around them. It might be tricky depending on what I find.

 

On another note, I've had a breakthrough in optimizing my output code for size and I've managed to make some of it drastically smaller while still keeping it efficient enough to get the scanlines out in time. This freed up a lot of RAM and now I have a full 64k words (128k bytes) available for the shared video buffer/character RAM/emulator address space. Now I'm going through the emulator code trying to optimize it for speed.

Link to comment
Share on other sites

Posted (edited)

Happy New Year, everyone!

 

I finished assembling rev. 1.1 of my board tonight. It's working, but it had a couple of minor errors that thankfully were easy to fix. The next board revision will correct them. This is the version that attempts a bidirectional parallel port. I got the nice purple one from a cheapo single-chip PCI parallel port card I picked up on ebay. I'm waiting for a breakout box that will make testing easy, but I did a preliminary test and I can get the Inty to at least read the status pins :)

 

I'm only working on an NTSC version, since I don't have any PAL equipment. I can say, though, that a PAL version would require significant changes to the hardware. For NTSC I can get away with an 8-bit scan line counter, since the Inty only displays 192 scan lines. On PAL, however, an 8-bit counter isn't enough for all of the scan lines so the circuitry would have to change significantly. I also have no idea if the Pi Pico can keep up with PAL timing. It can barely get scan line data out for NTSC, so if PAL requires it to run any faster then it definitely won't work.

 

IMG_2149.thumb.png.59531768ae0327ab0c9302fc751fb6e8.png

 

Edited by JohnPCAE
  • Like 2
Link to comment
Share on other sites

Posted (edited)

Today's software update: now that I have 128k of RAM for the video buffer, it can support 640x191x256 graphics mode. Also, I've added some more screen modes, so this is the new list:

 

#define SCREEN_MODE_40_COLS        0
#define SCREEN_MODE_80_COLS        1

#define SCREEN_MODE_160_96_2       2
#define SCREEN_MODE_160_96_16      3
#define SCREEN_MODE_160_96_256     4
#define SCREEN_MODE_160_96_TRUE16  5
#define SCREEN_MODE_160_96_TRUE32  6

#define SCREEN_MODE_160_191_2      7
#define SCREEN_MODE_160_191_16     8
#define SCREEN_MODE_160_191_256    9
#define SCREEN_MODE_160_191_TRUE16 10
#define SCREEN_MODE_160_191_TRUE32 11

#define SCREEN_MODE_320_96_2       12
#define SCREEN_MODE_320_96_16      13
#define SCREEN_MODE_320_96_256     14
#define SCREEN_MODE_320_96_TRUE16  15
#define SCREEN_MODE_320_96_TRUE32  16

#define SCREEN_MODE_320_191_2      17
#define SCREEN_MODE_320_191_16     18
#define SCREEN_MODE_320_191_256    19
#define SCREEN_MODE_320_191_TRUE16 20

#define SCREEN_MODE_640_96_2       21
#define SCREEN_MODE_640_96_16      22
#define SCREEN_MODE_640_96_256     23
#define SCREEN_MODE_640_96_TRUE16  24

#define SCREEN_MODE_640_191_2      25
#define SCREEN_MODE_640_191_16     26
#define SCREEN_MODE_640_191_256    27

#define SCREEN_MODE_MAX            27

 

There are some caveats to the new true-color modes. There are only a total of 640 NTSC timeslices per scan line, so when the screen width is 320 pixels, only two timeslice values are written per pixel. This will cause some blending of colors, though that would be the case regardless of the bit depth. Likewise, when the screen width is 640 pixels, only one timeslice value is written per pixel, which makes a true-color mode kind of pointless. It's also why 80-column text is so hard to read on a TV. The screen mode is there, regardless.

Edited by JohnPCAE
Link to comment
Share on other sites

Posted (edited)

I'm honestly surprised that this works.

 

For most of the bitmap graphics modes (not the text modes), you have the *option* of enabling sprite-exclusion. When you enable it, what the software does is quite involved and memory intensive:

- allocates a block in the video buffer for a shadow copy of your display data. This will always be at a set location based on your screen mode.

- copies your display raster data to the shadow area, doubling scan line data if necessary (if you're in a 96-scan-line mode, it line-doubles it to 192 scan lines of data)

- Scans through sprite data that is *always* located at 0x1FFE0 in the video buffer and glyph data that is *always* located at 0x1F7E0 in the video buffer

- If the sprite and glyph data tell it that sprite pixels are located at a particular location on the screen, it replaces that pixel data in its shadowed copy with zero (i.e. prevents overlaying anything there).

 

How is this useful? It lets you tell the overlay video to NOT overlay anything where the Inty is displaying its sprites. In the sprite data, you can tell it the location and scaling of a sprite similarly to how you would tell the STIC, and the glyph data supplies the dot patterns.

 

To go into more detail:

 

Starting at 0x1FFE0, there are 8 four-byte records, one record for each sprite. Each record contains the following:

- X position

- Y position

- glyph index

- attributes

 

The X and Y values contain the location of the sprite's upper-left pixel, plus an offset. Adding an offset lets my software support sprites that are partially displayed along the top or left edges. The glyph index is a number from 0-255 and the attributes byte has bit fields that supply visibility, scaling, etc. information. Their meanings correspond one-to-one with the bits that the STIC uses, though the bit positions are necessarily different.

 

The glyph data at 0x1F7E0 is simply raw dot patterns for 256 glyphs. I use this many to support Inty's that have 256 GRAM cards. The idea is that you would shadow what you write to the Inty's GRAM here. Note that it does NOT support sprites that use GROM glyphs, though you can always use some of these 256 available glyphs to represent glyphs that the Inty has in its GROM.

 

And finally, a test screenshot. This is excluding 8 sprites at maximum size with various flip settings. It's something of a stress test.

 

If I tried this with a text mode it would require massive changes so I don't know if it's possible. It's also not lost on me that this functionality could pretty easily be extended to allow you to supply your own extra sprites, as long as it can all run in the allotted time.

SpriteExclusion.png

Edited by JohnPCAE
Link to comment
Share on other sites

*sigh* Text mode in general is proper hard. I've managed to implement sprite exclusion in 40-column text mode, but there are some caveats.

 

If you don't use any 4-color characters, it can exclude up to 5 maximum-size sprites (double-width, height x 8, double-glyphs) if none of them are clipped along the left and right edges of the screen. Going above 5 causes the Pico to run out of time and you get screen corruption. It can, however, exclude more sprites if they're only quad height and if none of them are clipped along the left and right screen edges.

 

4-color characters take longer to convert to pixels, so the more of them you use the less time budget you have for compositing a shadowed screen and excluding sprites. Likewise, if a sprite is clipped along the left or right edges of the screen, the code can't optimize the sprite pixel loop and it takes longer to process.

 

Basically, while you can do some sprite exclusion in text mode, there are limitations. If all of the sprites are small, there should be no problems excluding them all. It comes down to how many screen pixels have to be blanked out. The larger a sprite, the more pixels the code has to process. That's why the test above with all 8 sprites at maximum size was a stress test.

 

Sprite exclusion in 80-column text mode is a total non-starter. It takes way too long to shadow the text as pixels.

Link to comment
Share on other sites

Posted (edited)

Hmm. For some reason I can't add to the thread from Firefox anymore. I had to switch to IE. In Firefox it immediately demands that I drag an attachment to the thread, but even if I do so it won't let me type in any text.

 

Anyway, I've gotten really tired of inconsistent compliation results from gcc. Sometimes it gives me decent performance, and then I'll make a code change and a completely unrelated part of code will suddenly have performance issues. So I've started converting all of my output code to assembler. I'm getting much better at Arm Thumb assembly, as limited as it is.

 

I've run into perhaps the weirdest thing I've ever seen while testing. I'm testing with a StarTech USB video capture device, and for some inexplicable reason it sometimes wants to interpret my overlaid video as grayscale. The video coming from the Inty will still be in color, but the overlaid video will be in black-and-white. Sometimes closing my video capture software and unplugging the USB device fixes it. Sometimes resetting the Inty does it as well, but resetting the Inty can also cause it to go from color to black-and-white. I've verified that it has nothing to do with my software as resetting the Inty doesn't reset the Pico. As long as the Inty has power, the software on the Pico will run uninterrupted. I do trigger an interrupt on the Pico if I detect an MSYNC pulse, but only to reset some internal state variables to a consistent state. It has no effect on how my test patterns are being output. I think what's happening is that the USB capture device is trying to be smart and make high-resolution text legible. I almost wonder if I need a tiny color CRT or something similarly dumb to test with.

 

EDIT: Hah. I knew this would come in handy someday...

IMG_2152.JPG

Edited by JohnPCAE
Link to comment
Share on other sites

Posted (edited)

I have a question for some Inty gurus. I'm looking closely at the bus traffic to try to catch any glitches in my setup, and in the process of doing that I'm seeing something else that's strange. When the Inty starts up, something is accessing my code and (I think) writing to GRAM. Does the EXEC do some sort of GRAM initialization on startup?

 

Also, is anyone else having problems posting from Firefox? The forums aren't letting me type in any text. I have to switch to IE to post. It only started happening within the past week or so.

 

Strange memory accesses.png

Edited by JohnPCAE
Link to comment
Share on other sites

40 minutes ago, JohnPCAE said:

I have a question for some Inty gurus. I'm looking closely at the bus traffic to try to catch any glitches in my setup, and in the process of doing that I'm seeing something else that's strange. When the Inty starts up, something is accessing my code and (I think) writing to GRAM. Does the EXEC do some sort of GRAM initialization on startup?

I believe the EXEC clears all RAM, including GRAM during it's initialization stage.

 

      -dZ.

 

Link to comment
Share on other sites

9 hours ago, JohnPCAE said:

Also, is anyone else having problems posting from Firefox? The forums aren't letting me type in any text. I have to switch to IE to post. It only started happening within the past week or so.

Regarding Firefox, I am posting this using Firefox on Windows 10.

Link to comment
Share on other sites

Posted (edited)

This is what I get when using Firefox on Windows 7. It doesn't give me any place to type text.

This bug started happening somewhere between January 3 and January 5.

 

Cannot_post_from_Firefox.thumb.png.8fac8ac3b2ae2f69096962d238cffc93.png

Edited by JohnPCAE
Link to comment
Share on other sites

50 minutes ago, JohnPCAE said:

This is what I get when using Firefox on Windows 7. It doesn't give me any place to type text.

This bug started happening somewhere between January 3 and January 5.

Try disabling adblocker as a test.

Link to comment
Share on other sites

1 hour ago, JohnPCAE said:

This is what I get when using Firefox on Windows 7. It doesn't give me any place to type text.

This bug started happening somewhere between January 3 and January 5.

 

Cannot_post_from_Firefox.thumb.png.8fac8ac3b2ae2f69096962d238cffc93.png

I get that with older versions of Firefox (the ones my ancient Mac could support).  I think it's a JavaScript/Stylesheet compatibility issue.

 

I switched to Firefox Legacy and Interweb (special builds of later Firefox code for older machines) and the problem is sorted.

 

On an old 2009 Mac Pro running Mac OS X 10.5.8 (Mountain Lion), I use Interweb for AtariAge and it works a treat.
 

 dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

Posted (edited)

I posted about the problem on the Firefox forums, and they pointed me to a solution. I had to go into my Firefox settings and clear the cache. All fixed now!

 

In other news, I've been going on a major optimization spree in my Pico code, rewriting all kinds of stuff in assembly. It can now *barely* exclude a single sprite if every character on the screen is a four-color narrow-pixel character (meaning: characters that are 8 pixels across and each pixel is represented by 2 bits). Those are very CPU-intensive to composite into a separate 320x192x256 buffer and it's a real stress test. By contrast, if you're using only standard two-color characters, it can exclude four maximum-size sprites (double-width, quadruple height, two glyphs per sprite). And if you're using any of the bitmap graphics screen modes instead, it can exclude all eight Intellivision sprites at maximum size.

 

To recap, sprite exclusion allows you to tell it to not render anything where an Intellivision sprite would be. It's an optional feature that you don't have to enable. When enabled, instead of directly displaying whatever is in your video buffer, it reserves a portion of it for a full 320x191x256 frame buffer and first renders to that. It then blanks out any pixels that an Intellivision sprite would occupy before displaying it on the screen. It reserves a portion of its video buffer where you would place sprite glyphs and tell it where the sprites are. The effect is that you could have the extra video appear *under* Intellivision sprites instead of mixed with them. Rendering character-mode screen modes is much more CPU intensive than pure graphics modes (which involves a simple block copy of memory), so there are restrictions on how many sprites you can exclude because of the time involved. You also cannot exclude any sprites if you're using 80-column mode, at least for now. I haven't attempted to try it and I doubt there's enough CPU horsepower available to pull it off (not to mention that I'm running hard into the RAM limit with all of the code that's already written).

 

When using sprite exclusion with bitmap graphics modes, I should explain one more caveat.

 

Intellivision sprites have a Y position resolution of 192 pixels, in other words they can be placed on any scan line. This means that whatever frame buffer my code uses when excluding sprites has to have 192 scan lines. So if you're using a "thick scanline" mode with 96 pixels, the code will always double it up to 191 scan lines when excluding sprites. This places limitations on which graphics modes allow sprite exclusion, since the total video memory is 128k bytes. Any graphics modes that need more than 128k for the normal and "shadowed" frame buffer cannot have sprite exclusion since there isn't enough room for a separate frame buffer. This applies to a handful of screen modes:

 

160x96x32bit

160x191x32bit

320x96x16bit

320x96x32bit

320x191x16bit

640x96x256

640x96x16bit

640x191x256

 

Edited by JohnPCAE
Link to comment
Share on other sites

Posted (edited)

Well, aside from testing the parallel port and any bugfixes, the software is basically complete. All of the existing screen modes are working and I'm right up at the RAM limit. I did learn something important last night: while the Pi Pico can run at up to 133MHz, it's default speed is only 125MHz. I set it for 133 and adjusted my bus timing code to match, so now it has a little extra speed margin. Tomorrow I should be receiving a dedicated RS-25 port testing breakout box so I can test the parallel port in earnest.

 

This is the final list of available screen modes.   Entries with an asterisk mean that sprite exclusion is unavailable due to insufficient RAM for the required shadow framebuffer. It's worth noting that you *can* do sprite exclusion for 320x191x256, the closest equivalent to VGA 320x200x256 mode. Since sprite exclusion reserves a large portion of the video buffer for a shadow framebuffer, it does restrict memory available for other things like RAM glyphs and emulation code.

 

#define SCREEN_MODE_40_COLS        0
#define SCREEN_MODE_80_COLS        1    *

#define SCREEN_MODE_160_96_2       2
#define SCREEN_MODE_160_96_4       3
#define SCREEN_MODE_160_96_16      4
#define SCREEN_MODE_160_96_256     5
#define SCREEN_MODE_160_96_TRUE16  6
#define SCREEN_MODE_160_96_TRUE32  7    *

#define SCREEN_MODE_160_191_2      8
#define SCREEN_MODE_160_191_4      9
#define SCREEN_MODE_160_191_16     10
#define SCREEN_MODE_160_191_256    11
#define SCREEN_MODE_160_191_TRUE16 12
#define SCREEN_MODE_160_191_TRUE32 13   *

#define SCREEN_MODE_320_96_2       14
#define SCREEN_MODE_320_96_4       15
#define SCREEN_MODE_320_96_16      16
#define SCREEN_MODE_320_96_256     17
#define SCREEN_MODE_320_96_TRUE16  18   *
#define SCREEN_MODE_320_96_TRUE32  19   *

#define SCREEN_MODE_320_191_2      20
#define SCREEN_MODE_320_191_4      21
#define SCREEN_MODE_320_191_16     22
#define SCREEN_MODE_320_191_256    23
#define SCREEN_MODE_320_191_TRUE16 24   *

#define SCREEN_MODE_640_96_2       25
#define SCREEN_MODE_640_96_4       26
#define SCREEN_MODE_640_96_16      27
#define SCREEN_MODE_640_96_256     28   *
#define SCREEN_MODE_640_96_TRUE16  29   *

#define SCREEN_MODE_640_191_2      30
#define SCREEN_MODE_640_191_4      31
#define SCREEN_MODE_640_191_16     32
#define SCREEN_MODE_640_191_256    33   *

 

Edited by JohnPCAE
Link to comment
Share on other sites

Posted (edited)
On 12/31/2021 at 12:38 AM, Lathe26 said:

You should coordinate your instructions with Joe Zbiciak since the LTO has its own set of extended opcodes.

I'm going through the Locutus documentation. The issue I see is that I have more opcodes than will fit into his reserved opcode areas. He blocks out 000001xxxxxxxxxx and 010000xxxxxxxxxx as reserved areas, but my opcodes won't fit in to just those areas. I would need a little more opcode space to fit them all. Also, the paradigm is completely different: the Locutus opcodes are designed to coexist with an existing CP-1600, whereas mine assume a CPU replacement that is backward compatible.

 

It looks like all of the Locutus opcodes work around the 1001111xxx MVOI opcode. I might be able to move mine a little so that they don't use those bits. I'll see what I can do.

 

EDIT: Okay. I've moved my instructions so that none of them occupy where MVOI/Locutus/CP-1600X would be.

 

PV_DISPATCH dispatch[] =
  {
    DO_HLT,  DO_SDBD, DO_EIS,  DO_DIS,  DO_J,    DO_TCI,  DO_CLRC, DO_SETC,
    DO_INCR, DO_INCR, DO_INCR, DO_INCR, DO_INCR, DO_INCR, DO_INCR, DO_INCR,
    DO_DECR, DO_DECR, DO_DECR, DO_DECR, DO_DECR, DO_DECR, DO_DECR, DO_DECR,
    DO_COMR, DO_COMR, DO_COMR, DO_COMR, DO_COMR, DO_COMR, DO_COMR, DO_COMR,
    DO_NEGR, DO_NEGR, DO_NEGR, DO_NEGR, DO_NEGR, DO_NEGR, DO_NEGR, DO_NEGR,
    DO_ADCR, DO_ADCR, DO_ADCR, DO_ADCR, DO_ADCR, DO_ADCR, DO_ADCR, DO_ADCR,
    DO_GSWD, DO_GSWD, DO_GSWD, DO_GSWD, DO_NOP,  DO_NOP,  DO_SIN,  DO_SIN,
    DO_RSWD, DO_RSWD, DO_RSWD, DO_RSWD, DO_RSWD, DO_RSWD, DO_RSWD, DO_RSWD,

    DO_SWAP, DO_SWAP, DO_SWAP, DO_SWAP, DO_SWAP2, DO_SWAP2, DO_SWAP2, DO_SWAP2,
    DO_SLL,  DO_SLL,  DO_SLL,  DO_SLL,  DO_SLL2,  DO_SLL2,  DO_SLL2,  DO_SLL2,
    DO_RLC,  DO_RLC,  DO_RLC,  DO_RLC,  DO_RLC2,  DO_RLC2,  DO_RLC2,  DO_RLC2,
    DO_SLLC, DO_SLLC, DO_SLLC, DO_SLLC, DO_SLLC2, DO_SLLC2, DO_SLLC2, DO_SLLC2,
    DO_SLR,  DO_SLR,  DO_SLR,  DO_SLR,  DO_SLR2,  DO_SLR2,  DO_SLR2,  DO_SLR2,
    DO_SAR,  DO_SAR,  DO_SAR,  DO_SAR,  DO_SAR2,  DO_SAR2,  DO_SAR2,  DO_SAR2,
    DO_RRC,  DO_RRC,  DO_RRC,  DO_RRC,  DO_RRC2,  DO_RRC2,  DO_RRC2,  DO_RRC2,
    DO_SARC, DO_SARC, DO_SARC, DO_SARC, DO_SARC2, DO_SARC2, DO_SARC2, DO_SARC2,

    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,
    DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR, DO_MOVR,

    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,
    DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR, DO_ADDR,

    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,
    DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR, DO_SUBR,

    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,
    DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR, DO_CMPR,

    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,
    DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR, DO_ANDR,

    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,
    DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR, DO_XORR,

    DO_BADD,     DO_BADDC,    DO_BADDO,    DO_BADDNS,   DO_BADDZ,    DO_BADDLT,   DO_BADDLE,   DO_BADDUSC,
    DO_BSKIP,    DO_BADDNC,   DO_BADDNO,   DO_BADDS,    DO_BADDNZ,   DO_BADDGE,   DO_BADDGT,   DO_BADDESC,
    DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,
    DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,  DO_BADDEXT,
    DO_BSUB,     DO_BSUBC,    DO_BSUBO,    DO_BSUBNS,   DO_BSUBZ,    DO_BSUBLT,   DO_BSUBLE,   DO_BSUBUSC,
    DO_BSKIP,    DO_BSUBNC,   DO_BSUBNO,   DO_BSUBS,    DO_BSUBNZ,   DO_BSUBGE,   DO_BSUBGT,   DO_BSUBESC,
    DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,
    DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,  DO_BSUBEXT,

    DO_MVO,      DO_MVO,      DO_MVO,      DO_MVO,      DO_MVO,      DO_MVO,      DO_MVO,      DO_MVO,
    DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,
    DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,
    DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,  DO_MVOA123,
    DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567,
    DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567,
    DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567,
    DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567, DO_MVOA4567,

    DO_MVI,      DO_MVI,      DO_MVI,      DO_MVI,      DO_MVI,      DO_MVI,      DO_MVI,      DO_MVI7,
    DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,
    DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,
    DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,  DO_MVIA123,
    DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,
    DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,
    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,    DO_MVIA6,
    DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,  DO_MVIA457,

    DO_ADD,      DO_ADD,      DO_ADD,      DO_ADD,      DO_ADD,      DO_ADD,      DO_ADD,      DO_ADD,
    DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,
    DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,
    DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,  DO_ADDA123,
    DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,
    DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,
    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,    DO_ADDA6,
    DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,  DO_ADDA457,

    DO_SUB,      DO_SUB,      DO_SUB,      DO_SUB,      DO_SUB,      DO_SUB,      DO_SUB,      DO_SUB,
    DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,
    DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,
    DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,  DO_SUBA123,
    DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,
    DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,
    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,    DO_SUBA6,
    DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,  DO_SUBA457,

    DO_CMP,      DO_CMP,      DO_CMP,      DO_CMP,      DO_CMP,      DO_CMP,      DO_CMP,      DO_CMP,
    DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,
    DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,
    DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,  DO_CMPA123,
    DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,
    DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,
    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,    DO_CMPA6,
    DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,  DO_CMPA457,

    DO_AND,      DO_AND,      DO_AND,      DO_AND,      DO_AND,      DO_AND,      DO_AND,      DO_AND,
    DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,
    DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,
    DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,  DO_ANDA123,
    DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,
    DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,
    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,    DO_ANDA6,
    DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,  DO_ANDA457,

    DO_XOR,      DO_XOR,      DO_XOR,      DO_XOR,      DO_XOR,      DO_XOR,      DO_XOR,      DO_XOR,
    DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,
    DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,
    DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,  DO_XORA123,
    DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,
    DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,
    DO_XORA6,    DO_XORA6,    DO_XORA6,    DO_XORA6,    DO_XORA6,    DO_XORA6,    DO_XORA6,    DO_XORA6,
    DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,  DO_XORA457,

    // Extended opcodes start here

    // ORx                    ; RD |= Src
    // 000001 0000 sss ddd

    DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,    // OR@   R0, RD
    DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,    // OR@   R1, RD
    DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,    // OR@   R2, RD
    DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,   DO_ORA123,    // OR@   R3, RD
    DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,    // OR@   R4, RD
    DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,    // OR@   R5, RD
    DO_ORA6,     DO_ORA6,     DO_ORA6,     DO_ORA6,     DO_ORA6,     DO_ORA6,     DO_ORA6,     DO_ORA6,      // OR@   R6, RD
    DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,   DO_ORA457,    // ORI   DATA, RD

    // ADCx                   ; RD += Src + C
    // 000001 0001 sss ddd

    DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,   // ADC@  R0, RD
    DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,   // ADC@  R1, RD
    DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,   // ADC@  R2, RD
    DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,  DO_ADCA123,   // ADC@  R3, RD
    DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,   // ADC@  R4, RD
    DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,   // ADC@  R5, RD
    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,    DO_ADCA6,     // ADC@  R6, RD
    DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,  DO_ADCA457,   // ADCI  DATA, RD

    // SBBx                   ; RD -= (Src + C)
    // 000001 0010 sss ddd

    DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,   // SBB@  R0, RD
    DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,   // SBB@  R1, RD
    DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,   // SBB@  R2, RD
    DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,  DO_SBBA123,   // SBB@  R3, RD
    DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,   // SBB@  R4, RD
    DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,   // SBB@  R5, RD
    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,    DO_SBBA6,     // SBB@  R6, RD
    DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,  DO_SBBA457,   // SBBI  DATA, RD

    // TSTx                   ; Sets the S and Z flags based on RS & Src
    // 000001 0011 sss ddd

    DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,   // TST@   R0, RS
    DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,   // TST@   R1, RS
    DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,   // TST@   R2, RS
    DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,  DO_TSTA123,   // TST@   R3, RS
    DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,   // TST@   R4, RS
    DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,   // TST@   R5, RS
    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,    DO_TSTA6,     // TST@   R6, RS
    DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,  DO_TSTA457,   // TSTI   DATA, RS

    // SLLx                   ; RD <<= Src
    // 000001 0100 sss ddd

    DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,   // SLL@   R0, RD
    DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,   // SLL@   R1, RD
    DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,   // SLL@   R2, RD
    DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,  DO_SLLA123,   // SLL@   R3, RD
    DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,   // SLL@   R4, RD
    DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,   // SLL@   R5, RD
    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,    DO_SLLA6,     // SLL@   R6, RD
    DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,  DO_SLLA457,   // SLL    RD, DATA

    // SLRx                   ; RD >>= Src
    // 000001 0101 sss ddd

    DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,   // SLR@   R0, RD
    DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,   // SLR@   R1, RD
    DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,   // SLR@   R2, RD
    DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,  DO_SLRA123,   // SLR@   R3, RD
    DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,   // SLR@   R4, RD
    DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,   // SLR@   R5, RD
    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,    DO_SLRA6,     // SLR@   R6, RD
    DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,  DO_SLRA457,   // SLR    RD, DATA

    // SARx                   ; RD = RD sar Src (arithmetic shift right)
    // 000001 0110 sss ddd

    DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,   // SAR@   R0, RD
    DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,   // SAR@   R1, RD
    DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,   // SAR@   R2, RD
    DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,  DO_SARA123,   // SAR@   R3, RD
    DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,   // SAR@   R4, RD
    DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,   // SAR@   R5, RD
    DO_SARA6,    DO_SARA6,    DO_SARA6,    DO_SARA6,    DO_SARA6,    DO_SARA6,    DO_SARA6,    DO_SARA6,     // SAR@   R6, RD
    DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,  DO_SARA457,   // SAR    RD, DATA

    // ROLx                   ; RD = RD rol Src
    // 000001 0111 sss ddd

    DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,   // ROL@   R0, RD
    DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,   // ROL@   R1, RD
    DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,   // ROL@   R2, RD
    DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,  DO_ROLA123,   // ROL@   R3, RD
    DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,   // ROL@   R4, RD
    DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,   // ROL@   R5, RD
    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,    DO_ROLA6,     // ROL@   R6, RD
    DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,  DO_ROLA457,   // ROL    RD, DATA

    // RORx                   ; RD = RD ror Src
    // 000001 1000 sss ddd

    DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,   // ROR@   R0, RD
    DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,   // ROR@   R1, RD
    DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,   // ROR@   R2, RD
    DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,  DO_RORA123,   // ROR@   R3, RD
    DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,   // ROR@   R4, RD
    DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,   // ROR@   R5, RD
    DO_RORA6,    DO_RORA6,    DO_RORA6,    DO_RORA6,    DO_RORA6,    DO_RORA6,    DO_RORA6,    DO_RORA6,     // ROR@   R6, RD
    DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,  DO_RORA457,   // ROR    RD, DATA

    // Reserved for Locutus
    // 000001 1001 ... ...

    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,


    // MULx                   ; RD *= Src (unsigned multiply)
    // 000001 1010 sss ddd

    DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,   // MUL@   R0, RD
    DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,   // MUL@   R1, RD
    DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,   // MUL@   R2, RD
    DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,  DO_MULA123,   // MUL@   R3, RD
    DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,   // MUL@   R4, RD
    DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,   // MUL@   R5, RD
    DO_MULA6,    DO_MULA6,    DO_MULA6,    DO_MULA6,    DO_MULA6,    DO_MULA6,    DO_MULA6,    DO_MULA6,     // MUL@   R6, RD
    DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,  DO_MULA457,   // MULI   DATA, RD

    // IMULx                  ; RD *= Src (signed multiply)
    // 000001 1011 sss ddd

    DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123,  // IMUL@  R0, RD
    DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123,  // IMUL@  R1, RD
    DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123,  // IMUL@  R2, RD
    DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123, DO_IMULA123,  // IMUL@  R3, RD
    DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457,  // IMUL@  R4, RD
    DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457,  // IMUL@  R5, RD
    DO_IMULA6,   DO_IMULA6,   DO_IMULA6,   DO_IMULA6,   DO_IMULA6,   DO_IMULA6,   DO_IMULA6,   DO_IMULA6,    // IMUL@  R6, RD
    DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457, DO_IMULA457,  // IMULI  DATA, RD

    // ORR      RS, RD        ; RD |= RS
    // 000001 1100 sss ddd

    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,
    DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,      DO_ORR,

    // ADCR     RS, RD        ; RD += RS + C
    // 000001 1101 sss ddd

    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,
    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,    DO_ADCR2,

    // SBBR     RS, RD        ; RD -= (RS + C)
    // 000001 1110 sss ddd

    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,
    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,    DO_SBBR2,

    // INCLR    RD            ; Increments only the low byte of RD.  If RD was 255, it rolls over to 0 without affecting the high byte but sets the carry flag.
    // TSTR     RA, RB        ; RA <> RB. Sets the S and Z flags based on RA & RB
    // 000001 1111 ddd ddd    INCLR
    // 000001 1111 aaa bbb    TSTR

    DO_INCLR,    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_INCLR,    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_INCLR,    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_INCLR,    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_INCLR,    DO_TSTR,     DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_INCLR,    DO_TSTR,     DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_INCLR,    DO_TSTR,
    DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_TSTR,     DO_INCLR,

    // SLLR     RD, RA        ; RD <<= RA
    // 000010 0000 ddd aaa

    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,
    DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,     DO_SLLR,

    // SLRR     RD, RA        ; RD >>= RA
    // 000010 0001 ddd aaa

    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,
    DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,     DO_SLRR,

    // SARR     RD, RA        ; RD = RD sar RA
    // 000010 0010 ddd aaa

    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,
    DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,     DO_SARR,

    // ROLR     RD, RA        ; RD = RD rol RA
    // 000010 0011 ddd aaa

    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,
    DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,     DO_ROLR,

    // RORR     RD, RA        ; RD = RD ror RA
    // 000010 0100 ddd aaa

    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,
    DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,     DO_RORR,

    // MULR     RS, RD        ; RD *= RS   (RD gets only the low word of the result)
    // 000010 0101 sss ddd

    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,
    DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,     DO_MULR,

    // MULRW    RA, RB        ; R0:R1 = RA * RB   (R0 = low word, R1 = high word)
    // 000010 0110 aaa bbb

    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,
    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,    DO_MULRW,

    // IMULR    RS, RD        ; RD *= RS   (RD gets only the low word of the result)
    // 000010 0111 sss ddd

    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,
    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,    DO_IMULR,

    // IMULRW   RA, RB        ; R0:R1 = RA * RB   (R0 = low word, R1 = high word)
    // 000010 1000 aaa bbb

    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,
    DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,   DO_IMULRW,

    // Reserved for Locutus
    // 000010 1001 ... ...

    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,

    // VMOVx    Src, RD       ; v3d[RD] = v3d[Src]    Copies a 3-vector from [Src] to [RMD].  Each vector component is 32 bits.
    // LOOP     RD            ; RD--, if RD is nonzero afterwards, R7 += disp
    // BA       disp          ; Branch if above (unsigned compare)       alternate: BNBE (branch if not below or equal)
    // BNA      disp          ; Branch if not above (unsigned compare)   alternate: BBE (branch if below or equal)
    // 000010 1010 sss ddd        VMOVx   sss <> ddd
    // 000010 1010 ddd ddd        LOOP    ddd < 6
    // 000010 1010 110 110 PPPP   BA      disp    ((C or Z) = 0)
    // 000010 1010 111 111 PPPP   BNA     disp    ((C or Z) = 1)

    DO_LOOP,     DO_VMOVNN,   DO_VMOVNN,   DO_VMOVNN,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,    // VMOV@@  R0, RD    (RD <> R0, if RD = R6, VPSH@  R0)       if RD = R0, LOOP R0 instead
    DO_VMOVNN,   DO_LOOP,     DO_VMOVNN,   DO_VMOVNN,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,    // VMOV@@  R1, RD    (RD <> R1, if RD = R6, VPSH@  R1)       if RD = R1, LOOP R1 instead
    DO_VMOVNN,   DO_VMOVNN,   DO_LOOP,     DO_VMOVNN,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,    // VMOV@@  R2, RD    (RD <> R2, if RD = R6, VPSH@  R2)       if RD = R2, LOOP R2 instead
    DO_VMOVNN,   DO_VMOVNN,   DO_VMOVNN,   DO_LOOP,     DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,   DO_VMOVNI,    // VMOV@@  R3, RD    (RD <> R3, if RD = R6, VPSH@  R3)       if RD = R3, LOOP R3 instead
    DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_LOOP,     DO_VMOVII,   DO_VMOVII,   DO_VMOVII,    // VMOV@@  R4, RD    (RD <> R4, if RD = R6, VPSH@  R4)       if RD = R4, LOOP R4 instead
    DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_VMOVII,   DO_LOOP,     DO_VMOVII,   DO_VMOVII,    // VMOV@@  R5, RD    (RD <> R5, if RD = R6, VPSH@  R5)       if RD = R5, LOOP R5 instead
    DO_VMOV6N,   DO_VMOV6N,   DO_VMOV6N,   DO_VMOV6N,   DO_VMOV6I,   DO_VMOV6I,   DO_BA,       DO_VMOV6I,    // VMOV@@  R6, RD    (RD <> R6, alternate: VPUL@ RD)         if RD = R6, BA instead
    DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_VMOVIN,   DO_VMOVII,   DO_VMOVII,   DO_VMOVII,   DO_BNA,       // VMVOI@  DATA, RD  (RD <> R7, if RD = R6, VPSH@  DATA)     if RD = R7, BNA instead

    // VADDx    Src, RD       ; v3d[RD] += v3d[Src]    Adds a 3-vector from [Src] to [RD].  Each vector component is 32 bits.
    // 000010 1011 sss ddd

    DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,    // VADD@@  R0, RD
    DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,    // VADD@@  R1, RD
    DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,    // VADD@@  R2, RD
    DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNN,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,   DO_VADDNI,    // VADD@@  R3, RD
    DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDSS,   DO_VADDII,   DO_VADDII,   DO_VADDIN,    // VADD@@  R4, RD
    DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDII,   DO_VADDSS,   DO_VADDII,   DO_VADDIN,    // VADD@@  R5, RD
    DO_VADD6N,   DO_VADD6N,   DO_VADD6N,   DO_VADD6N,   DO_VADD6I,   DO_VADD6I,   DO_VADD66,   DO_VADD6I,    // VADD@@  R6, RD
    DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDIN,   DO_VADDII,   DO_VADDII,   DO_VADDII,   DO_VADDSS,    // VADDI@  DATA, RD

    // VSUBx    Src, RD       ; v3d[RD] -= v3d[Src]    Subtracts a 3-vector in [Src] from [RD].  Each vector component is 32 bits.
    // 000010 1100 sss ddd

    DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,    // VSUB@@  R0, RD
    DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,    // VSUB@@  R1, RD
    DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,    // VSUB@@  R2, RD
    DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNN,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,   DO_VSUBNI,    // VSUB@@  R4, RD
    DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBSS,   DO_VSUBII,   DO_VSUBII,   DO_VSUBIN,    // VSUB@@  R4, RD
    DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBII,   DO_VSUBSS,   DO_VSUBII,   DO_VSUBIN,    // VSUB@@  R5, RD
    DO_VSUB6N,   DO_VSUB6N,   DO_VSUB6N,   DO_VSUB6N,   DO_VSUB6I,   DO_VSUB6I,   DO_VSUB66,   DO_VSUB6I,    // VSUB@@  R6, RD
    DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBIN,   DO_VSUBII,   DO_VSUBII,   DO_VSUBII,   DO_VSUBSS,    // VSUBI@  DATA, RD

    // UNPR     RB, RA        ; RB = RA >> 8, RA &= 0xFF       RA, RB = R0..R3    Unpacks RA into RB:RA
    // PCKR     RS, RD        ; RA = (RA & 0xFF) | (RB << 8)   RA, RB = R0..R3    Packs the low bytes of RB:RA into RA
    // LOOPE    RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if Z=1, R7 += disp
    // LOOPNE   RD            ; RD--, ddd < 6, if RD is nonzero afterwards and if Z=0, R7 += disp
    // BREVR    RD            ; RD = bit-reversed RD, RD = R0..R5
    // LOOPS    RD            ; RD--, ddd < 6, if RD is negative afterwards and if S=1, R7 += disp
    // LOOPNS   RD            ; RD--, ddd < 6, if RD is not negative afterwards and if S=0, R7 += disp
    // COMC                   ; C = !C
    // STCP     R0            ; if R0 contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as R0 parity)
    
    // 000010 1101 00b baa        UNPR
    // 000010 1101 01b baa        PCKR
    // 000010 1101 100 ddd PPPP   LOOPE         ddd < 6
    // 000010 1101 100 110        BREVR    R0
    // 000010 1101 100 111        BREVR    R1
    // 000010 1101 101 ddd PPPP   LOOPNE        ddd < 6
    // 000010 1101 101 110        BREVR    R2
    // 000010 1101 101 111        BREVR    R3
    // 000010 1101 110 ddd PPPP   LOOPS         ddd < 6
    // 000010 1101 110 110        BREVR    R4
    // 000010 1101 110 111        BREVR    R5
    // 000010 1101 111 ddd PPPP   LOOPNS        ddd < 6
    // 000010 1101 111 110        COMC
    // 000010 1101 111 111        STCP
    
    DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,    // UNPR   R0/R1, RA
    DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,     DO_UNPR,    // UNPR   R2/R3, RA
    DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,    // PCKR   R0/R1, RA
    DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,     DO_PCKR,    // PCKR   R2/R3, RA
    DO_LOOPE,    DO_LOOPE,    DO_LOOPE,    DO_LOOPE,    DO_LOOPE,    DO_LOOPE,    DO_BREVR0,   DO_BREVR1,  // LOOPE  R0..R5       BREVR   R0/R1
    DO_LOOPNE,   DO_LOOPNE,   DO_LOOPNE,   DO_LOOPNE,   DO_LOOPNE,   DO_LOOPNE,   DO_BREVR2,   DO_BREVR3,  // LOOPNE R0..R5       BREVR   R2/R3
    DO_LOOPS,    DO_LOOPS,    DO_LOOPS,    DO_LOOPS,    DO_LOOPS,    DO_LOOPS,    DO_BREVR4,   DO_BREVR5,  // LOOPS R0..R5        BREVR   R4/R5
    DO_LOOPNS,   DO_LOOPNS,   DO_LOOPNS,   DO_LOOPNS,   DO_LOOPNS,   DO_LOOPNS,   DO_COMC,     DO_STCP,    // LOOPNS R0..R5       COMC             STCP

    // MAXR     RS, RD        ; RD = unsigned maximum of RS and RD.   RS, RD = R0 .. R3
    // MINR     RS, RD        ; RD = unsigned minimum of RS and RD.   RS, RD = R0 .. R3
    // IMAXR    RS, RD        ; RD = signed maximum of RS and RD.   RS, RD = R0 .. R3
    // IMINR    RS, RD        ; RD = signed minimum of RS and RD.   RS, RD = R0 .. R3
    // 000010 1110 00s sdd    MAXR
    // 000010 1110 01s sdd    MINR
    // 000010 1110 10s sdd    IMAXR
    // 000010 1110 11s sdd    IMINR

    DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,    // MAXR   R0/R1, RD
    DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,     DO_MAXR,    // MAXR   R2/R3, RD
    DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,    // MINR   R0/R1, RD
    DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,     DO_MINR,    // MINR   R2/R3, RD
    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,   // IMAXR  R0/R1, RD
    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,    DO_IMAXR,   // IMAXR  R2/R3, RD
    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,   // IMINR  R0/R1, RD
    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,    DO_IMINR,   // IMINR  R2/R3, RD

    // SBBR     RD            ; RD -= C
    // B2AH     RD            ; RD = hexadecimal ASCII representation of the low byte of RD (e.g. 0x0A --> 3041 "0A")
    // SHLD     RD, IMM4      ; RD = high word of RD:R0 shifted left by 0 .. 15.  C = high bit of RD shifted out if amount > 0.  RD = R1 ... R3
    // 000010 1111 000 ddd    SBBR
    // 000010 1111 001 ddd    B2AH
    // 000010 1111 dd aaaa    SHLD

    DO_SBBR,     DO_SBBR,     DO_SBBR,     DO_SBBR,     DO_SBBR,     DO_SBBR,     DO_SBBR,     DO_SBBR,    // SBBR   RD
    DO_B2AH,     DO_B2AH,     DO_B2AH,     DO_B2AH,     DO_B2AH,     DO_B2AH,     DO_B2AH,     DO_B2AH,    // B2AH   RD
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R1:R0
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R1:R0
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R2:R0
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R2:R0
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R3:R0
    DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,     DO_SHLD,    // SHLD   R3:R0

    // AH2B     RD            ; RD = binary value (0..255) of hexadecimal ASCII characters stored in RD.  Invalid characters in a byte result
    //                        ; in that byte being interpreted as 0 (e.g. 3041 --> 0x0A, 2F41 --> 0x0A). Ignores case.
    // DIV5     RD            ; RD /= 5 (unsigned divide)
    // SHRD     RS, IMM4      ; R0 = low word of RS:R0 shifted right by 0 .. 15.  C = low bit of R0 shifted out if amount > 0.  RS = R1 ... R3
    // 000011 0000 000 ddd    AH2B
    // 000011 0000 001 ddd    DIV5
    // 000011 0000 ss aaaa    SHRD

    DO_AH2B,     DO_AH2B,     DO_AH2B,     DO_AH2B,     DO_AH2B,     DO_AH2B,     DO_AH2B,     DO_AH2B,    // A2BH   RD
    DO_DIV5,     DO_DIV5,     DO_DIV5,     DO_DIV5,     DO_DIV5,     DO_DIV5,     DO_DIV5,     DO_DIV5,    // DIV5   RD
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R1:R0
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R1:R0
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R2:R0
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R2:R0
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R3:R0
    DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,     DO_SHRD,    // SHRD   R3:R0

    // CL0R     RD            ; RD = number of consecutive 0 bits in RD starting at the MSB
    // CL1R     RD            ; RD = number of consecutive 1 bits in RD starting at the MSB
    // CT0R     RD            ; RD = number of consecutive 0 bits in RD starting at the LSB
    // CT1R     RD            ; RD = number of consecutive 1 bits in RD starting at the LSB
    // SUBGER0  RD            ; if RD >= R0 (unsigned compare), RD -= R0.  Useful for speeding up division algorithms.
    // DIV3     RD            ; RD /= 3 (unsigned divide)
    // DIV100   RD            ; RD /= 100 (unsigned divide)
    // DUPLR    RD            ; RD = (RD & 0xFF) | (RD << 8)      Duplicates the low byte in RD
    // 000011 0001 000 ddd    CL0R
    // 000011 0001 001 ddd    CL1R
    // 000011 0001 010 ddd    CT0R
    // 000011 0001 011 ddd    CT1R
    // 000011 0001 100 ddd    SUBGER0
    // 000011 0001 101 ddd    DIV3
    // 000011 0001 110 ddd    DIV100
    // 000011 0001 110 ddd    DUPLR

    DO_CL0R,     DO_CL0R,     DO_CL0R,     DO_CL0R,     DO_CL0R,     DO_CL0R,     DO_CL0R,     DO_CL0R,    // CL0R    RD
    DO_CL1R,     DO_CL1R,     DO_CL1R,     DO_CL1R,     DO_CL1R,     DO_CL1R,     DO_CL1R,     DO_CL1R,    // CL1R    RD
    DO_CT0R,     DO_CT0R,     DO_CT0R,     DO_CT0R,     DO_CT0R,     DO_CT0R,     DO_CT0R,     DO_CT0R,    // CT0R    RD
    DO_CT1R,     DO_CT1R,     DO_CT1R,     DO_CT1R,     DO_CT1R,     DO_CT1R,     DO_CT1R,     DO_CT1R,    // CT1R    RD
    DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0,  DO_SUBGER0, // SUBGER0 RD
    DO_DIV3,     DO_DIV3,     DO_DIV3,     DO_DIV3,     DO_DIV3,     DO_DIV3,     DO_DIV3,     DO_DIV3,    // DIV3    RD
    DO_DIV100,   DO_DIV100,   DO_DIV100,   DO_DIV100,   DO_DIV100,   DO_DIV100,   DO_DIV100,   DO_DIV100,  // DIV100  RD
    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,    DO_DUPLR,   // DUPLR   RD

    // DECLR    RD            ; Decrements only the low byte of RD.  If RD was 0, it rolls over to 255 without affecting the high byte but sets the carry flag.
    // XCHGR    RA, RB        ; Swaps the contents of RA and RB     RA <> RB
    // 000011 0010 aaa bbb    XCHGR        aaa <> bbb
    // 000011 0010 ddd ddd    INCLR

    DO_DECLR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R0,      XCHGR   RA, RB
    DO_XCHGR,    DO_DECLR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R1,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_DECLR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R2,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_DECLR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R3,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_DECLR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R4,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_DECLR,    DO_XCHGR,    DO_XCHGR,   // DECLR   R5,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_DECLR,    DO_XCHGR,   // DECLR   R6,      XCHGR   RA, RB
    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_XCHGR,    DO_DECLR,   // DECLR   R7,      XCHGR   RA, RB

    // MVID@    RM, RD, disp      ; RD = [RM + disp]    Does ***not*** change R4 .. R6 if mmm=4..6. Supports SDBD.
    // 000011 0011 mmm ddd PPPP   MVID

    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R0, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R1, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R2, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R3, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R4, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R5, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R6, RD, disp
    DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,     DO_MVID,    // MVID@   R7, RD, disp

    // MVOD@    RM, RS, disp      ; [RM + disp] = RS    Does ***not*** change R4 .. R6 if mmm=4..6. Supports SDBD.
    // 000011 0100 mmm sss PPPP   MVOD

    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R0, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R1, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R2, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R3, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R4, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R5, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R6, RD, disp
    DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,     DO_MVOD,    // MVOD@   R7, RD, disp

    // ABSR     RD            ; RD = |RD|
    // POW2R    RD            ; RD = 1 << RD            If RD > 15, result is 0
    // ABSRW@   RD            ; D[RD] = |D[RD]|         Replaces the 32-bit DWORD at [RD] with its absolute value
    // MVO@     R0, RS        ; Just like normal MVO@ but supports R0
    // MVI@     R0, RD        ; Just like normal MVI@ but supports R0
    // ADD@     R0, RD        ; Just like normal ADD@ but supports R0
    // SUB@     R0, RD        ; Just like normal SUB@ but supports R0
    // CMP@     R0, RD        ; Just like normal CMP@ but supports R0
    // 000011 0101 000 ddd    ABSR
    // 000011 0101 001 ddd    POW2R
    // 000011 0101 010 ddd    ABSRW@
    // 000011 0101 011 sss    MVO@   R0, RS
    // 000011 0101 100 ddd    MVI@   R0, RD
    // 000011 0101 101 ddd    ADD@   R0, RD
    // 000011 0101 110 ddd    SUB@   R0, RD
    // 000011 0101 111 ddd    CMP@   R0, RD

    DO_ABSR,     DO_ABSR,     DO_ABSR,     DO_ABSR,     DO_ABSR,     DO_ABSR,     DO_ABSR,     DO_ABSR,    // ABSR    RD
    DO_POW2R,    DO_POW2R,    DO_POW2R,    DO_POW2R,    DO_POW2R,    DO_POW2R,    DO_POW2R,    DO_POW2R,   // POW2R   RD
    DO_ABSRWI,   DO_ABSRWI,   DO_ABSRWI,   DO_ABSRWI,   DO_ABSRWN,   DO_ABSRWN,   DO_ABSRW6,   DO_ABSRWN,  // ABSRW@  RD
    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,    DO_MVOA0,   // MVO@    R0, RS
    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,    DO_MVIA0,   // MVI@    R0, RD
    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,    DO_ADDA0,   // ADD@    R0, RD
    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,    DO_SUBA0,   // SUB@    R0, RD
    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,    DO_CMPA0,   // CMP@    R0, RD

    // AND@     R0,   RD      ; Just like normal AND@ but supports R0
    // XOR@     R0,   RD      ; Just like normal XOR@ but supports R0
    // OR       ADDR, RD      ; RD |= [ADDR]
    // ADC      ADDR, RD      ; RD += [ADDR] + C
    // SBB      ADDR, RD      ; RD -= ([ADDR] + C)
    // TST      ADDR, RD      ; Set S and Z flags based on (RD & [ADDR])
    // SLL      ADDR, RD      ; RD <<= [ADDR]
    // SLR      ADDR, RD      ; RD >>= [ADDR]
    // 000011 0110 000 ddd    AND@   R0,   RD
    // 000011 0110 001 ddd    XOR@   R0,   RD
    // 000011 0110 010 ddd    OR     ADDR, RD
    // 000011 0110 011 ddd    ADC    ADDR, RD
    // 000011 0110 100 ddd    SBB    ADDR, RD
    // 000011 0110 101 ddd    TST    ADDR, RD
    // 000011 0110 110 ddd    SLL    ADDR, RD
    // 000011 0110 111 ddd    SLR    ADDR, RD

    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,    DO_ANDA0,     // AND@   R0, RD
    DO_XORA0,    DO_XORA0,    DO_XORA0,    DO_XORA0,    DO_XORA0,    DO_XORA0,    DO_XORA0,    DO_XORA0,     // XOR@   R0, RD
    DO_OR,       DO_OR,       DO_OR,       DO_OR,       DO_OR,       DO_OR,       DO_OR,       DO_OR,        // OR     RD, ADDR
    DO_ADC,      DO_ADC,      DO_ADC,      DO_ADC,      DO_ADC,      DO_ADC,      DO_ADC,      DO_ADC,       // ADC    RD, ADDR
    DO_SBB,      DO_SBB,      DO_SBB,      DO_SBB,      DO_SBB,      DO_SBB,      DO_SBB,      DO_SBB,       // SBB    RD, ADDR
    DO_TST,      DO_TST,      DO_TST,      DO_TST,      DO_TST,      DO_TST,      DO_TST,      DO_TST,       // TST    RS, ADDR
    DO_SLLA,     DO_SLLA,     DO_SLLA,     DO_SLLA,     DO_SLLA,     DO_SLLA,     DO_SLLA,     DO_SLLA,      // SLL    RD, ADDR
    DO_SLRA,     DO_SLRA,     DO_SLRA,     DO_SLRA,     DO_SLRA,     DO_SLRA,     DO_SLRA,     DO_SLRA,      // SLR    RD, ADDR

    // SAR      ADDR, RD      ; RD = RD sar [ADDR]    (arithmetic shift right)
    // ROL      ADDR, RD      ; RD = RD rol [ADDR]
    // ROR      ADDR, RD      ; RD = RD ror [ADDR]
    // MUL      ADDR, RD      ; RD *= [ADDR]          (unsigned multiply)
    // IMUL     ADDR, RD      ; RD *= [ADDR]          (signed multiply)
    // VMOV@    ADDR, RD      ; v3d[RD] = v3d[ADDR]     Copies a 3-vector from [ADDR] to [RD].  Each vector component is 32 bits.
    // VADD@    ADDR, RD      ; v3d[RD] += v3d[ADDR]    Adds a 3-vector from [ADDR] to [RD].  Each vector component is 32 bits.
    // VSUB@    ADDR, RD      ; v3d[RD] -= v3d[ADDR]    Subtracts a 3-vector in [ADDR] from [RD].  Each vector component is 32 bits.
    // 000011 0111 000 ddd    SAR    ADDR, RD
    // 000011 0111 001 ddd    ROL    ADDR, RD
    // 000011 0111 010 ddd    ROR    ADDR, RD
    // 000011 0111 011 ddd    MUL    ADDR, RD
    // 000011 0111 100 ddd    IMUL   ADDR, RD
    // 000011 0111 101 ddd    VMOV   ADDR, RD
    // 000011 0111 110 ddd    VADD   ADDR, RD
    // 000011 0111 111 ddd    VSUB   ADDR, RD

    DO_SARA,     DO_SARA,     DO_SARA,     DO_SARA,     DO_SARA,     DO_SARA,     DO_SARA,     DO_SARA,      // SAR    RD, ADDR
    DO_ROL,      DO_ROL,      DO_ROL,      DO_ROL,      DO_ROL,      DO_ROL,      DO_ROL,      DO_ROL,       // ROL    RD, ADDR
    DO_ROR,      DO_ROR,      DO_ROR,      DO_ROR,      DO_ROR,      DO_ROR,      DO_ROR,      DO_ROR,       // ROR    RD, ADDR
    DO_MUL,      DO_MUL,      DO_MUL,      DO_MUL,      DO_MUL,      DO_MUL,      DO_MUL,      DO_MUL,       // MUL    ADDR, RD
    DO_IMUL,     DO_IMUL,     DO_IMUL,     DO_IMUL,     DO_IMUL,     DO_IMUL,     DO_IMUL,     DO_IMUL,      // IMUL   ADDR, RD
    DO_VMOVN,    DO_VMOVN,    DO_VMOVN,    DO_VMOVN,    DO_VMOVI,    DO_VMOVI,    DO_VMOVI,    DO_VMOVI,     // VMOV@  ADDR, RMD  (if RMD = R6, VPSH   ADDR)
    DO_VADDN,    DO_VADDN,    DO_VADDN,    DO_VADDN,    DO_VADDI,    DO_VADDI,    DO_VADDI,    DO_VADDI,     // VADD@  ADDR, RMD
    DO_VSUBN,    DO_VSUBN,    DO_VSUBN,    DO_VSUBN,    DO_VSUBI,    DO_VSUBI,    DO_VSUBI,    DO_VSUBI,     // VSUB@  ADDR, RMD

    // FPMULDx   Src, RD      ; Unsigned 32-bit fixed-point values (16.16 format) at Src and [RD] are multiplied and the
    //                        ; 16.16 format fixed-point result placed in [RD].
    // 000011 1000 sss ddd    FPMULD@@  [RS], RD        ; F[RD] *= F[RS]
    // 000011 1000 111 ddd    FPMULDI@  DATA, RD        ; F[RD] *= DATA (32-bit immediate in 16.16 format)

    DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI,  // FPMULD@@  R0,   RD
    DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI,  // FPMULD@@  R1,   RD
    DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI,  // FPMULD@@  R2,   RD
    DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNN, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI, DO_FPMULDNI,  // FPMULD@@  R3,   RD
    DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII,  // FPMULD@@  R4,   RD
    DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII,  // FPMULD@@  R5,   RD
    DO_FPMULD6N, DO_FPMULD6N, DO_FPMULD6N, DO_FPMULD6N, DO_FPMULD6I, DO_FPMULD6I, DO_FPMULD6I, DO_FPMULD6I,  // FPMULD@@  R6,   RD
    DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDIN, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII, DO_FPMULDII,  // FPMULDI@  DATA, RD

    // Reserved for Locutus
    // 000011 1001 ... ...

    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,
    DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,      DO_NOP,

    // IFPMULDx   Src, RD     ; Signed 32-bit fixed-point values (16.16 format) at Src and [RD] are multiplied and the
    //                        ; 16.16 format fixed-point result placed in [RD].
    // 000011 1010 sss ddd    IFPMULD@@  [RS], RD       ; F[RD] *= F[RS]
    // 000011 1010 111 ddd    IFPMULDI@  DATA, RD       ; F[RD] *= DATA (32-bit immediate in 16.16 format)

    DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI,  // IFPMULD@@  R0,   RD
    DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI,  // IFPMULD@@  R1,   RD
    DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI,  // IFPMULD@@  R2,   RD
    DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNN, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI, DO_IFPMULDNI,  // IFPMULD@@  R3,   RD
    DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII,  // IFPMULD@@  R4,   RD
    DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII,  // IFPMULD@@  R5,   RD
    DO_IFPMULD6N, DO_IFPMULD6N, DO_IFPMULD6N, DO_IFPMULD6N, DO_IFPMULD6I, DO_IFPMULD6I, DO_IFPMULD6I, DO_IFPMULD6I,  // IFPMULD@@  R6,   RD
    DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDIN, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII, DO_IFPMULDII,  // IFPMULDI@  DATA, RD

    // FPMULD@   ADDR, RD     ; Unsigned 32-bit fixed-point values (16.16 format) at Src and [RD] are multiplied and the
    //                        ; 16.16 format fixed-point result placed in [RD].
    // IFPMULDx  ADDR, RD     ; Signed 32-bit fixed-point values (16.16 format) at Src and [RD] are multiplied and the
    //                        ; 16.16 format fixed-point result placed in [RD].
    // MVOI      DATA, ADDR   ; [ADDR] = DATA
    // ADDI      DATA, ADDR   ; [ADDR] += DATA
    // SUBI      DATA, ADDR   ; [ADDR] -= DATA
    // CMPI      DATA, ADDR   ; Sets flags based on ([ADDR] - DATA)
    // ANDI      DATA, ADDR   ; [ADDR] &= DATA
    // XORI      DATA, ADDR   ; [ADDR] ^= DATA
    // ORI       DATA, ADDR   ; [ADDR] |= DATA
    // ADCI      DATA, ADDR   ; [ADDR] += DATA + C
    // SBBI      DATA, ADDR   ; [ADDR] -= (DATA + C)
    // TSTI      DATA, ADDR   ; Sets Z and S flags based on ([ADDR] & DATA)
    // SLLI      DATA, ADDR   ; [ADDR] <<= DATA
    // SLRI      DATA, ADDR   ; [ADDR] >>= DATA
    // SARI      DATA, ADDR   ; [ADDR] = [ADDR] sar DATA    (arithmetic shift right)
    // ROLI      DATA, ADDR   ; [ADDR] = [ADDR] rol DATA
    // ROLI      DATA, ADDR   ; [ADDR] = [ADDR] ror DATA
    // MULI      DATA, ADDR   ; [ADDR] *= DATA              (unsigned multiply)
    // IMULI     DATA, ADDR   ; [ADDR] *= DATA              (signed multiply)
    // STCP      RD           ; RD = R1..R3  if RD contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as RD parity)
    // SWAP      RD           ; Same as SWAP, but supports R4..R7
    // 000011 1011 000 ddd    FPMULD@   ADDR, RD       ; F[RD] *= F[ADDR]
    // 000011 1011 001 ddd    IFPMULD@  ADDR, RD       ; F[RD] *= F[ADDR]
    // 000011 1011 001 000    MVOIA     DATA, ADDR
    // 000011 1011 001 001    ADDIA     DATA, ADDR
    // 000011 1011 001 010    SUBIA     DATA, ADDR
    // 000011 1011 001 011    CMPIA     DATA, ADDR
    // 000011 1011 001 100    ANDIA     DATA, ADDR
    // 000011 1011 001 101    XORIA     DATA, ADDR
    // 000011 1011 001 110    ORIA      DATA, ADDR
    // 000011 1011 001 111    ADCIA     DATA, ADDR
    // 000011 1001 010 000    SBBIA     DATA, ADDR
    // 000011 1011 010 001    TSTIA     DATA, ADDR
    // 000011 1011 010 010    SLLIA     DATA, ADDR
    // 000011 1011 010 011    SLRIA     DATA, ADDR
    // 000011 1011 010 100    SARIA     DATA, ADDR
    // 000011 1011 010 101    ROLIA     DATA, ADDR
    // 000011 1011 010 110    RORIA     DATA, ADDR
    // 000011 1011 010 111    MULIA     DATA, ADDR
    // 000011 1011 011 000    IMULIA    DATA, ADDR
    // 000011 1011 011 0dd    STCP      RD           dd <> 0
    // 000011 1011 011 1dd    SWAP      RD           RD=dd+4

    DO_FPMULDN,  DO_FPMULDN,  DO_FPMULDN,  DO_FPMULDN,  DO_FPMULDI,  DO_FPMULDI,  DO_FPMULDI,  DO_FPMULDI,   // FPMULD@   ADDR, RD
    DO_IFPMULDN, DO_IFPMULDN, DO_IFPMULDN, DO_IFPMULDN, DO_IFPMULDI, DO_IFPMULDI, DO_IFPMULDI, DO_IFPMULDI,  // IFPMULD@   ADDR, RD
    DO_MVOIA,    DO_ADDIA,    DO_SUBIA,    DO_CMPIA,    DO_ANDIA,    DO_XORIA,    DO_ORIA,     DO_ADCIA,
    DO_SBBIA,    DO_TSTIA,    DO_SLLIA,    DO_SLRIA,    DO_SARIA,    DO_ROLIA,    DO_RORIA,    DO_MULIA,
    DO_IMULIA,   DO_STCP123,  DO_STCP123,  DO_STCP123,  DO_SWAP3,    DO_SWAP3,    DO_SWAP3,    DO_SWAP3
  };

 

Edited by JohnPCAE
Link to comment
Share on other sites

I managed to condense how I handle instruction dispatching to save space by using a pair of smaller lookup tables instead of one large one. It incurs a very tiny performance penalty but in the grand scheme of things it's only a few clock cycles. This freed up a bunch of RAM and I managed to add more emulated instructions and expand some existing ones. I found that the Pi Pico has a hardware integer divider so I've added a bunch of divide and remainder instructions, a bunch of new bitwise instructions inspired by the Locutus ones (NAND, NOR, etc.) and some other odds and ends.

 

My RS-232 tester came in, but...Cancer? WTH?

 

IMG_2162.JPG

Edited by JohnPCAE
Link to comment
Share on other sites

1 hour ago, Sinjinhawke said:

Wow, keep that away from your ovaries.  

LOL. I opened it up and took a look inside. I didn't see anything out of the ordinary, just a standard circuit board with LED's, DIP switches, and some SIP resistor arrays. I was half expecting a tritium battery or something ?

  • Haha 1
Link to comment
Share on other sites

I'm happy to say that my Intellivision now has a working bidirectional parallel port ?

 

The current hardware differs from standard parallel ports in one way: you cannot receive data on the four control signals (STROBE, AUTO_LINEFEED, INITIALIZE, SELECT_PRINTER). That said, I found a way to enhance the board design so that it's possible to receive data on three of them. I had three pins available on one of my LS245 chips so I can route the first three of them to those input pins. I have 1k resistors on those four control pins between my LS574 outputs and the actual parallel port pin, so I simply needed to run traces from three parallel port pins to the three free inputs on my LS245 chip. Those three inputs will show up in three spare bits on the printer status port. So with the exception of pin 17 (Select_Printer), the Inty can fulfill all of the functions of a standard parallel port (pin 17 will be output-only). And it has input capability on the data pins (you switch the data pins from output to input by setting bit 5 on the control port, just as you would on a PC).

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...