Sunday, September 13


Imaginary Code

Here's the full programming model of the Imagine CPU and DSP.  I'll write a proper manual as I go; this is mostly to give an idea of what the processor will look like, and as a document for myself to make sure I haven't either (a) missed anything critical or worse (b) run out of opcodes.

Let's see if I can get a bunch of preformatted text in place without the Minx editor reducing it to mush...  Yes, on my third try.

Couple of things that fell out of this proper run-through of the full programming model:
  • We now have eight stack pointers!  The bits were there to be used, so why the hell not.  All four index registers, the two reserved stack pointers, the loop counter, and even the program counter can be used as stack pointers.

  • Why the hell would you use the program counter as a stack pointer?  Well, for pushing data it would be very weird.  But for popping data, you can read up to ten registers at once from immediate data:

    POP P, WXYZLT will read read the four main index registers and two alternate index registers with a single two-byte instruction; normally that would take six separate instructions.  Great if you're setting up for some complex graphics algorithm.

    And POP P, WXYZSPLURT will set up all the index registers and stack pointers, and branch to a new place in the code.  If you don't trash the stack you might be able to turn it into a subroutine call.

    PUSH P on the other hand will push the specified registers into the current program, in reverse order, and then execute them.  I can't imagine why you would want to do that, but you can.

  • Similarly, I borrowed LEA - Load Effective Address - from the 6809.  But you can also LEAP - that is, LEA to P, the program counter.  Since LEA supports base+offset addressing and indirect addressing simultaneously, that provides us with both fixed and relative jump tables, without needing an instruction specific for that.

    In fact, you can even LEAP into an interpolated jump table.  There's nothing stopping you.

  • The general word-size bit fell by the wayside.  There's just not enough opcodes on a 10-bit design.  Instead I reserved a code page (32 opcodes) for 20-bit instructions, which gives us 15 available bits for that mode.

    I haven't really started on the details of 20-bit mode.  Having 32 times the opcode space is liberating to the point of paralysis.  Maybe the early Imagine models didn't implement 20-bit mode.

  • One group of registers spells SPLURT.  Another spells out QOFI.  The remainder are ABCD and WXYZ which don't really spell out anything.

  • The .B and .W markers are almost always optional; the assembler can distinguish the mode either from the registers used or from the size of the immediate data.  For example, BRA $F0 means BRA.B and BRA $000F0 means BRA.W.  Of course the two instructions do esentially the same thing.

  • I've done a draft of the Dream programming model as well; it's very similar albeit with another eight registers and with some rough corners smoothed off.  The Imagine needs some specialised opcodes for handling registers outside the two main sets (ABCD and WXYZ).  The Dream has enough bits in its register selection to handle that in an orderly manner.

    This is a mixed blessing.  Want to add accumulator A to the flags register F?  The Imagine very sensibly has no opcode for such a dumb instruction, but the Dream is happy to oblige.

Update 2020-09-14
  • In the indexing postbyte:
    • A value of 7 now codes for no base, allowing for indirect mode
    • In the offset, 12 through 15 code for WH through ZH for LEAF mode.
    • The loop counter L is no longer available as a base, only as an offset.
    • Timer / alternate index register T is not available at all.

  • The A100 and A101 segmented microprocessors now have two register banks, including all segment base and size registers.
  • The A102 and A103 (non-segmented) microcontrollers now have four register banks, but of course no segment registers.
  • The A108 DSP and A109 ASP now have eight banks of general-purpose registers - accumulators ABCD and WXYZ - but only one bank of the remaining registers.  (Also no segment registers.)

# Op page 0 is partly reserved
# Opcode 000 is NOP
 0 Special

# Basic arithmetic and logical operations
 1 ADD.B [abcd], SRC
 2 ADC.B [abcd], SRC
 3 SUB.B [abcd], SRC
 4 SBC.B [abcd], SRC
 5 AND.B [abcd], SRC
 6 OR.B [abcd], SRC
 7 XOR.B [abcd], SRC

# Load and store accumulators
 8 LD.B [abcd], SRC
 9 ST.B [abcd], DST

# Load and store index registers
10 LD.W [wxyz], SRC
11 ST.W [wxyx], DST

# Load effective address - calculates an indexed address using the 
# indexing postbyte and stores it in the designated register.

# This can be used for computed jumps and branches by loading to P.
# The LEAP instruction is an accepted variant of LEA P.

# Four modes - normal 20-bit, fractional (20.10), extended (10.20),
# and segmented (20.20).  Extended and segmented addressing are not available
# on all versions of the CPU and may cause an illegal address trap.

# See Indexing Postbyte docs for full details.

12 LEA [wxyzplus] 
   LEAF [wxyzplus]
   LEAX [wxyzplus]
   LEAS [wxyzplus]

# Special load/store ops on F, Q, L, and T registers

# F = flags
# Q = quick page
# L = loop counter
# T = timer / counter

# L and T can also be used as indexes (L) and offsets (both) in LEA operations

13 LD.B [abcd], [fq]
   ST.B [abcd], [fq]
   LD.W [wxyz], [lt]
   ST.W [wxyz], [lt]
