home .. forth .. misc mail list archive ..

Re: how does + work (MuP21)?


Greg,

>the diagrams I have indicate that you have MSBit cleared/set backwards.
>Is this just a simple mistake on your part, or have I misinterpretted
>something?
>(the opcode for JUMP in the diagram I am looking at, for example, is 00)

Simple mistake (it was very late at the end of night), I apologize.
You're right: opcodes 00 to 0F trigger a memory access, whereas 10 to 1F don't.
And I mispelled the two conditionnal jump instructions.

In my previous mail, substitute the following two WRONG lines:
>instructions have their MSBit cleared (the MSBit is set for the memory access
>instr @ @+ ! !+ LIT, and for the desequencing instr call ret jump jz jc, which

with the following two RIGHT lines:
>instructions have their MSBit set (the MSBit is cleared for the memory access
>instr @ @+ ! !+ LIT, and for the desequencing instr call ret jump T0 C0, which

--
>In instructions like T=0 (conditional branch) Ting's diagrams lead me
>to believe that if the branch comes in slot 0 that whatever comes in
>slot 1 will always be ignored.  Is this always the case, or is it only
>the case when the branch is taken?

The CALL, JUMP, T0, and C0 instructions may be executed in any slot, but are
only really useful in slot 0, because they use the contents of slots 1, 2, and
3, to generate the fifteen LSBits of the branch address, the 6 MSBits of the
branch address are taken from the 6 MSBits of P (the program word pointer).
In the case of the conditionnal branches (T0 when T is null, or C0 when T's
MSBit is null), whether the branch is taken or not does not change the fact
that the slots 1, 2, and 3, encode the branch address: if the branch is not
taken, execution continues with the first instruction of the _next_ program
word.

Note that the branch address is not transfered into P: it is directly used to
drive the address bus (as is the output of the R register on top of return
stack when a return instruction is executed) instread of P; the address bus is
permanently connected to the input of an address incrementer, which output is
latched into P (or into A for the @+ and !+ instructions) at the end of the
memory cycle.

When P points to byte memory (mainly during boot), 12 of the 20 data lines are
reallocated as address lines, and only the 8 LSBits of the instruction register
are loaded, i.e. slot 4's 5 bits and 3 bits from slot 3 (in fact the other 12
bits of the instruction register are loaded with the state of the corresponding
reallocated address lines), and slots 0, 1, and 2, are ignored, so only slot 4
is fed to the instruction decoder.
Therefore the CALL, JUMP, T0, and C0 instructions opcodes are in this case part
of the branch address: they each are only able to branch to no more than 8
different addresses.  Although this may seem very cumbersome, it doesn't matter
because only a very small bootloader has to be coded this way, which is limited
to assembling a few bytes into words to build a "secondary" bootloader into
word memory, to which it then jumps.

--
I can't cite your questions about opposite hardware polarities between even and
odd register bits (I erased your mail inadvertantly). Your guess are wrong.

Think it simpler: as a programmer, just forget it until you come to the chip's
I/O pads; then, simply imagine that every odd pad contains an inverter
(although it's not the reallity, it is strictly equivalent, except for the
silicon designer point of view).

As an application programmer: if you have to input (resp. output) communication
data through the I/O pads, invert every odd address bit, and invert every odd
data bit just _after_ the inputing @ (resp. just _before_ the outputing !).
When the address (and/or the output data) is a compile-time constant, you may
"AAAAA XOR" it at compile time, otherwise you must "AAAAA #, xor," it at run
time.  Don't care for it anywhere else in your programs: particularly, if you
store data in external memory to read them later, don't bother because they
will go twice through the inverters; in particular, a native MuP21 compiler
(i.e. executed by the MuP21 itself) _must_not_ invert the odd bits of the code
and data words that it outputs to memory.

As a cross-compiler writter: as your code (resp. data) is generated off-chip,
it will have to go through the pads when loaded into the instruction register
(resp. the T register); then in order to compensate for the inverting odd pads,
every address and code or data word must have its odd bits inverted (i.e. XORed
with hex AAAAA) when stored in memory; this inversion does not need to be done
during compilation, it's easier to do it when transfering the compiler output
from a file into a memory.

As a board designer: you cannot observe the chip's internal working, but only
its external bus activity, so invert every odd data or address bit; for example
the internal address sequence:  00000, 00001, 00002, 00003, 00004, 00005...
will be externally observed as: AAAAA, AAAAB, AAAA8, AAAA9, AAAAE, AAAAF...
My simulators have a switch to display either the internal or the external
patterns, whether you want to have the software or the hardware point of view.

As a silicon designer: it makes you a bit schizophrenic because you have to
invert your mind every other bit, but it's not really harder than to think
complementary when laying out CMOS circuits, or even to think horizontal and
vertical layout symmetries: it's a lot of fun, ask Chuck!

--
I hope that these few tricks will help you become a happier misc fellow :-)

CL
--
http://www-rocq.inria.fr/~lavarenn
Pourquoi faire simple quand on peut faire complique'?