Вы находитесь на странице: 1из 30

Building the P

Design and Operation of Microprocessors 1 Review of Digital Logic


1.1 Number Systems The mapping of unsigned and signed numbers into a space of 2 possible values can be accomplished in N many ways. A series of 0-based numbers (0 through 2 1) can be mapped directly into their binary representation, such that each number A =
N

k =0

a k 2k .

For signed numbers mapped into a space of 2


N-1

values, half of the values are mapped to non-negative values (0 through 2 1) and half are mapped to N-1 negative values (-1 through -2 ). The non-negative values are mapped identically to the method used for the unsigned case. The negative values as mapped as twos-compliments of their negated value. Twos-compliment values are formed by performing a ones-compliment (bit-wise inversion) and adding one. For N = 4, the mapping of values (both signed and unsigned) are mapped as follows:
Binary Octal Hexidecimal Decimal (unsigned) Decimal (signed)

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17

0 1 2 3 4 5 6 7 8 9 A B C D E F

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

0 1 2 3 4 5 6 7 -8 -7 -6 -5 -4 -3 -2 -1

Using twos-compliment arithmetic, unsigned addition and subtraction hardware can be used for signed numbers with no modification. Multiplication of signed numbers requires only minimal pre- and postprocessing to remove and re-add the signs. When using shift registers to accomplish quick multiplication and division by 2, only shifting right requires a modification to preserve the sign bit.

Losh

August 2002

When groups of N-bits form a value, the quantity is referred to as a nibble (N=4), byte (N=8), word (N=16), double word (N=32), or quad word (N=64). Hierarchically a byte is composed of a leastsignificant nibble and most-significant-order nibble, a word is composed of a least-significant byte (LSB) and a most-significant byte (MSB), and so forth. LSB and MSB can also stand for least- and mostsignificant bits.
1.2 Combinational Logic

Combinational logic devices include gates, such as AND, OR, NAND, NOR, NOT, XOR, and XNOR functions. Also included in this category are data buffers. Many useful building blocks for microprocessor design can be formed by using only combinational logic, such as decoders, multiplexers, and adders.
1.2.1 Basic Logic

1.2.1.1 Binary Valued Devices

Basic logic devices, such as AND, OR, NAND, NOR, XOR, and XNOR functions, are designed to evaluate 2 or more inputs and form a signal output. Both inputs and output are assumed to take on one of two possible logical values. Two additional devices, the inverter and buffer, operate similarly with only one input. The primary reason for adding a buffer is to increase the current drive, which is needed to handle fan-out issues when driving large numbers of devices.
1.2.1.2 Three State Devices

In some cases, it may be desirable for multiple devices to drive a single line or to control the direction of flow through along a signal path while still providing large current gains. Consider a gated unidirectional buffer and a gated bidirectional buffer shown below:
G1 X Y

A G

G2

The gated unidirectional buffer is used when multiple devices wish to drive a given line. By adding a gate, the output can be set to a high impedance state in addition to the normal high and low states. The truth table is as follows:
A G Y

1 0 X

1 1 0

1 0 hi-Z

When the output is in a high impedance state, the output is essentially an open circuit. Now consider a gated bidirectional buffer. The device is used to control the direction of data flow on a signal line while offering substantial current gain. The truth table is as follows:
G1 G2 X Y

Losh

August 2002

1 1 0 0

1 0 1 0

illegal

illegal

Input Y hi-Z

X input hi-Z

1.2.2 Decoders

A decoder is used to examine a group of bits to determine if a condition is true. If a collection of N bits is examined, such that a value A =

k =0

ak 2k , the decoder function can be expressed as a function of A.

This function will be used later to control peripherals and to address memory in the microprocessor. Consider a decoder that asserts a logical true output if A = 0x0378, where A is a 16-bit value. The decoder would then be as follows:

a15 a14 a13 a12 a11 a10 (A = 0x378) a9 a8 a7 a6 a5 a4 a3 a2 a1 a0

Losh

August 2002

Similarly, a decoder can decode a range of values as well. For example, if the decoder is designed to detect 0x0378 < A < 0x037B, the a0 and a1 terms would be dropped in the decoder above.
Note: Most standard PCs use the 0x0378 through 0x0x37B decoder to tell the parallel printer controller that data is being sent to it. 1.2.3 Multiplexers

In many cases, it may be necessary for several signals to share a common signal path. If M = 2 input lines (a0, a1, , aM-1) are multiplexed to a single output line, then N control lines (c0, c1, , cN-1) are needed to determine which of the M input lines should be output from multiplexer. If the collection of M input lines is thought of collectively, a M-bit wide input bus is formed. Similarly, if the collection of N control lines is thought of collectively, an N-bit wide control bus C is formed. Functionally, the output is aC (the Cth input). Schematically, the multiplexer appears as:

Input

Multiplexer

Output

N Control

Note: To convert M to N, use N = log2(M) = logx(M) / logx(2). 1.2.4 Adders

The addition of two N-bit numbers (X and Y) can be performed by cascading a series of full adders to form a ripple adder, as follows:

0 X0 Y0 C1 X1 Y1 Full Adder

Z0

Full Adder

Z1

C2 X2 Y2 Full Adder

Z2 C3

where the output and carry terms are generated as:


Losh 4 August 2002

Zk = (Xk XOR Yk) XOR Ck Ck+1 = (Xk AND Yk) OR [(Xk XOR Yk) AND Ck]
Note: The XOR terms and AND terms are really outputs of two half-adders that form the full adder.

The problem with this architecture is that the carry term requires 3 levels of logic. The (Xk AND Yk) and (Xk XOR Yk) terms can be computed simultaneously, followed by the [(Xk XOR Yk) AND Ck] product, followed by the evaluation of the (Xk AND Yk) OR [(Xk XOR Yk) AND Ck] sum. Assuming the propagation delay (Tp) is the same for all operations, the delay would be 3 Tp per full adder. If an 8-bit ripple adder is built, the delay would be 24 Tp. To reduce this delay at the cost of added gates and complexity, carry terms can be generated for multiple levels. For instance, the C2 carry can be generated directly from the inputs X1, Y1, X2, and Y2. While faster, this method (called partial lookahead carry generation) is more complicated that the ripple adder, but is far less complicated that a bruteforce adder, where two N-bit numbers are added to form an n+1-bit result using n+1 logic circuits each with 2N inputs. There is a significant tradeoff between delay and complexity.
1.3 Sequential Logic

