Contents
Previous Chapter
Next Chapter



3 CPU

eCOG1X has an advanced high speed, low power CPU with a powerful instruction set targeted at high level languages, in particular C. The CPU is capable of operating at speeds up to 70MHz. Full details of the instruction set are contained in the eCOG1 Macro Assembler User Manual.

The main features of the processor are:

3.1 Programmer's Model

Figure 2: Programmer's model

3.1.1 Memory

The CPU has a Harvard architecture, which means it has separate buses for code and data spaces. This allows the CPU to fetch instructions and access data at the same time.

The eCOG1 CPU is a 16-bit word orientated machine. The addressable data space is 64Kbytes. The addressable code space is 32Mbytes (16M x 16-bit words). Although the internal memories are small compared to the addressing range, external memories can be added to take advantage of the full addressing range. The internal memories are:

The instruction set supports addressing high and low bytes of the 16-bit data words. The data space can be viewed as either 32K (15-bit address) of 16-bit words, or 64K (16-bit address) of 8-bit bytes.

Bytes are organised in a big-endian manner within 16-bit words or 32-bit long words. The diagram below illustrates this. Big-endian means the most significant part of a data word is stored at the lower address in memory.

Figure 3: Memory organisation

The MMU allows the physical memories to be mapped into this logical address space. The MMU and physical memories are described in Section 4, Memory Management Unit.

3.1.2 Registers

The CPU contains the following registers:

AH/AL:

32-bit Accumulator or two 16-bit registers. All arithmetic and shift instructions operate on the AH/AL registers.

Y:

16 bit variable/index register, typically used as a stack pointer.

XH/X:

24-bit variable/index register, typically used as a general purpose pointer to code or data memory.

Flags:

status information for arithmetic instructions and interrupts.

BRK:

Debug register, used to implement hardware breakpoints.

PC:

24-bit program counter. Holds the address of the instruction currently being executed.

3.1.3 Pseudo-Registers

The eCOG1 C Compiler uses the concept of pseudo-registers for temporary storage of variables. This is used to supplement the limited core register resource to improve code efficiency, at the cost of a small amount of RAM. The compiler uses addresses 0xFFC0 to 0xFFFF as pseudo-registers.

To support fast context switches, the IY register is used as the base address to redirect accesses to data addresses 0xFFC0 to 0xFFFF when using direct addressing in User Mode. When an address in this range is accessed by the program (in direct addressing mode only), the actual address used is the value of the IY register plus the (signed) data address given. This is to support a separate interrupt context and many user mode contexts, and context switching takes place in Interrupt Mode. This means that a context switch does not require storing the pseudo-registers.

In User Mode, direct addressed accesses to 0xFFC0 to 0xFFFF (64 bytes) are redirected to addresses (IY - 64) to (IY - 1) respectively. The redirection does not take place for indirect or indexed addressing modes. In Interrupt Mode, these direct addressed accesses are not redirected and the literal address is used. An additional MMU translator for internal RAM is provided specifically to support this memory region in Interrupt Mode.

The assembler code that executes before the compiled C code starts is responsible for initialising the IY register. This code is provided with the CyanIDE tools as a template in the file "cstartup.asm".

3.2 Instruction Set

This section is a brief overview of the instruction set; the eCOG1 Macro Assembler User Manual contains a complete description.

Users do not write the PREFIX or MODIFY words; these are inserted automatically by the assembler.

In the descriptions below:

data

Refers to a number in a memory location.

reg

Refers to the contents of a register.

CSNZ

Arithmetic/Logic flags as described in Section 3.4.1.

Table 4: eCOG1X instruction set

Operand

Opcode

Reg

Mode

Assembler

Operation

Flags

-

0x1

-

-

LD

reg, data

reg ← data

NZ

-

0x1

-

-

LD.B

reg, data

reg[15:0] ← data[7:0] or data[15:8] − sign extended

NZ

-

0x1

-

-

LD.BU

reg, data

reg[15:0]← data[7:0] or data[15:8] - zero extended

NZ

-

0x0

01

01

LD flags,

@(<nn>,y)

flags ← @(<nn>,y)

ALL

-

0x0

01

10

LD UX,

@(<nn>,y)

UX[15:0] ← @(<nn>,y)

-

-

0x0

01

11

LD UY,