# Push instructions

# Any base register, including the program counter and loop register
# can be used as a stack pointer.

# PUSH P overwrites the instructions immediately before the program
# counter in reverse order and then executes them.  This is not an 
# illegal operation but it is very weird.  Please don't do this.  

# Note: Despite the cute convention of "wxyzsplurt", P is
# always the last register to be PUSHed or POPped. 
# This allows a POP from immediate data to include the
# address of a subroutine, loading parameters and jumping
# in a single instruction.

14 PUSH.B [wxyzplus], [abcdfqio]
   PUSH.W [wxyzplus], [wxyzsplurt]

# Pop instructions

# POP P can be used to load multiple registers from immediate data.
# Unlike PUSH P it is sane and useful.

15 POP.B [wxyzplus], [abcdfqio]
   POP.W [wxyzplus], [wxyzsplurt]

# IO operations
16 IN.B [abcd], SRC
17 OUT.B [abcd], DST

# Conditionally execute next N bytes (N=1..4)
18 IFcc N

# Loop on N bytes (N=1..4)
# Loop continues until the loop register L reaches zero or the
# condition code is met by the instructions in the loop.
19 LOOPcc N

# Conditional branch, jump, return
# For conditional computed branches and jumps use IFcc / LEAP
20 BRcc.B 

# Compare
21 CMP.B [abcd], SRC
22 CMP.W [wxyc], SRC

# Shift and rotate - only available on byte registers
23 LSL [abcd]
   LSR [abcd]
   ASL [abcd]
   ASR [abcd]
   ROL [abcd]
   RLC [abcd]
   ROR [abcd]
   RRC [abcd]   

# Single-register operations

24 CLR.B [abcd]
   COM.B [abcd]
   NEG.B [abcd]
   SEX [wxyz]
   CLR.W [wxyz]
   COM.W [wxyz]
   NEG.W [wxyz]
   SWAPB [wxyz]

25 INC.B [abcd]
   DEC.B [abcd]
   INC.W [wxyz]
   DEC.W [wxyz]
   INC.W [lt]
   DEC.W [lt]
   TST.W [lt]
   CLR.W [lt]
   TST.W [abcd]
   TST.W [wxyz]

# 10/20 bit conversions
26 ST.B [abcd], [wxyz]
   LD.WL [ac], [wxyz]
   LD.WH [bd], [wxyz]

# Multiply, multiply/accumulate, and divide.
# Will trap to firmware on older devices.

# These have limited register selection.

# MUL, MULS, and MAC multiply A x B or C x D and store or add 
# to W, X, Y, or Z.

# DIV only supports A as a divisor

27 MUL [wxyz], ab
   MUL [wxyz], cd
   MULS [wxyz], ab
   MULS [wxyz], cd
   MAC [wxyz], ab
   MAC [wxyz], cd
   DIV [wzyz], a
   DIVS [wzyz], a   
# Swap   
28 SWAP [abcd], DST

# DSP Operations
29 MAC [al / ar] [abcd] [abcd]

30 Reserved for 20-bit opcodes

# Op page 31 is used for subroutine and system instructions
# including interrupt handling, segment management, and extended
# addressing.
31 System
   JSR address
   SWI [abcd]
   GRP [0-7]


A 10-bit accumulator
B 10-bit accumulator
C 10-bit accumulator
D 10-bit accumulator

W 20-bit index
X 20-bit index
Y 20-bit index
Z 20-bit index

S 20-bit stack pointer
U 20-bit stack pointer

L 20-bit loop counter / index
T 20-bit timer / offset

P 20-bit program counter
R 20-bit refresh counter

Q 10-bit quick page base register
O 10-bit output page base register
F 10-bit flags register
I 10-bit interrupt vector register

SRC / DST Encoding
    Byte  Word
0   a	  w
1   b	  x
2   c	  y
3   d	  z

4   P + byte offset
5   Q + byte offset  
6   Immediate
7   Indexed

Indexing Postbyte Encoding

Bits 0-2 are the base

0	w
1	x
2	y
3	z
4	s
5       u
6	p
7	none

Bits 3-6 are the offset

0	a
1	b
2	c
3	d
4	immediate byte
5	immediate word
6       none
7	l
8	w
9	x
10	y
11	z
12	wh
13      xh
14	yh
15	zh

In fractional mode (the LEAF instruction, or explicitly) the high byte of 
the offset - W, X, Y or Z - is added as a low byte to the base.

Bits 7-8 are the increment / decrement control

0 no action
1 post-increment offset
2 pre-decrement base
3 post-increment base

Bit 9 is the indirect flag.  If set, the address is calculated, 
the contents of that address are read, and those contents are returned 
as the resulting address

0 direct
1 indirect

Posted by: Pixy Misa at 04:49 PM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 1593 words, total size 11 kb.

Apple pies are delicious. But never mind apple pies. What colour is a green orange?

55kb generated in CPU 0.08, elapsed 0.2422 seconds.
56 queries taking 0.1645 seconds, 318 records returned.
Powered by Minx 1.1.6c-pink.