Several sequential logic circuits are important for microprocessor design, including D-flip-flops, D-latches, counters, shift registers, and multipliers.
1.3.1 D-Flip Flops

The D-flip flop is a simple logic device that loads the input (D) on the transition of the clock input into an internal one-bit memory. This internal value is output as Q (and sometimes Q). For most flip flops, the trigger for this operation is the positive transition of the clock (from low to high). The schematic symbols are shown below:
D CLK
CLR

SET

D CLK

SET

CLR

Positive-edge triggered (common)

Negative-edge triggered

For the positive-edge triggered D-flip flop, the transition table is:

CLK

Q+

1 0 X X
1.3.2 D-Latches

0 1

1 0 Q Q

The D-latch is a logic device that operates in a gated- and latched-mode of operation, depending on a gate signal (G). When the gate is asserted, the input (D) is presented to the output (Q). On the deassertion of the gate, the current value of the output is latched. For most latches, the gate assertion is active low.

Losh

August 2002

D Gate

D G Q

D Q Gate

D G Q

Active-high gate

Active-low gate (common)

For the active-low gated D-latch, the transition table is:

Q+

1 0 X
1.3.3 Counters

0 0 1

1 0 Q

The modulo counter building block performs several functions: increment, decrement, clear, and load. When the load signal is asserted, the contents of an input bus (A) are loaded into the internal storage register, whose output is available at the output bus (Y). When the clear signal is asserted and the load signal is not asserted (this choice of load taking priority over clear is arbitrary), the contents of the internal registers are zeroed. When both load and clear are de-asserted, the clock and up/dn control line manipulate the internal register contents. The schematic symbols is as follows:

A
N N

LOAD CLEAR UP/DN

CLK

The transistion table for the modulo-M (M = 2 ) counter is:


LOAD CLEAR UP/DN CLK Y+

1 0 0 0
1.3.4 Shift Registers

X 1 0 0

X X 1 0

X X

A 0 (Y + 1) % M (Y - 1) % M

The shift register is a common part of a microprocessor. It is used for bit manipulations, including simple N multiplication and division by 2 . A shift register capable of shifting left or right can be constructed as follows:

Losh

August 2002

SET

Yn+1

yn+1

CLK
CLR

Q Q

LEFT/RIGHT yn-1 yn

SET

yn

CLR

Q Q
Yn-1

SET

yn-2

CLR

Six different types of shift registers are commonly used: logical shift left/right, arithmetic shift left/right, and rotate left/right. Logical shift registers are designed to manipulate unsigned numbers. The schematic for the logical shift registers are shown below:
0

Consider the unsigned number 10 = 00001010. Multiplication by 2 is equivalent to shifting left 1 position, yielding 10 << 1 = 00010100 = 20. Division by 2 is equivalent to shifting right 1 position, yielding 10 >> 1 = 00000101 = 5. Note that for the signed number 2 = 11111110, shifting right yields 01111111 = 127, which is not correct, while shift left works correctly. Arithmetic shift registers are designed to manipulate signed numbers. The schematic for the arithmetic shift registers are shown below:
0

Consider the signed number -2 = 11111110. Multiplication by 2 is equivalent to shifting left 1 position, yielding -2 << 1 = 11111100 = -4. Division by 2 is equivalent to shifting right 1 position, yielding -2 >> 1 = 11111111 = -1. The trick here is that the sign bit (most significant bit / MSB) is preserved. Rotation left and right are accomplished as follows:

Losh

August 2002

1.3.5 Multipliers

A multiplier is often created using a state machine that executes a series of shift and adds to form the product. Consider the following 3-bit x 3-bit multiplier that computes a 6-bit result as shown below:
Y 0 1 1 X 1 0 1

LOAD Y REG Y

ROT RT Y LOAD X REG X 1- x 3-bit Multiplier

3-bit Adder ZERO Z LOAD Z SHIFT RT Z REG Z

The following table illustrates the steps necessary to compute the product Z = X Y: Command LOAD X LOAD Y ZERO Z LOAD Z SHIFT RT Z ROT Y LOAD Z SHIFT RT Z ROT Y LOAD Z SHIFT RT Z ROT Y REG X+ 101 101 101 101 101 101 101 101 101 101 101 101 REG Y+ ? 011 011 011 011 101 101 101 110 110 110 011 REG Z+ ? ? 0000000 0101000 0010100 0010100 0111100 0011110 0011110 0011110 0001111 0001111 SUM+ ? ? 0101 0101 0111 0111 1100 1000 0011 0011 0001 0110

The lower 6-bits of register Z represent the output after the next to the last operation. The final ROT Y is designed to return the value of register Y to the original value. The number of clock cycles (steps) required is 3 + (3 x N) = 12. If signed numbers are input to the multiplier, then negative numbers should be negated by taking the twos-compliment. If sign(X) XOR sign(Y) = 1, the the result should be negated to form the answer.
Note: Some digital signal processors (DSPs) use flash multipliers that multiply two N-bit numbers, by brute force. All 2N outputs are functions of the 2N inputs, creating a device with nearly immediate computation of the product terms. Divide and conquer methods are also used.
Losh 8 August 2002

2 Simplified Single-bus Microprocessor


2.1 Introduction

The objective is to study basic concepts of microprocessors applicable to many different types of processors, from vendors such as AMD, Intel, Microchip, Motorola, Sun, and others. By abstracting only the set of common features, a better understanding of microprocessor operation, capabilities, and limitations can be realized.
2.2 Attributes of a Microprocessor