@(<nn>,y)

UY[15:0] ← @(<nn>,y)

-

-

0x0

11

10

LD XH,

@(<nn>,y)

(U==1) ? UX[23:16] : {IX[23:16], UX[23:16]}
← @(<nn>,y)

-

-

0x2

-

not-00

ST

reg, data

data ← reg

NZ

-

0x2

-

not-00

ST.B

reg, data

data[7:0] ← reg[7:0]

NZ

-

0x0

00

01

ST flags,

@(<nn>,y)

@(<nn>,y)← flags

-

-

0x0

00

10

ST UX,

@(<nn>,y)

@(<nn>,y) ← UX[15:0]

-

-

0x0

00

11

ST UY,

@(<nn>,y)

@(<nn>,y) ← UY[15:0]

-

-

0x0

10

10

ST XH,

@(<nn>,y)

@(<nn>,y) ← (U==1) ? UX[23:16]
: {IX[23:16], UX[23:16]}

-

0xEC

0x0

10

01

MOV

AL,X

AL[15:0] ← X[15:0]

-

0xED

0x0

10

01

MOV

AH,X

AH[15:0] ← X[15:0]

-

0xEE

0x0

10

01

MOV

Y,X

Y[15:0] ← X[15:0]

-

0xEF

0x0

10

01

MOV

X,Y

X[15:0] ← Y[15:0]

-

0xF0

0x0

10

01

MOV

AL,AH

AL[15:0] ← AH[15:0]

-

0xF1

0x0

10

01

MOV

AH,AL

AH[15:0] ← AL[15:0]

-

0xF2

0x0

10

01

TST

AL,flags

AL[15:0] ← flags[15:0] & AL[15:0]

-

0xF3

0x0

10

01

CLR

flags,AL

flags[15:0] ← flags[15:0] & ~AL[15:0]

CSNZ

0xF4

0x0

10

01

SET

flags,AL

flags[15:0] ← flags[15:0] | AL[15:0]

CSNZ

0xF5

0x0

10

01

MOVAX

 

XH[7:0] ← AH[7:0], X[15:0] ← AL[15:0]

-

0xF6

0x0

10

01

MOV

AH,Y

AH[15:0] ← Y[15:0]

-

0xF7

0x0

10

01

MOV

AL,Y

AL[15:0] ← Y[15:0]

-

0xF8

0x0

10

01

MOV

Y,AH

Y[15:0] ← AH[15:0]

-

0xF9

0x0

10

01

MOV

X,AH

X[15:0] ← AH[15:0]

-

0xFA

0x0

10

01

MOV

XH,AH

XH[7:0] ← AH[7:0]

-

0xFB

0x0

10

01

MOV

Y,AL

Y[15:0] ← AL[15:0]

-

0xFC

0x0

10

01

MOV

X,AL

X[15:0] ← AL[15:0]

-

0xFD

0x0

10

01

MOV

XH,AL

XH[7:0] ← AL[7:0]

-

0xFF

0x0

10

01

BC

 

for (AL; AL>0; AL--) @(Y++) ← @(X++)

-

-

0x3

-

-

ADD

reg, data

reg ← reg + data

CSNZ

-

0x4

-

-

ADDC

reg, data

reg ← reg + data + C

CSNZ

-

0x5

-

-

SUB

reg, data

reg ← reg - data

CSNZ

-

0x6

-

-

SUBC

reg, data

reg ← reg - data - C

CSNZ

-

0x7

-

-

NADD

reg, data

reg ← -reg + data

CSNZ

-

0x8

-

-

CMP

reg, data

flags ← reg - data

CSNZ

-

0x9

00

-

UMULT

data

AH:AL ← AL * data; (unsigned)

-

-

0x9

00

-

SMULT

data

AH:AL ← AL * data; (signed)

-

-

0x9

01

-

UDIV

data

AL ← AH:AL ÷ data; AH ← rem; (unsigned)

-

-

0x9

01

-

SDIV

data

AL ← AH:AL ÷ data; AH ← rem; (signed)

-

-

0x9

10

-

TST

data

flags ← data

NZ

-

0xA

00

-

ASL

data

C←[AH:AL]←0

C

-

0xA

00

-

LSL

data

C←[AH:AL]←0

C

-

0xA

01

-

ASR

data

