Computer Architecture Lab/Winter2006/LechnerWalterStadlerTrinkl/Workplace
RISE
[edit | edit source]Design decisions
[edit | edit source]We have choose to do a RISC processor featuring a typical load/store architecture. The only powerful instructions are the load (LD) and store instructions (ST) where we focused on a single-cycle implementation. Some parts of the instructions has been inspired by the ARM architecture which has similar load/store operations. All operations can be conditional. We have chosen to use only general purpose registers where we have given the register R13 to R15 special meanings. Please not that all registers share the same location with the exception of the register R15'.
User Mode | Interrupt Mode | ||
R0 | 16 Bit Zero Register | R0 | 16 Bit Zero Register |
R1 | 16 Bit General Purpose Register | R1 | 16 Bit General Purpose Register |
R2 | 16 Bit General Purpose Register | R2 | 16 Bit General Purpose Register |
R3 | 16 Bit General Purpose Register | R3 | 16 Bit General Purpose Register |
R4 | 16 Bit General Purpose Register | R4 | 16 Bit General Purpose Register |
R5 | 16 Bit General Purpose Register | R5 | 16 Bit General Purpose Register |
R6 | 16 Bit General Purpose Register | R6 | 16 Bit General Purpose Register |
R7 | 16 Bit General Purpose Register | R7 | 16 Bit General Purpose Register |
R8 | 16 Bit General Purpose Register | R8 | 16 Bit General Purpose Register |
R9 | 16 Bit General Purpose Register | R9 | 16 Bit General Purpose Register |
R10 | 16 Bit General Purpose Register | R10 | 16 Bit General Purpose Register |
R11 | 16 Bit General Purpose Register | R11 | 16 Bit General Purpose Register |
R12 | 16 Bit General Purpose Register | R12 | 16 Bit General Purpose Register |
R13 | 16 Bit Link Register (Special - See Notes) | R13 | 16 Bit Link Register (Special - See Notes) |
R14 | 16 Bit Program Counter (Special - See Notes) | R14 | 16 Bit Program Counter (Special - See Notes) |
R15 | Status Register | R15 | Status Register |
R15' | Backup Status Register |
Register file of RISE processor
Notes: The Link Register R13 is updated with the value of the program counter PC + 2 if the Jump Subroutine instruction is executed. This effectively places the return address in the link register.
Notes SR: The Status Register is special because is contains a lot of flags. The lower byte is used to store conditionals and the high byte is used for interrupt handling (Not implemented):
Bit15 | Bit14:12 | Bit11:8 | Bit 7:4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
Disable Interrupts | Interrupt Priority Mask | - | - | Overflow | Negative | Carry | Zero |
Status Register
Pipeline stages
[edit | edit source]- Instruction fetch: Fetches instructions from program memory.
- Instruction decode and Register fetch
- Execution
- Memory Access
- Write back
Instruction decode and Argument fetch stages could probably be combined in one single stage.
Interrupt Handling (Feature)
[edit | edit source]The processor supports eight external interrupt sources INT0 to INT7. If an external interrupt pin is high the value of the interrupt source is compared with the priority level in the status register. If it is greater than or equal to the level and the global Disable Interrupt bit in the status registers is cleared an interrupt is generated.
Interrupt are only handled at the end of the currently executing instruction. If an interrupt is handled the return address is placed in the link register (LR) and the current value of the status register (SR) is copied into the backup status register (R15'). In the next step the processor loads the address stored at 0x0000 + 2*IRQ_NR into its program counter. In addition the interrupt disable flag in the status register (Bit 15) is set which disables any further interrupts.
IRQ_HANDLE: st sr, [sp] add sp, #1 st r1, [sp] add sp, #1 /* do something here touching only r1*/ sub sp, #1 ld r1, [sp] sub sp, #1 ld sr, [sp] /* Restore status register from stack. */ ldm pc, lr /* Return from ISR with mode switch (copies backup SR (R15') to SR */
Instruction set
[edit | edit source]The conditional flags
[edit | edit source]Almost all instructions support the usage of conditonals. Conditionals specify if the instruction should be executed depending on the current value of the status registers. The following conditionals are supported:
- 000b: Uncoditional:
- 001b: NZ ( Not Equal != 0 )
- 010b: Z ( Equal = 0)
- 011b: C ( Carry )
- 100b: N ( Negative < 0)
- 101b: O ( Overflow )
- 110b: Z, N (Zero or Negative)
Open Questions
[edit | edit source]These Questions are open and must be worked out:
- What about interrupt support in the feature. If an interrupt occurs it must be possible to save the processor status register and the other registers on something like a stack without corrupting the other registers.
Load Instructions
[edit | edit source]Load Immediate
[edit | edit source]The load immediate instruction loads a 8-Bit constant into the destination register. Depending upon the value of lhb (Load High Byte) the value is either stored in the high or low byte of the register. If the low byte is accessed the high byte is set to zero. Otherwise loading of small constants, which is very frequent, couldn't be done in one instruction. If the high byte is written the low byte remains unchanged.
Bit 15:13 | Bit 12 | Bit 11:8 | Bit 7:0 |
100 (Opcode) | lhb (Load High Byte) | rX (Destination Register) | imm8 (Immediate 8-Bit value) |
Format of Load Immediate instruction
Semantics: If lhb(Load High Byte) is zero the value is stored in the low byte of rX. If lhb is set the value is stored in the high byte of rX. This functions does not affect the status register. For example to load ANY 16-Bit constant the following assembler code is sufficient:
ld rX, #LO8(IMM16) ; Load low byte of IMM16 into rX. ldhb rX, #HI8(IMM16) ; Load high byte of IMM16 into rX.
Syntax: ld rX, #IMM8 to load an 8-Bit immediate into rX. ldhb rX, #IMM8 to load an 8-Bit immediate into the high byte of rX.
Load Indirect with Displacement
[edit | edit source]The Load Indirect with Displacement instruction, abbr. ld rX, rZ[rY] adds the value of rZ to the value of the register rY. The resulting address is then used to fetch the operand from memory with the result beeing stored in rX.
Bit 15:13 | Bit 12:10 | Bit 9:8 | Bit 7:4 | Bit 3:0 |
101 (Opcode) | cond (Conditional flags) | rZ (See Notes) | rX (Destination register) | rY (Base Address Register) |
Format of Load Indirect with Displacement
Notes: Only the lower 2bits of rZ are encoded in the instruction. On instruction decode the value is constructed by using the value rZ prefixed by 00b. That is valid registers value for rZ are r0:r3 = 00XX.
Semantics: The value of rZ is added to the value of rY. The resulting address is then used to fetch an operand from memory and the result is stored in rX. Depending upon cond the function is either conditional or not.
Syntax: ld{COND} rX, rZ[rY]
Load Indirect with Displacement and Mode Switch
[edit | edit source]The Load Indirect with Displacement and Mode Switch instruction works equally to the Load Indirect with Displacement instruction. But additionally this instruction copies the backup SR (R15') into the real SR. This is needed i.e. when leaving an interrupt service routine.
Bit 15:13 | Bit 12:10 | Bit 9:8 | Bit 7:4 | Bit 3:0 |
110 (Opcode) | cond (Conditional flags) | rZ (See Notes) | rX (Destination register) | rY (Base Address Register) |
Format of Load Indirect with Displacement and Mode Switch
Syntax: ldm{COND} rX, rZ[rY]
Load Indirect {with Mode Switch}
[edit | edit source]This Load Indirect function, abbr. ld{m} rX, [rY] is implemented by the Load Indirect with Displacement function by using r0 as displacement register. This functionallity is implemented into the assembler which generates a instruction for ld{m} rX, r0[rY].
Load Register Register
[edit | edit source]The Load Register with Register instruction, abbr. ld rX, rY stores the value of rY in rX.
Bit 15:11 | Bit 10:8 | Bit 7:4 | Bit 3:0 |
00001 (Opcode) | cond (Conditional flags) | rX (Destination register) | rY (Source register) |
Format of Load Register with Register
Semantics: The value of rY is copied into rX. Depending upon cond the instruction is either conditional or not.
Syntax: ld{COND} rX, rY
Note: Please note that the instruction format is the same as for the general instructions but because it is a load instruction is has been placed here.
Store instructions
[edit | edit source]Store Indirect
[edit | edit source]This Store Indirect function, abbr. st rX, [rY] is implemented by the Store Indirect with Displacement function by using r0 as displacement register. This functionallity is implemented into the assembler which generates a instruction for st rX, r0[rY].
Store Indirect with Displacement
[edit | edit source]The Store Indirect with Displacement instruction, abbr. st rX, rZ[rY] adds the value of rZ to the value of the register rZ. The resulting address is then used to store the value of rX.
Bit 15:13 | Bit 12:10 | Bit 9:8 | Bit 7:4 | Bit 3:0 |
111 (Opcode) | cond (Conditional flags) | rZ (See Notes) | rX (Source register) | rY (Base Address Register) |
Format of Store Indirect with Displacement
Notes: Only the lower 2bits of rZ are encoded in the instruction. On instruction decode the value is constructed by using the value rZ prefixed by 10b. That is valid registers value for rZ are r11:r8 = 10XX.
Semantics: The value of rZ is added to the value of rY. The resulting address is then used to store the value of rX to. Depending upon cond the function is either conditional or not.
Syntax: st{COND} rX, rZ[rY]
Other instructions
[edit | edit source]All other instructions are of the format shown below.
Bit 15:11 | Bit 10:8 | Bit 7:4 | Bit 3:0 |
0xxxx (Opcode) | cond (Conditional flags) | rX (Destination register) | rY (Source register) |
General instruction for Register-Register Operation
or
Bit 15:11 | Bit 10:8 | Bit 7:4 | Bit 3:0 |
0xxxx (Opcode) | cond (Conditional flags) | rX (Destination register) | imm4 (4 Bit Immediate) |
General instruction for Register-Immediate Operation
Arithmetic
[edit | edit source]All arithmetic instructions work on 16-bit signed values.
Assembler Syntax | Opcode | Description |
ADD{COND} rX, rY | 00010 | Add value of rY to rX, and store result in rX. |
ADD{{COND} rX, #imm4 | 00011 | Add unsigned 4-Bit value to rX. |
SUB{COND} rX, rY | 00100 | Substract value of rY from rX and store result in rX. |
SUB{COND} rX, #imm4 | 00101 | Substract unsigned 4-Bit value from in rX. |
NEG{COND} rX, rY | 00110 | Build two's complement of rY and store result in rX. |
ARS{COND} rX, rY | 00111 | Arithmetically shift right by value of rY. |
ALS{COND} rX, rY | 01000 | Arithmetically shift left by value of rY. |
Arithmetic Instructions
Notes: Arithmetic left shift instruction seems to be redundant since the produced result doesn't differ from a logical left shift. Though we think a arithmetic left shift make sense because a logical left shift wouldn't update the overflow bit in the status register.
Logical
[edit | edit source]Assembler Syntax | Opcode | Description |
AND{COND} rX, rY | 01001 | Logically and value of rY with rX and store result in rX. |
NOT{COND} rX, rY | 01010 | Negate the value of rY and store result in rX. |
EOR{COND} rX, rY | 01011 | Logically exclusive or of rY with rX and store result in rX. |
LS{COND} rX, rY | 01100 | Shift value of rX left by rY bits. |
RS{COND} rX, rY | 01101 | Shift value of rX right by rY bits. |
Logical Instructions
Program Control
[edit | edit source]Assembler Syntax | Opcode | Description |
JMP{COND} [rX] | 01110 | Jump to subroutine starting at the address provided in register rX. Return address is stored in link register. |
Subroutine instructions
Other
[edit | edit source]Assembler Syntax | Opcode | Description |
TST{COND} rX | 01111 | Test value of register rX. |
NOP | 00000 | Nop instruction |
Other Instructions
Tool Chain
[edit | edit source]We have ported the GNU binutils which include assembler, linker and other tools for our processor. You can get download our patch from here (patch-rise-1.5.gz). In addition some assembler source are available my here.
Installing the port (Users)
[edit | edit source]Download binutils 2.17 and unpack it into a directory. Switch to this directory and apply our patch and build the toolchain.
$ tar -jxf binutils-2.17.tar.bz2 $ cd binutils-2.17 $ patch -p1 < ../patch-rise-1.3 ... $ ./configure --prefix=/opt/gcc-rise --target=rise $ make && make install
Installing the port (Developers)
[edit | edit source]The port uses CGEN as a framework for building the assembler, disassembler. Non CGEN specific parts include BFD/ELF support and Autoconf/Automake stuff but changeing them is rarely necessary. First download cgen and unpack it into a directory. Then copy the subdirectory 'cgen' into the binutils directory. Finally configure must be called with --enable-cgen-main to support updating the processor description.
$ tar -jxf ../sources/cgen-20061014.tar.bz2 $ cp -Rpf src/cgen binutils-2.17 $ ./configure --prefix=/opt/gcc-rise --target=rise --enable-cgen-maint $ make && make install
Now build the toolchain to test if everything worked out okay.
Adding new opcodes
[edit | edit source]In this example we are going to add a new opcode for loading an immediate value into a register to the processor. Open the file 'cpu/rise.cpu' in an editor and add the following piece of code at the end:
(dni ldid "Load Indirect with Displacement" () "ld${cond1} $dr,$dr2[$sr]" (+ OPC_3_LD_IN_DISP cond1 dr2 dr sr ) (nop) () )
The second line is the assembler syntax and the third list is the actual encoding of the instruction. cond1, $dr, %dr2 and $sr are defined as operands in rise.cpu. OPC_3 is defined as an enum type. If you have finished updating the CPU file change to the opcode directory and call 'make stamp-rise'. This calls CGEN and rebuilds the input source files for the GNU assembler.
$ make stamp-rise ... Generating rise desc.h ... Generating rise desc.c ... Generating rise-opc.h ... Generating rise-opc.c ... Generating rise-ibld.in ... Generating rise-asm.in ... Generating rise-dis.in ... Generating rise-opinst.c ... touch stamp-rise make[1]: Leaving directory `binutils-2.17/opcodes' $
Now switch to the top-level directory and rebuild the tools. You can test the new tools without installing them by calling 'gas/as-new' and 'binutils/objdump'.
Common problems
[edit | edit source]- Changes in the BFD (e.g. archures.c) subdirectory require calling 'make headers' within this directory.
- If you get an error like .././opcodes/cgen.sh: line 96: guile: command not found during make stamp-rise you have to install guile.
Using it
[edit | edit source]You can test the port with the following assembler source code.
.text ld r5,addrlo(stack) ldhb r5,addrhi(stack) /* an absolute call. */ ld r2,addrlo(func1) ldhb r2,addrhi(func1) ld pc, r2 /* a PC relative call. */ ld r2, #( ( 1f - func2 ) & 0xFF ) ldhb r2, #( ( ( 1f - func2 ) >> 8 ) & 0xFF ) /* store return address in link register */ ld lr, #(1f + 0x02) 1: ld pc, r2[pc] nop func1: ld pc, lr func2: ld pc, lr
The source file must then be compiled by the assembler rise-as and liked with rise-ld to resolve the symbols. This is done with the following steps:
$ rise-as simple.s -o simple.o $ rise-ld simple.o -o simple
The result can then be disassembling again by calling rise-objdump.
$ ./binutils/objdump -d demo.o demo.o: file format elf32-rise Disassembly of section .text: 00000000 <func1-0x12>: 0: 85 00 ld R5,#0x0 2: 8d 00 ldhb R5,#0x0 4: 80 12 ld R0,#0x12 6: 88 00 ldhb R0,#0x0 8: 10 38 ld R7,R0 a: 80 fa ld R0,#0xfa c: 88 ff ldhb R0,#0xff e: a1 c7 ld R7,R0[R7] ... 00000012 <func1>: 12: 10 3e ld R7,R6 00000014 <func2>: 14: 10 3e ld R7,R6 $
Another demo program for testing the compiler:
.text /* an absolute call. */ ld r2,addrlo(func1) ldhb r2,addrhi(func1) jmp r2 nop nop /* a PC relative call. */ ld r2, #( ( func2 - 1f ) & 0xFF ) ldhb r2, #( ( ( func2 - 1f ) >> 8 ) & 0xFF ) /* store return address in link register */ ld lr, #(1f + 0x02) 1: ld pc, r2[pc] nop /* arithmetic test block */ func1: /* add r1 with Immediate 0x03 */ add r1,#03 ars r2,r1 neg r3,r2 /* add if r3 negative */ addn r3,r2 ars r4,r3 /* sub if r4 not zero */ subnz r4,#01 neg r4,r4 sub r2,r4 ld pc, lr /* logical test block */ func2: and r1,r2 /* not if overflow */ noto r2,r1 ld r3,#03 tst r2 /* right shift if zero or negative */ rszn r2,r3 eor r3,r2 ld r4,#64 tst r3 eorz r3,r4 ld r5,#01 ls r3,r5 ld pc, lr
Port Details
[edit | edit source]The following files have been modified for this port to work:
BFD specific parts
[edit | edit source]A BFD ELF backend is required for storing object files on the disc. In additions it handles all the low levels stuff like relocations, ...
- bfd/aclocal.m4, bfd/configure, bfd/doc/Makefile.in, bfd/Makefile.in, bfd/po/Makefile.in, bfd/config.h, bfd/targmatch.h, bfd/elf32-target.h: Autogenerated
- bfd/configure.in: Add support for or --target=rise.
- bfd/config.bfd: Add target vector
- bfd/cpu-rise.c: CPU architecture and name
- bfd/elf32-rise.c: ELF specific stuff for the architecture.
- bfd/targets.c: Architecture vector.
- bfd/Makefile.am: Add sources and dependencies for compilation.
- bfd/reloc.c: Add support for relocations (Used by high/low bytes of 16-bit addresses).
- bfd/archures.c: Architecture declaration
- bfd/bfd.h bfd/bfd-in2.h bfd/bfd-in3.h bfd/bfdver.h: autogenerated by calling make headers in BFD.
- include/elf/common.h
- include/elf/rise.h
CGEN/CPU specific parts
[edit | edit source]This defines the types of instructions and how they are encoded.
- opcodes/aclocal.m4, opcodes/configure, opcodes/configure.in, opcodes/Makefile.in, opcodes/po/Makefile.in: Autogenerated
- opcodes/Makefile.am: Add support for our target.
- opcodes/disassemble.c: Call disassemble function for our target.
- cpu/rise.cpu: CPU description - Most important file. Add new instructions here.
- cpu/rise.opc: Special handling/parsing for opcodes.
- include/dis-asm.h: Prototype for disassemble function.
- opcodes/rise-asm.c opcodes/rise-desc.c opcodes/rise-desc.h opcodes/rise-dis.c opcodes/rise-ibld.c opcodes/rise-opc.c opcodes/rise-opc.h opcodes/rise-opinst.c: Auto generated by CGEN from rise.cpu and rise.opc for our CPU.
GNU assembler specific parts
[edit | edit source]- gas/aclocal.m4, gas/configure: Autogenerated
- gas/configure.in: Add support for or --target=rise.
- gas/configure.tgt: Add the cpu and the generic target. Define the endianness and the BFD format.
- gas/Makefile.am: Add sources.
- gas/config/tc-rise.c: Special assembler handling for our target and CGEN setup.
- gas/config/tc-rise.h: Defines for our target.
GNU ld
[edit | edit source]- ld/aclocal.m4, ld/Makefile.in
- ld/configure.tgt
- ld/Makefile.am
- ld/emulparams/riseelf.sh: Generates a linker script for our target.
Other parts
[edit | edit source]- binutils/readelf.c: Support for disassembling ELF objects for our target.
- bootstrap.sh
- config.sub, configure