A microprocessor is usually compromised of one or more buses, several registers, an arithmetic logic unit (ALU), a program counter (PC), stack pointer (SP), an instruction register, and a decode and control block. For a microprocessor to be useful in a microcontroller or microcomputer, it must be connected to memory (or have it internal to the processor) and input/output (i/o) devices, such as a keyboard and a CRT controller. The buses can be viewed as roadways on which data is transferred between the components within the microprocessor, such as the registers, ALU, program counter, and stack pointer, and devices outside the microprocessor, such as memory and i/o devices. In general, several different addressing modes are provided to allow data can be transferred between a register and another register or a memory address over these buses. The registers can be thought of as quick scratch pad memory for temporarily storing results of operations. They can be contrasted from external memory by three main differences: 1. Speed - Writing and reading from internal registers can be much faster than writing and reading from external memory. 2. Size Register memory totals in the tens of bytes, whereas external memory vary from several thousand bytes in small controllers and simple processors to several billion bytes in modern desktops and servers. If a data in a word processing application (the document) is stored in external memory, not in the registers. 3. Application Many registers are dedicated to particular tasks within the processor, such as the index register, which can be likened to addressing the nth element of an array, and the stack pointer, which points to a location in memory that represents the top of a LIFO (last-in first-out) memory. The ALU is the utility player of the microprocessor. In simplest form, it is a device that takes one or two operands, performs a mathematic operation on the arguments, and outputs a result. The exact operation to perform is received from the decode and control block of the processor. The program counter (also referred to as the instruction pointer), the instruction queue, and the decode and control block control the flow of operations in the microprocessor. The processor works by performing a series of instructions that are stored in memory. The program counter is the bookmark that points to the starting location (address) in the external memory of the next instruction to be executed. At startup, the program counter is initialized to a pre-known address so that the system can boot correctly. The instruction queue contains a number of instruction bytes that are fetched from memory. The instruction bytes (op codes) of the instruction queue are decoded by the decode and control block to determine the meaning of the fetched instruction. The control portion of the block operates as a state machine and executes micro code to activate control lines connected to registers, memory, and i/o devices in a predetermined order to execute the instruction.
Losh 9 August 2002

The stack pointer is a register dedicated to providing a temporary last-in first-out memory for the program information. In general, push commands are provided that store the contents of registers on the top of the stack (at an external memory address location starting at SP), and then increment SP to prepare for storage of another value. Pop commands are provided to decrement SP and reload a register with the contents of memory starting at SP). The stack is essential to operation of the subroutine calls and returns.
Note on stack operation: In some processors, SP is decremented during PUSH operations and incremented during POP operations. 2.3 Simplified Single-bus Microprocessor

To study the operation of a simple processor, consider the 8-bit microprocessor shown in Figure 2.3-1. The microprocessor utilizes a single 8-bit bus to covey information within the microprocessor.

Losh

10

August 2002

WR_ADD_L

Address Latch L
16 8

PC L
8

WR_PC_L RD_PC_L

Address bus

Address Latch H
WR_ADD_H

PC H

WR_PC_H RD_PC_H

64kB Memory
Data bus

SP L
8

WR_SP_L RD_SP_L

Data Buffer

SP H
WR_DATA

WR_SP_H RD_SP_H

RD_DATA RD_MEM WR_MEM ALU_OP

ALU_LD_1 1 8 Argument 1
8

IDX L

WR_IDX_L RD_IDX_L

ALU_OUT_L ALU_OUT_H

ALU

IDX H

WR_IDX_H RD_IDX_H

8 Argument 2
8

ALU_LD_2

ACC L

WR_ACC_L RD_ACC_L

8 Result

ACC H

WR_ACC_H RD_ACC_H

Flag Register
CARRY, OVERFLOW, SIGN, ZERO 8

REG XL
8

WR_REGX_L RD_REGX_L

Instruction Queue (FIFO)


8 Instruction bytes

REG XH

WR_REGX_H RD_REGX_H

All RD and WR ALU_OP Buffer/Latch/ Memory Control

REG YL Instruction Decode and Control


8 Immediate data and memory addresses
8

WR_REGY_L RD_REGY_L

REG YH

WR_REGY_H RD_REGY_H

Figure 2.3-1 Simplified Single-bus 8-bit Microprocessor


Losh 11 August 2002

2.3.1 Arithmetic Logic Unit

The ALU is capable of simple mathematical operations, selectable through the ALU_OP control bus, which is driven by the control block. Simple commands include addition, subtraction, multiplication, increment/decrement (of argument 1), bit-wise AND, bit-wise OR, and bit-wise NOT operations. Operands are loaded to the ALU by the ALU_LD_1 and ALU_LD_2 lines. For all operations except multiplication, the result is an 8-bit result, readable by asserting the ALU_OUT_L line. For multiplication, the result is a 16-bit product, readable as two byte-width values via the ALU_OUT_L and ALU_OUT_H lines. The following table summarizes operations:
ALU_OP Result operand1 + operand2 operand1 operand2 operand1 operand2 operand1 BITWISE-AND operand2 operand1 BITWISE-OR operand2

add sub mul and or not inc dec

BITWISE-NOT operand1
operand1 + 1 operand1 1

Notes on flag operation: A flag (or status) register generally contains several bits, including CARRY (set if carry-out for addition or borrow-in for subtraction), OVERFLOW (change in the most-significant bit of the result), SIGN (mostsignificant bit of the result), and ZERO (last ALU operation result was zero).

2.3.2 Internal Registers

Internally, the processor has an accumulator, A, and two general purpose 16-bit registers, X and Y, which are addressable in two byte-width registers. The lower and upper registers are referred to as AL, XL, and YL and AH, XH, and YH, respectively. The program counter, stack pointer, and index register (PC, SP, and IDX) are also provided (see 2.3.4 and 2.3.5). The contents of each register are read onto the internal bus by asserting the appropriate RD_regname_L/H control line. The contents of the internal bus are written to a register by asserting the appropriate WR_regname_L/H control line.

Losh

12

August 2002

2.3.3 Memory and I/O Devices