AH[15]→[AH:AL]→C

C

-

0xA

01

-

LSR

data

0→[AH:AL]→C

C

-

0xA

10

-

ROL

data

C←[AH:AL]←C

C

-

0xA

11

-

ROR

data

C→[AH:AL]→C

C

-

0xB

-

-

OR

reg, data

reg ← reg | data

NZ

-

0xC

-

-

AND

reg, data

reg ← reg & data

NZ

-

0xD

-

-

XOR

reg, data

reg ← reg ^ data

NZ

-

0xE

00

-

BRA

addr

PC ← branch_addr

-

-

0x9

11

-

BSR

addr

X ← PC + 1; PC ← branch_addr

-

-

0xE

01

-

BLT

addr

if S = 1, PC ← branch_addr

-

-

0xE

10

-

BPL

addr

if N = 0, PC ← branch_addr

-

-

0xE

11

-

BMI

addr

if N = 1, PC ← branch_addr

-

-

0xF

00

-

BNE

addr

if Z = 0, PC ← branch_addr

-

-

0xF

01

-

BEQ

addr

if Z = 1, PC ← branch_addr

-

-

0xF

10

-

BCC

addr

if C = 0, PC ← branch_addr

-

-

0xF

11

-

BCS

addr

if C = 1, PC ← branch_addr

-

0xFE

0x0

10

01

BRXL

 

PC ← PC + X[15:0] + 1; X[15:0] sign extended.

-

-

0x0

11

01

RTI

@(<nn>,y)

PC ← {IXH, IX}; flags ← data

ALL

0x00

0x0

00

00

NOP

 

No operation

-

0x00

0x0

01

00

BRK

 

Stop for debug

-

0x00

0x0

10

00

SLEEP

 

Enter sleep mode

-

0x00

0x0

11

00

SIF

 

Perform eICE (SIF) access during instruction

-

-

0x2

-

00

PRINT

reg, data

None. Debug request for simulators.

-

not 0x00

0x0

00

00

PREFIX

operand

ARG_EXT = (ARG_EXT<<8) + operand

-

0x00

0x0

10

01

MODIFY

 

Modifier word: unsigned

-

0x01

0x0

10

01

MODIFY

 

Modifier word: signed

-

  1. Indicates UNSIGNED prefix instruction required for this instruction.
    <nn> represents the instruction operand for instructions with a specific addressing mode.

The bit field values for the Reg and Mode fields in the instruction word are shown in the following tables. These values are used for instructions that support different registers or addressing modes, when there is no specific value given in the above table.

Reg Field (Register Access Code)

reg

Reg field

AH

00

AL

01

X

10

Y

11

 

Address Mode Field

mode

Data Address Modes (word accesses): source or destination

00

Immediate

data = 16 bit sign extended operand

01

Direct

data = 16 bit value @ address ({arg16[15..1], 0})

10

Indexed X

data = 16 bit value @ address ({arg16[15..1], 0} + X)

11

Indexed Y

data = 16 bit value @ address ({arg16[15..1], 0} + Y)

mode

Data Address Modes (byte accesses): source or destination

00

unused

Not used

01

Direct

data = 8 bit value @ address (arg16)

10

Indexed X

data = 8 bit value @ address (arg16 + X)

11

Indexed Y

data = 8 bit value @ address (arg16 + Y)

mode

Branch Address Modes

00

PC relative

PC + 25 bit offset ({arg25[24..1], 0})

01

Direct

25 bit address ({XH, X, 0} + {arg25[24..1], 0})

10

X Relative

25 bit address ({XH, contents of address at {arg16[15..1], 0}, 0})

11

Indexed Y

25 bit address ({XH, contents of address at {arg16[15..1], 0} + Y, 0})

  1. {<a>, <b>} represents the bit concatenation of a and b.
    <a>[<b>..<c>] represents bits <b> to <c> inclusive of value <a>.
    arg16, arg25 represent a 16 or 25 bit sign extended operand, constructed using prefix words if required.

3.3 Processor Operating Modes

There are three aspects to the state of the processor, all of which are independent.

Processor State:

Whether the processor is awake or sleeping.

Processor Mode:

Whether the processor is handling an interrupt or not.

Program State:

Whether the program is running or stopped.
This is used for debug.

3.3.1 Processor State