The processor addresses 2 bytes of memory (64kB) through 16 multiplexed address lines, formed from two 8-bit address latches connected to the internal bus. The use of the WR_ADD_L and WR_ADD_H lines write data from the internal bus into the address latches. A number of address modes are available to transfer memory addressing modes are available to move data to and from the memory. The syntax and description of these modes are included in a later section. Consider the execution of the following command: MOVE [X], AL In this addressing mode, the contents of the 8-bit register AL will be written to the 16-bit memory address equal to the value of the X register. To form the address, the control block reads the contents of XL to the bus (RD_REGX_L), writes the bus data to the lower address latch (WR_ADD_L), reads the contents of XH to the bus (RD_REGX_H), and then writes the bus data to the upper address latch (WR_ADD_H). To transfer the data, the control block reads the contents of AL to the bus (RD_ACC_L), enables the buffer to write to memory (WR_DATA), and then writes the data on the bus to the memory (WR_MEM). A convenient notation, called register transfer language (RTL), can be used to represent this operation as follows: [X] AL Now consider the 16-bit version of the preceding command: MOVE [X], A Just like the 8-bit move operation above, the contents of the 16-bit X register specifies a 16-bit memory address. Unlike the 8-bit move operation involving AL, the 16-bit register, A, requires two byte memory locations to store its contents. In this case, the X register contents specify the starting address for one of the two bytes needed to store A (AH and AL). This creates an ubiquity, in that two byte memory locations X and X+1 are the destination for the contents of two byte registers, AH and AL. If the contents of AH are stored at the memory location specified by X and the contents of AL are stored at the memory location specified by X+1, this is called a big-endian operation, since the most-significant byte (MSB) of the register is stored at the lowest memory location. If the contents of AL are stored at the memory location specified by X and the contents of AH are stored at the memory location specified by X+1, this is called a little-endian operation, since the least-significant byte (LSB) of the register is stored at the lowest memory location. Shown in register transfer language (RTL) notation, the storage of A proceeds as: [X] AH and [X+1] AL (high-endian operation) [X] AL and [X+1] AH (low-endian operation)
Notes on endian-ness: - Processors such as the Intel 80x86 and AMD 6502 are low-endian processors. - Processors such as the Motorola 68000 and Sun SPARC are high-endian processors. - Some processors, such as the PowerPC, are capable of both low- and high-endian operations.

16

The 64kB memory address space must be shared between random-access memory (RAM), read-only memory (ROM), and i/o devices. Memory decoding must be added to map the memory and i/o devices into the address space. RAM is read/write memory that is normally volatile (when power is removed, the contents are lost). ROM is read-only memory that is not volatile (the contents are persistent without

Losh

13

August 2002

power). I/O devices are mapped into the address space by responding to selected ranges of addresses and performing read and write operations as if they were memory. Some small amount of ROM is always required so that the machine starts up or boots (see 1.3.8). This memory is commonly associated with the basic in/out system (BIOS) that contains code that looks for storage devices, such as hard disks, and loads programs (like an operating system) into the RAM for further execution.
Notes on memory: - Some microcontrollers and microcomputers incorporate RAM and/or ROM internal to the microprocessor, so a minimal or no additional memory is needed. - Depending on the application, the microcontroller or microcomputer may contain the entire program in ROM alleviating the need for storage devices for program storage (i.e., microwave oven controller). Notes on i/o devices: - Microcontrollers incorporate i/o ports (memory address decoders that activate data in/out latches) that minimize external components needed to handle i/o. - Instead of mapping i/o devices into the memory space, many processors add a write and read command specific to i/o that differentiates addresses for i/o devices and addresses for memory. 2.3.4 Addressing Modes and Data Flow

In the previous section, the MOVE [X], AL and MOVE [X], A commands were discussed. In general, the move instruction can be expressed as MOVE dest, source. The next sections discuss the different types of destinations and sources for the MOVE instruction. These sections are equally applicable to the ADD dest, source, SUB dest, source, AND dest, source, and OR dest, source instructions.
2.3.4.1 Register Addressing Mode

When the transfer is from a register to a register, the addressing mode is called the register addressing mode. Consider the following commands:
Instruction RTL / Comment

MOVE A, X MOVE AL, XL MOVE AL, YH MOVE AL, X MOVE A, XL

AX AL XL AL YH
illegal illegal

The only requirement is that the source and destination be of the same size (byte v. word)

Losh

14

August 2002

2.3.4.2 Immediate Addressing Mode

When the transfer is from a number stored immediately after the MOVE op code to a register, the addressing mode is called the immediate addressing mode. Consider the following commands:
Instruction RTL / Comment

MOVE A, 1234h MOVE AL, 56h MOVE XH, 78h MOVE A, 12h MOVE XL, 1234h

A 1234h AL 56h XH 78h A 0012h


illegal

It is required that the immediate value not exceed the range of the destination register.
2.3.4.3 Direct (or Extended) Addressing Mode

When the transfer is between a register and a memory address stored as part of the MOVE instruction, the addressing mode is called the direct addressing mode. This mode is also called the extended addressing mode since it uses extended bytes (second and third bytes) in the instruction to specify the address. Consider the following commands:
Instruction RTL / Comment

MOVE AL, [2000h] MOVE [2000h], AH MOVE A, [2000h] MOVE [2000h], A MOVE [2000h], [3000h]

AL [2000h] [2000h] AH A [2000h] [2000h] A


not a direct addressing mode move no memory to memory moves supported so illegal

In these commands, [z] means the contents of the memory starting at address z. For a byte-width registers, such as the first two commands, [z] refers to a single byte at memory location z. For a wordwidth registers, such as the third and fourth commands, [z] refers to a two bytes at memory locations z and z+1. As shown in 2.3.3, an ambiguity exists in the ordering of the storage of the word-length register contents into two adjacent memory locations.

Losh

15

August 2002

Consider the execution of the following commands that read from registers and write into memory:
Command Big-endian [2000h] [2001h] Little-endian [2000h] [2001h] Comments

Before MOVE A, 1234h MOVE A, 1234h MOVE XH, 56h MOVE [2000h], XH MOVE [2000h], A

00h 00h 00h 56h 12h

00h 00h 00h 00h 34h

00h 00h 00h 56h 34h

00h 00h 00h 00h 12h

Dummy values for [2000h] and [2001h] Register addressing mode does not effect memory Register addressing mode does not effect memory Address 2001h is not affected, since 2000h is address for storage of XH Addresses 2000h and 2001h are overwritten

Note that the MOVE [2000h], A instruction is considered big-endian if the MSB of A is stored in the lowest memory address and little-endian if the LSB of A is stored in the lowest memory address.

Now consider the execution of the following commands:


Command Big-endian AH AL Little-endian AH AL Comments

Before MOVE XL, 34h MOVE XL, 34h MOVE [2000h], XL MOVE XL, 12h MOVE [2001h], XL MOVE AH, [2000h] MOVE AL, [2000h] MOVE A, [2000h]

00h 00h 00h 00h 00h 34h 34h 34h

00h 00h 00h 00h 00h 00h 34h 12h

00h 00h 00h 00h 00h 34h 34h 12h

00h 00h 00h 00h 00h 00h 34h 34h

Dummy values for [2000h] and [2001h] Just initializing XL Memory location 2000h contains 34h Just initializing XL Memory location 2001h contains 12h Contents of 2000h copied to AH Contents of 2000h copied to AL Contents of 2000h and 2001h are copied to AH and AL

Note that the MOVE A, [2000h] instruction is considered big-endian if the MSB of A is loaded from the lowest memory address and little-endian if the LSB of A is loaded from the lowest memory address.

Losh

16

August 2002

2.3.4.4 Indexed Address Mode

When the transfer is between a register and a memory address specified in one or two registers, the addressing mode is called the indexed addressing mode. Consider the following commands:
Instruction RTL / Comment

MOVE AL, [X] MOVE [X], AH MOVE A, [X+IDX] MOVE [X+IDX], A

AL [X] [X] AH A [X+IDX] [X+IDX] A

In these commands, [z] means the contents of the memory starting specified by the contents of register(s) z. For a byte-width registers, such as the first two commands, [z] refers to a single byte at memory location z. For a word-width registers, such as the third and fourth commands, [z] refers to a two bytes at memory locations z and z+1. As shown in 2.3.3, an ambiguity exists in the ordering of the storage of the word-length register contents into two adjacent memory locations. Consider the execution of the following commands that read from registers and write into memory:
Command Big-endian [2000h] [2001h] Little-endian [2000h] [2001h] Comments

Before MOVE A, 1234h MOVE A, 1234h MOVE X, 2000h MOVE [X], AH MOVE [X], A

00h 00h 00h 12h 12h

00h 00h 00h 00h 34h

00h 00h 00h 12h 34h

00h 00h 00h 00h 12h

Dummy values for [2000h] and [2001h] Register addressing mode does not effect memory Register addressing mode does not effect memory Address 2001h is not affected, since 2000h is address for storage of AH Addresses 2000h and 2001h are overwritten

Note that the MOVE [X], A instruction is considered big-endian if the MSB of A is stored in the lowest memory address and little-endian if the LSB of A is stored in the lowest memory address. 2.3.5 Flow Control

At startup, the value of PC is set to a pre-set address. It is important that the memory associated with this address be located in ROM, so that the system can boot. After initialization, the processor pre-fetches instructions in an instruction queue to speed execution. Instruction execution continues in-line, unless a jump, subroutine call, or subroutine return is encountered. When a jump, call, or return is executed, the value of PC is changed and the contents of the queue are purged to fetch instruction bytes at the new location in memory.

Losh

17

August 2002

2.3.5.1 Jumps

A jump may be unconditional or conditional (sometimes called a branch since it can allow the program to continue on one of two branches, depending on a condition). Common branch conditions in most processors are related to the condition of flags, such as CARRY, OVERFLOW, SIGN, or ZERO.
2.3.5.1.1 Unconditional Jumps

When a jump is executed, the program is sent to a new location by loading the program counter with a new value. To generate the new value of PC, it may be loaded with an absolute value or adjusted with a relative offset, either positive or negative. The advantages of a relative jump is that the program can be loaded at varying memory locations in memory without the danger of absolute jump commands within a program failing. Also, a short relative jump takes only 2 bytes of memory storage v. three bytes for the absolute jump. For an absolute jump, the JUMP command can be stored in three instruction bytes as follows: JUMP absolute op code JUMP absolute op code low byte of new address high byte of new address high byte of new address low byte of new address low-endian high-endian

If it is desired to jump to address 2100h, the resulting jump command would be encoded as: JUMP absolute op code JUMP absolute op code 00h 21h 21h 00h low-endian high-endian

For a short relative jump (move PC from 128 bytes back to 127 bytes forward), the JUMP command can be stored in two instruction bytes as follows: JUMP short relative op code signed delta PC

The following code and the corresponding encoding for the short relative jump command are as follows: 2000h: JUMP 2020h 2002h: Command after jump 2020h: First command after jump occurs JUMP short relative op code 2020h 2002h = 1Eh

Notes: - The value of PC is 2002h (the starting address of the next command in-line when the jump command is executing). - The instruction address of the command after jump is 2000h + 2 = 2002h, since the JUMP short relative op code is two bytes long - The relative change needed for PC is 2020h 2002h = 1Eh

Losh

18

August 2002

For a long relative jump (move PC from 32768 bytes back to 32767 bytes forward), the JUMP command can be stored in three instruction bytes as follows: JUMP long relative op code JUMP long relative op code low byte of delta PC high byte of delta PC high byte of delta PC low byte of delta PC little-endian big-endian

The following code and the corresponding encoding for the long relative jump command are as follows: 2000h: JUMP 2200h 2003h: Command after jump 2200h: First command after jump occurs JUMP long relative op code JUMP long relative op code FDh 01h 01h FDh little-endian big-endian

Notes: - The instruction address of the command after jump is 2000h + 3 = 2003h, since the JUMP long relative op code is three bytes long - The relative change needed for PC is 2200h 2003h = 1FDh 2.3.5.1.2 Conditional Jumps

The conditional jumps are like the unconditional jumps, with the exception of the op codes. When the control/decode block examines the unconditional JUMP absolute, JUMP short relative, or JUMP far relative, it always jumps to the new address. When the control/decode block examines the conditional JUMPZ absolute, JUMPZ short relative, or JUMPZ far relative, it jumps to the new address only if corresponding flag condition is met.
Notes: Many processors do not support absolute conditional jumps. 2.3.5.2 Calls