This section should be read in conjunction with Section 7.4 and Section 7.6, which discuss the SSM control of sleep and wakeup in more detail.

The processor can be asleep or awake. When the processor is awake, it fetches and executes instructions as normal. When the processor is asleep, no instructions are executed. The sleep instruction puts the processor into the sleep state, provided the evening bit is asserted. If the morning bit is asserted, then the sleep instruction is interpreted as a nop and has no effect.

The processor can be woken up in two ways:

Peripheral Interrupt

eICE Wake Up command

If the processor is woken by the eICE command, then execution starts at the instruction following the sleep instruction that put the processor into sleep state.

If the processor is woken by an interrupt from a peripheral, then execution starts at the associated interrupt handler as defined by the vector table. The interrupt handler can decide whether the interrupt source should cause the processor to continue execution following the interrupt, in which case it must assert the morning bit. When the end of the interrupt service routine is reached and the rti (return from interrupt) instruction is executed, the CPU returns to and executes the original sleep instruction. If the evening bit is set, the CPU returns to the sleep state. If the morning bit is set, then the sleep is interpreted as a nop and execution continues.

The table below gives an analogy for this sequence:

Table 5: Sleep control: morning and evening bits

 

Person

eCOG1

1

In the evening a person goes to bed.

Software asserts the evening bit

2

The person goes to sleep.

Software executes the sleep instruction

3

The person wakes up as a result of something happening.

Processor starts to execute the interrupt handler

4

The person decides to go back to sleep.

Software examines the source of the interrupt, decides not to stay awake and returns from interrupt to the sleep state.

5

The person wakes up because of something happening.

Processor starts to execute the interrupt handler

6

It is morning so the person stays awake.

Software examines the source of the interrupt, decides to wake up, asserts the morning bit and returns from interrupt.

7

The person does a days work.

Processor continues execution after the sleep instruction.

 

back to the top

back to the top

3.3.2 Processor Mode

The two processor modes are interrupt mode and user mode. When the processor is in interrupt mode, no interrupts can take place. When the processor is in user mode, an interrupt from an enabled interrupt source takes the processor into interrupt mode.

Software can write to the FLAGS register to change the processor mode, which could be used to implement semaphores by only changing the value of the semaphore when the processor is in interrupt mode. The eCOG1X Macro Assembler User Manual contains details of how to implement this mechanism.

3.3.3 Program State

The program that the processor is executing can be running or stopped. The stopped state is normally used only for interactive debugging. When a product is in service, the program is always running.

In order to stop the program, eICE commands must be used to enable break events. This can be done using the CyanIDE debugger. Details of all the eICE commands are listed in Appendix F.8. When break events are enabled, the processor can be stopped in four ways:

execution of a BRK instruction

PC register equals BRK register

eICE Stop command

When the program is stopped, eICE must be used to start the program running again.

3.4 Flags

The flags register has eight bits that can be put into three groups.

Arithmetic/Logic

Interrupt

Debug

3.4.1 Arithmetic/Logic

There are four arithmetic/logic flags:

C:

Carry: Set if previous arithmetic or shift operation produced a carry.

S:

Signed: Set if the result of the previous arithmetic operation was negative.

N:

Negative: This is the MSB of the result. This bit is set if the result of the previous arithmetic operation was negative. This flag is only valid if the operation did not overflow. The LD and ST instructions also change this flag.

Z:

Zero: This bit is set if the result of the previous arithmetic operation was zero. This flag is only valid if the operation did not overflow. The LD and ST instructions also change this flag.

The Macro Assembler User Manual contains a complete description of which instructions affect these flags and how the flag value is calculated.

3.4.2 Interrupt

There are two interrupt flags:

I:

This bit is used for indication only and is asserted when a peripheral has caused an interrupt. The software does not need to do anything with this bit. Writes to this bit have no effect.

U:

When asserted the processor is in User Mode; when clear the processor is in Interrupt Mode. See Section 3.3.2, Processor Mode for a description of User and Interrupt Mode. This flag bit is cleared by an interrupt event and can be set or cleared by software.

When an interrupt occurs, the U bit is cleared and no further interrupts can take place. The interrupt handler must reassert this bit and restore the other flags when returning from an interrupt. Asserting the U bit takes the processor from Interrupt Mode to User Mode. In a similar way, users can switch to Interrupt Mode from User Mode at any time by writing '0' to this bit in the flags register. This has the effect of globally disabling interrupts. This is useful for implementing functions that must not be interrupted, such as setting and clearing semaphores.