When a subroutine is called, it is required that a return address be stored prior to calling the subroutine, so that execution can continue after the subroutine returns. This is accomplished by storing the present value of PC on the stack. If a subroutine call is encountered, such as CALL 1000h, the current value of PC, which is equal to the starting memory location of the command after CALL 1000h, is stored on the stack as follows: [SP] PCL, SP SP + 1, [SP] PCH, SP SP + 1 (little-endian) [SP] PCH, SP SP + 1, [SP] PCL, SP SP + 1 (big-endian) Execute then continues as if an absolute JUMP 1000h instruction was encountered.

Losh

19

August 2002

When a subroutine is complete, a RETURN command is executed to return program execution to a command immediately following the CALL function. The address of this return address is stored on the stack and is retrieved with the following operations: SP SP 1, PCH [SP], SP SP 1, PCL [SP] (little-endian) SP SP 1, PCL [SP], SP SP 1, PCH [SP] (big-endian) To illustrate the operation of the call and return functions, consider the following code sample and its corresponding op codes: 2000h: CALL 2200h 2003h: MOVE AL, 0 (command after return occurs) 2200h: MOVE AL, 1 (first command after call occurs) 2210h: RETURN CALL op code CALL op code 00h 22h 22h 00h little-endian big-endian

The following table summarizes the operation of the stack after each of the executed commands. The commands are listed in order of execution.
Command SP after command Big-endian [SP-1] [SP-2] Little-endian [SP-1] [SP-2] Comments

Before CALL 2200h CALL 2200h MOVE AL, 1 RETURN MOVE AL, 0

7000h 7002h 7002h 7000h 7000h

00h 03h 03h 00h 00h

00h 20h 20h 00h 00h

00h 20h 20h 00h 00h

00h 03h 03h 00h 00h

Dummy values for [SP-1] and [SP2] Value of PC is pushed on stack Operation does not effect stack Value of PC is popped from stack Operation does not effect stack

Note: [SP-2] is a lower address than [SP-1]; therefore, storage of the contents of PCH (20h) in [SP-2] and the contents of PCL (03h) in [SP-1] by the CALL 2200h command is a big-endian operation. 2.6 Op Code Encoding

To efficiently design the instruction decode block of the microprocessor, it is important to choose the optimal set of op codes for each of the instructions. There is a large group of commands that involve the ALU directly for data operations. These commands, such as MOVE, ADD, SUB, AND, and OR perform functions with similar type and format of targets and sources.

Losh

20

August 2002

We can set aside 7 different types of general functions (MOVE, ADD, SUB, ) for this processor, with the following op code assignments:
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

General function (000 110)

Transfer mode

where: - General functions are MOVE = 0, ADD = 1, SUB = 2, AND = 3, OR = 4, MUL = 5, NOT = 6 - For the multiply command, transfer modes involve a 16-bit destination (mem or one of 3 regs) and an 8-bit source (memory or one of 6 registers) = 28 permutations - For the not command, transfer modes involves one register so we can define the transfer mode as AL = 0, AH = 1, XL = 2, XH = 3, YL = 4, YH = 5, A = 6, X = 7, Y = 8, {reserved = 9-31} - For the move, add, subtract, and, and or commands, 32 transfer modes are selected from the following 50 possibilities: 30 register transfer modes: A X, A Y, AL XL, AL XH, AL YL, AL YH, AH XL, AH XH, AH YL, AH YH, X A, Y A, XL AL, XH AL, YL AL, YH AL, XL AH, XH AH, YL AH, YH AH, X Y, Y X, XL YL, YL XL, XH YH, YH XH, XL YH, YH XL, XH YL, YL XH 9 immediate addressing modes: A immed, AL immed, AH immed, X immed, XL immed, XH immed, Y immed, YL immed, YH immed, 9 direct addressing modes: A [mem], AL [mem], AH [mem], X [mem], XL [mem], XH [mem], Y [mem], YL [mem], YH [mem], 2 index addressing modes: A [X], A [X+IDX] The design goal is to allow the decode and control block to extract the lowest five bits to determine the destination and source of the instruction and to use the highest three bits to determine the function. This leaves the byte values of 111xxxxx undefined. Since a number of instructions do not need this degree of flexibility in transfer mode, they can be mapped into the following op code mask:
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

Miscellaneous function (00000-11111)

where the miscellaneous functions are JUMP abs = 0, JUMPZ abs = 1, CALL = 2, RETURN = 3, JUMP short rel = 4, JUMPZ short rel = 5, JUMP far rel = 6, JUMPZ far rel = 7, PUSH A = 8, POP A = 9, PUSH X = 10, POP X = 11, PUSH Y = 12, POP Y = 13, PUSH IDX = 14, POP IDX = 15, PUSH SP = 16, POP SP = 17, PUSH PC = 18, POP PC = 19, {reserved = 20-31} The decode block can look for an instruction byte with the value of 111xxxxx and perform the function indicated by xxxxx.

Losh

21

August 2002

2.7 Decode and Control Operations 2.7.1 Immediate Addressing and Direct Addressing Mode Interaction

During execution of instructions utilizing immediate addressing modes, the decode and control block must retrieve an 8- or a 16-bit value from the byte(s) immediately following the instruction byte that contains the instruction op code. The situation is similar in direct address mode instructions, jump, and call instructions where the address or address offset is included as part of the instruction. The following table summarizes the number of additional instruction bytes used by various instructions.
Instruction Type Example # of Additional Instruction Bytes

Immediate addressing Direct addressing JUMP or JUMPcond CALL

MOVE AL, 01h MOVE A, 3400h MOVE [2000h], AL MOVE AL, [2000h] JUMP abs or far rel JUMP short rel CALL abs

1 2 2 2 2 1 2

In the following section, the decode and control block copies these values to the bus from the instruction queue.
2.7.2 Microcode Execution

The following sections illustrate the micro code steps to perform common instructions. Please refer to Figure 2.3-1 for the names of the control lines that are asserted during execution. When interpreting the code, assume that a value written on the bus remains there until another write operation occurs.
2.7.2.1 Register Addressing Mode Operations 2.7.2.1.1 Byte Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg8, source_reg8 RTL: dest_reg8 dest_reg8 OPERATOR source_reg8 Generic micro-code: RD_dest_reg8, ALU_LD_1, RD_source_reg8, ALU_LD_2, ALU_OP = {operation}, ALU_OUT_L, WR_dest_reg8 Micro-code examples: ADD XL, YH: RD_REGX_L, ALU_LD_1, RD_REGY_H, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_REGX_L MOV AL, XL can be shortened to two steps, since no ALU operation is needed: RD_REGX_L, WR_ACC_L
2.7.2.1.2 Word Operations
Losh 22 August 2002

Form: MOVE/ADD/SUB/AND/OR dest_reg16, source_reg16 RTL: dest_reg16 dest_reg16 OPERATOR source_reg16 Micro-code examples: ADD X, Y: (XL XL + YL) RD_REGX_L, ALU_LD_1, RD_REGY_L, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_REGX_L (XH XH + YH + CARRY flag) RD_REGX_H, ALU_LD_1 if (CF set) {ALU_OP = {inc}, ALU_OUT_L, ALU_LD_1)} RD_REGY_H, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_REGX_H SUB X, Y: (XL XL - YL) RD_REGX_L, ALU_LD_1, RD_REGY_L, ALU_LD_2, ALU_OP = {sub}, ALU_OUT_L, WR_REGX_L (XH XH - YH - CARRY flag) RD_REGX_H, ALU_LD_1 if (CF set) {ALU_OP = {dec}, ALU_OUT_L, ALU_LD_1)} RD_REGY_H, ALU_LD_2, ALU_OP = {sub}, ALU_OUT_L, WR_REGX_H MOV A, X can be shortened to four operations, since no ALU operation is needed: RD_REGX_L, WR_ACC_L, RD_REGX_H, WR_ACC_H
2.7.2.1.3 Mixed Byte/Word Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg8, source_reg16 MOVE/ADD/SUB/AND/OR dest_reg16, source_reg8


illegal 2.7.2.2 Immediate Addressing Mode Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg8, byte_value MOVE/ADD/SUB/AND/OR dest_reg16, word_value RTL: dest_reg8 dest_reg8 OPERATOR byte_value dest_reg16 dest_reg16 OPERATOR word_value Move micro-code example: reg8 target: DCD places byte_value on bus, WR_reg8 reg16 target: DCD places lobyte(word_value) on bus, WR_reg8_L, DCD places hibyte(word_value) on bus, WR_reg8_H
2.7.2.3 Direct (or Extended) Addressing Mode Operations 2.7.2.3.1 Byte Operations
Losh 23 August 2002

Form: MOVE/ADD/SUB/AND/OR dest_reg8, [memory_address] MOVE/ADD/SUB/AND/OR [memory_address], source_reg8 RTL: dest_reg8 dest_reg8 OPERATOR [memory_address] [memory_address] [memory_address] OPERATOR source_reg8 Move micro-code example: MOVE [8000h], AL (address setup) DCD places 00h on bus, WR_ADD_L, DCD places 80h on bus, WR_ADD_H (data transfer) RD_ACC_L, WR_DATA, WR_MEMORY
2.7.2.3.2 Word Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg16, [memory_address] MOVE/ADD/SUB/AND/OR [memory_address], source_reg16 RTL: dest_reg16 dest_reg16 OPERATOR [memory_address] [memory_address] [memory_address] OPERATOR source_reg16

Losh

24

August 2002

Move micro-code: (generate address) DCD places lobyte(memory_address) on bus, WR_ADD_L, DCD places hibyte(memory_address) on bus, WR_ADD_H (data transfer) if write to memory: RD_source_reg16_L, WR_DATA, WR_MEMORY (little-endian) RD_source_reg16_H, WR_DATA, WR_MEMORY (big-endian) if read from memory: RD_DATA, RD_MEMORY, WR_dest_reg16_L (little-endian) RD_DATA, RD_MEMORY, WR_dest_reg16_H (big-endian) (generate address+1) DCD places lobyte(memory_address) on bus, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_ADD_L, DCD places hibyte(memory_address) on bus, if (CF set) {ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L} WR_ADD_H (data transfer) if write to memory: RD_source_reg8_H, WR_DATA, WR_MEMORY (little-endian) RD_source_reg8_L, WR_DATA, WR_MEMORY (big-endian) if read from memory: RD_MEMORY, RD_DATA, WR_dest_reg8_H (little-endian) RD_MEMORY, RD_DATA, WR_dest_reg8_L (big-endian) Little-endian micro-code example: MOVE [8000h], A (address setup for 8000h) DCD places 00h on bus, WR_ADD_L, DCD places 80h on bus, WR_ADD_H (low-byte data transfer) RD_ACC_L, WR_DATA, WR_MEMORY (address setup for 8001h) DCD places 00h on bus, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_ADD_L, DCD places 80h on bus if (CF set) {ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L} WR_ADD_H (high-byte data transfer) RD_ACC_H, WR_DATA, WR_MEMORY
2.7.2.4 Indexed/Indirect Addressing Mode Operations 2.7.2.4.1 Byte Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg8, [reg16 (+reg16)] MOVE/ADD/SUB/AND/OR [reg16 (+reg16)], source_reg8 RTL: dest_reg8 dest_reg8 OPERATOR [reg16 (+reg16)]
Losh 25 August 2002

[reg16 (+reg16)] [reg16 (+reg16)] OPERATOR source_reg8

Move micro-code (one register): (address setup) RD_reg16_L, WR_ADD_L, RD_reg16_H, WR_ADD_H if write to memory: RD_source_reg8, WR_DATA, WR_MEMORY if read from memory: RD_MEMORY, RD_DATA, WR_dest_reg8 Micro-code examples: MOVE [X], AL (address setup) RD_REGX_L, WR_ADD_L, RD_REGX_H, WR_ADD_H (data transfer) RD_ACC_L, WR_DATA, WR_MEMORY MOVE [X+IDX], AL (address setup) RD_REGX_L, ALU_LD_1, RD_IDX_L, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_ADD_L RD_REGX_H, ALU_LD_1 if (CF set) {ALU_OP = {inc}, ALU_OUT_L, ALU_LD_1} RD_IDX_H, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_ADD_H (data transfer) RD_ACC_L, WR_DATA, WR_MEMORY
2.7.2.4.2 Word Operations