The mode of the processor determines which set of XH, X and Y registers are accessed by the instructions. When the processor is in Interrupt Mode, instructions access the IXH, IX and IY registers. When the processor is in User Mode, instructions access the UXH, UX and UY registers.

There are some special instructions that access user mode registers in interrupt mode.

3.4.3 Debug

This advanced feature is not normally used. These flags have an effect only when eICE break events are disabled. Break events are described in Appendix F.8, eICE Commands.

These flags are not used by the eICE debugger.

There are two debug flags:

T:

When asserted, this flag causes a Debug Exception after each instruction.

B:

When asserted, this flag causes a Debug Exception when a break event occurs.

The code in the Debug Exception interrupt handler must test the values of the T and B flags to determine the cause of the interrupt.

3.5 Instruction Formats

Instructions are made up of one or more instruction words. An instruction word is either a basic instruction word, a PREFIX word or a MODIFY word.

All instruction words are 16 bits in size. Basic instructions can be prefixed with MODIFY or PREFIX words. Each of these words adds a 16-bit instruction word to the size of an instruction. The assembler is responsible for generating any MODIFY or PREFIX words, i.e. they do not have to be added to the assembler, they are implied from the instruction mnemonic and operands used.

A basic instruction contains 8 bits of signed operand, which is used to hold the literal value. If an instruction needs a literal value that is larger than 8 bits, then PREFIX word is prefixed to the basic instruction word. Each PREFIX word is 16 bits long and adds a further 8 bits of information to the literal value. The largest literal used by the instruction set is 24 bits, so a maximum of two PREFIX words may be prepended to the basic instruction word to hold literal values.

Table 6: Instruction prefix words

Literal Size

Number of PREFIX words

8 bits (-128 to 127)

0

16 bits (-32768 to 32767)

1

24 bits (-8388608 to 8388607)

2

Some instructions require a MODIFY word to be added to the basic instruction word. The MODIFY word changes the way in which the following instruction word is interpreted.

It is possible for basic instruction words to be prefixed by both a MODIFY word and up to two PREFIX words. In this case the MODIFY word precedes the PREFIX word(s) and the instruction. In the current instruction set none of the instructions that use a MODIFY instruction word need two PREFIX words.

The table below shows all possible instruction formats:

Table 7: Instruction formats

 

 

Examples

 

 

instruction

 

bra 0x10

ld ah,#0x10

smult #0x10

 

 

 

 

 

PREFIX

 

bra 0x100

ld ah,#0x100

sdiv #0x100

instruction

 

 

 

 

 

 

 

 

 

PREFIX

 

bra 0x10000

bpl 0x10000

blt 0x10000

PREFIX

 

 

 

 

instruction

 

 

 

 

 

 

 

 

 

MODIFY

 

umult #0x10

udiv #0x10

ld.b ah, @0x10

instruction

 

 

 

 

 

 

 

 

 

MODIFY

 

umult #0x100

udiv #0x100

ld.b ah, @0x1000

PREFIX

 

 

 

 

instruction

 

 

 

 

 

 

 

 

 

MODIFY

 

none in current set

 

 

PREFIX

 

 

 

 

PREFIX

 

 

 

 

instruction

 

 

 

 

3.6 Instruction Timings

In order to explain the timings of instructions, the execution of an instruction is separated into Fetch and Processing. During the Fetch, the CPU reads code memory and retrieves the instruction word. During Processing, the CPU interprets the instruction word and performs the implied processing. The processing may include the CPU making accesses to data memory.

The CPU has a single instruction prefetch, which means the CPU does Fetches and Processing in parallel. The Fetch for instruction word n+1 takes place at the same time as the Processing for instruction word n. The CPU moves onto the next pair of Fetch/Process when the previous Fetch and the Process have completed.

The diagram below illustrates two possible sequences of instructions. Execution time is measured between the points where the Processing completes.

Figure 4: Example instruction sequences

In the first sequence, the instruction fetch takes longer than the processing for most of the instructions; the result is that the processing of the previous instruction finishes before the next instruction fetch is complete. This is the case for a typical application running from internal flash memory.