Form: MOVE/ADD/SUB/AND/OR dest_reg16, [reg16 (+reg16)] MOVE/ADD/SUB/AND/OR [reg16 (+reg16)], source_reg16

Losh

26

August 2002

RTL: dest_reg16 dest_reg16 OPERATOR [reg16 (+reg16)] [reg16 (+reg16)] [reg16 (+reg16)] OPERATOR source_reg16 Move micro-code (one register): (generate address) RD_reg16_L, WR_ADD_L, RD_reg16_H, WR_ADD_H (data transfer) if write to memory: RD_source_reg8_L, WR_DATA, WR_MEMORY (little-endian) RD_source_reg8_H, WR_DATA, WR_MEMORY (big-endian) if read from memory: RD_MEMORY, RD_DATA, WR_dest_reg8_L (little-endian) RD_MEMORY, RD_DATA, WR_dest_reg8_H (big-endian) (generate address+1) RD_reg16_L, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_ADD_L, RD_reg16_H, if (CF set) {ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L} WR_ADD_H (data transfer) if write to memory: RD_source_reg8_H, WR_DATA, WR_MEMORY (little-endian) RD_source_reg8_L, WR_DATA, WR_MEMORY (big-endian) if read from memory: RD_MEMORY, RD_DATA, WR_dest_reg8_H (little-endian) RD_MEMORY, RD_DATA, WR_dest_reg8_L (big-endian) Little-endian micro-code example: ADD A, [X] (address setup for low-byte) RD_REGX_L, WR_ADD_L, RD_REGX_H, WR_ADD_H (low-byte add) RD_ACC_L, ALU_LD_1, RD_MEMORY, RD_DATA, ALU_LD_2, ALU_OP = {add}, ALU_OUT_L, WR_ACC_L (Note: that we need to handle the CF at this point, since the inc in the high-byte address will destroy the nd carry flag, so lets go ahead and precompute AH + CF and store in the 2 port of the ALU, which the increment command wont use. Admittedly, this is a little tricky. For the big-endian version, the lower address is used next, so the CF can be handled with the normal high-byte add steps.) (precompute AH + CF and store in port 2 of ALU) RD_ACC_H, ALU_LD_1, ALU_LD_2 if (CF set) {ALU_OP = {inc}, ALU_OUT_L, ALU_LD_2} (address setup for high-byte) RD_REGX_L, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_ADD_L, RD_REGX_H if (CF set) {ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L} WR_ADD_H

Losh

27

August 2002

(completion of high-byte add) RD_MEMORY, RD_DATA, ALU_LD_1, ALU_OP = {add}, ALU_OUT_L, WR_ACC_H
2.7.2.5 Misc Operations 2.7.2.5.1 Jump Operations

Form: JUMP memory_address_abs JUMP memory_address_short_rel JUMP memory_address_far_rel JUMP[Z|S|C] memory_address_abs JUMP[Z|S|C] memory_address_short_rel JUMP[Z|S|C] memory_address_far_rel RTL: if JUMP or (JUMPcondition and condition) perform one of the following: PC memory_address_abs PC PC + memory_address_short_rel PC PC + memory_address_far_rel Absolute jump micro-code example: If JUMPZ, execute only if ZERO FLAG = 1: DCD places lobyte(memory_address_abs) on bus, WR_PC_L, DCD places hibyte(memory_address_abs) on bus, WR_PC_H
2.7.2.5.2 Stack Operations

Form: PUSH reg16

Losh

28

August 2002

RTL: [SP] reg16_L, SP SP + 1, [SP] reg16_H, SP SP + 1 (little-endian) [SP] reg16_H, SP SP + 1, [SP] reg16_L, SP SP + 1 (big-endian) Form: POP reg16 RTL: SP SP 1, reg16_H [SP], SP SP - 1, reg16_L [SP] (little-endian) SP SP 1, reg16_L [SP], SP SP - 1, reg16_H [SP] (big-endian)
2.7.2.5.3 Call and Return

Form: CALL memory_address RTL: [SP] PC_L, SP SP + 1, [SP] PC_H, SP SP + 1 (little-endian) [SP] PC_H, SP SP + 1, [SP] PC_L, SP SP + 1 (big-endian) PC memory_address Form: RETURN RTL: SP SP 1, PC_H [SP], SP SP - 1, PC_L [SP] (little-endian) SP SP 1, PC_L [SP], SP SP - 1, PC_H [SP] (big-endian) Little-endian examples: CALL 1234h (address setup and data transfer saving PCL on stack) RD_SP_L, WR_ADD_L, RD_SP_H, WR_ADD_H, RD_PC_L, WR_DATA, WR_MEMORY (increment SP) RD_SP_L, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_SP_L If (CF set) {RD_SP_H, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_SP_H} (address setup and data transfer saving PCH on stack) RD_SP_L, WR_ADD_L, RD_SP_H, WR_ADD_H, RD_PC_H, WR_DATA, WR_MEMORY (increment SP) RD_SP_L, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_SP_L If (CF set) {RD_SP_H, ALU_LD_1, ALU_OP = {inc}, ALU_OUT_L, WR_SP_H} (jump) DCD places 34h on bus, WR_PC_L, DCD places 12h on bus, WR_PC_H RETURN (decrement SP) RD_SP_L, ALU_LD_1, ALU_OP = {dec}, ALU_OUT_L, WR_SP_L If (CF set) {RD_SP_H, ALU_LD_1, ALU_OP = {dec}, ALU_OUT_L, WR_SP_H} (address setup and data transfer restoring PCH from stack) RD_SP_L, WR_ADD_L, RD_SP_H, WR_ADD_H, RD_MEMORY, RD_DATA, WR_PC_H

Losh

29

August 2002

(decrement SP) RD_SP_L, ALU_LD_1, ALU_OP = {dec}, ALU_OUT_L, WR_SP_L If (CF set) {RD_SP_H, ALU_LD_1, ALU_OP = {dec}, ALU_OUT_L, WR_SP_H} (address setup and data transfer restoring PCL from stack) RD_SP_L, WR_ADD_L, RD_SP_H, WR_ADD_H, RD_MEMORY, RD_DATA, WR_PC_L

Losh

30

August 2002

Вам также может понравиться