The second sequence has shorter instruction fetch times that are completed within the processing time of the previous instruction. This is the case for a typical application running from internal cache.

This shows there is a significant benefit to running from cache rather than flash for the majority of instructions, but not for the slower instructions such as SMULT and UDIV.

The number of clock cycles for a particular instruction varies according to how much of the instruction fetch is overlapped with the processing time of the previous instruction.

In order to calculate the execution time of an instruction, we need to know the number of clock cycles for three stages:

Fetch

tFETCH (n)

Processing

tPROC (n)

Processing for the previous instruction

tPROC (n-1)

The execution time is:

max(0, tFETCH (n) - tPROC (n-1)) + tPROC (n)

The number of clock cycles for an instruction fetch is equal to the number of wait states on the code memory plus one.

The number of clock cycles for instruction processing depends on the type of the instruction:

  1. Each word in the instruction takes at least one clock cycle to execute.
  2. If an instruction accesses data space memory or registers, the number of wait states for the access is added. For internal data RAM this is usually zero. It is possible for accesses to peripheral registers to require wait states.
  3. If an instruction word causes a read from data space memory or registers, an extra clock cycle is added.
  4. If an instruction is an SMULT or UMULT, an extra 8 clock cycles are added.
  5. If an instruction is an SDIV or UDIV, an extra 16 clock cycles are added.
  6. If an instruction branches, an extra clock cycle is added.

The table below contains some example instruction timings. The Fetch Wait States column contains (a) 0 or (b) 1; this reflects the usual number of wait states for (a) cache and (b) flash memory when the CPU is running at 50MHz. The figures assume all data space accesses have zero wait states.

For instructions with multiple words, the Cycles to Fetch and Cycles to Process columns contain the number of clocks for each instruction word.

The number of cycles to execute an instruction is not always constant. When the Fetch time is greater than one clock cycle, the amount of overlap between Fetch and Process depends upon the Processing time of the previous instruction. For the instructions that have a Fetch of one clock cycle, the duration of the instruction is not variable. This is because the Fetch is always overlapped with the previous instruction's processing.

Table 8: Instruction cycles

Instruction

Size

Memory
Access

Fetch
Wait
States

Cycles to
Fetch

Cycles to
Process

Cycles to
Execute
Instruction

ld ah,#0x40

1

-

0

1

1

1

ld ah,#0x4000

2

-

0

1+1

1+1

2

st al, @0x40

1

W

0

1

1+1

2

st al, @0x4000

2

W

0

1+1

1+1

2

ld al, @0x40

1

R

0

1

1+2

3

ld al, @4000

2

R

0

1+1

1+2

3

 

 

 

 

 

 

 

smult #0x40

1

-

0

1

9

8

sdiv #0x40

1

-

0

1

17

17

umult #0x40

2

-

0

1+1

1+9

10

udiv #0x40

2

-

0

1+1

1+17

18

 

 

 

 

 

 

 

smult #0x4000

2

-

0

1+1

1+9

10

sdiv #0x4000

2

-

0

1+1

1+17

18

umult #0x4000

3

-

0

1+1+1

1+1+9

11

udiv #0x4000

3

-

0

1+1+1

1+1+17

19

 

 

 

 

 

 

 

ld ah,#0x40

1

-

1

2

1

1-3

ld ah,#0x4000

2

-

1

2+2

1+1

3-5

st al, @0x40

1

W

1

2

1

1-3

st al, @0x4000

2

W

1

2+2

1+1

3-5

ld al, @0x40

1

R

1

2

2

2-4

ld al, @4000

2

R

1

2+2

1+2

4-6

 

 

 

 

 

 

 

smult #0x40

1

-

1

2

9

9-11

sdiv #0x40

1

-

1

2

17

17-19

umult #0x40

2

-

1

2+2

1+9

11-13

udiv #0x40

2

-

1

2+2

1+17

19-21

 

 

 

 

 

 

 

smult #0x4000

2

-

1

2+2

1+9

11-13

sdiv #0x4000

2

-

1

2+2

1+17

19-21

umult #0x4000

3

-

1

2+2+2

1+1+9

13-15

udiv #0x4000

3

-

1

2+2+2

1+1+17

21-23

 


Contents
Previous Chapter
Next Chapter