proj-plbook-plChMipsDlxIsa

Difference between revision 12 and current revision

No diff available.

Table of Contents for Programming Languages: a survey

The MIPS and DLX, etc, ISAs

MIPS

MIPS is a Debian official port. Many alternate libcs support MIPS. It's also frequently discussed, eg. [1].

MIPS stands for Microprocessor without Interlocked Pipeline Stages.

" Goals of the 64bit MIPS architecture:

    Use general-purpose registers with a load-store architecture
    Support these addressing modes: displacement (with an address offset size of 12–16 bits), immediate (size 8–16 bits), and register indirect
    Support these data sizes and types: 8-, 16-, 32-, and 64-bit integers and 64-bit IEEE 754 floating-point numbers
    Support these simple instructions, since they will dominate the number of instructions executed: load, store, add, subtract, move register-register, and shift
    Compare equal, compare not equal, compare less, branch (with a PC-relative address at least 8 bits long), jump, call, and return
    Use fixed instruction encoding if interested in performance, and use variable instruction encoding if interested in code size
    Provide at least 16 general-purpose registers, be sure all addressing modes apply to all data transfer instructions
    Aim for a minimalist instruction set

MIPS addressing modes

    The data types are 8-bit bytes, 16-bit half words, 32-bit words, and 64-bit double words for integer data and 32-bit single precision and 64-bit double precision for floating point
    The only data addressing modes are immediate and displacement, both with 16-bit fields
    Register indirect is accomplished simply by placing 0 in the 16-bit displacement field
    Absolute addressing with a 16-bit field is accomplished by using register 0 as the base register
    MIPS memory is byte addressable with a 64-bit address
    Mode bit that allows software to select either Big Endian or Little Endian

" Goals of the 64bit MIPS architecture:

    Use general-purpose registers with a load-store architecture
    Support these addressing modes: displacement (with an address offset size of 12–16 bits), immediate (size 8–16 bits), and register indirect
    Support these data sizes and types: 8-, 16-, 32-, and 64-bit integers and 64-bit IEEE 754 floating-point numbers
    Support these simple instructions, since they will dominate the number of instructions executed: load, store, add, subtract, move register-register, and shift
    Compare equal, compare not equal, compare less, branch (with a PC-relative address at least 8 bits long), jump, call, and return
    Use fixed instruction encoding if interested in performance, and use variable instruction encoding if interested in code size
    Provide at least 16 general-purpose registers, be sure all addressing modes apply to all data transfer instructions
    Aim for a minimalist instruction set

Registers in MIPS

    32 64-bit general-purpose registers (GPRs), sometimes called integer registers, named R0, R1, ... , R31.
    32 floating-point registers (FPRs), named F0, F1, ... , F31, which can hold 32 single-precision (32-bit) values or 32 double-precision (64-bit) values
    When holding one single-precision number, the other half an FPR is unused
    R0 is always 0

MIPS addressing modes

    The data types are 8-bit bytes, 16-bit half words, 32-bit words, and 64-bit double words for integer data and 32-bit single precision and 64-bit double precision for floating point
    The only data addressing modes are immediate and displacement, both with 16-bit fields
    Register indirect is accomplished simply by placing 0 in the 16-bit displacement field
    Absolute addressing with a 16-bit field is accomplished by using register 0 as the base register
    MIPS memory is byte addressable with a 64-bit address
    Mode bit that allows software to select either Big Endian or Little Endian

MIPS instruction format

    2 addressing modes that are to be encoded in the opcode
    32 bit instructions (6 bit primary opcode)

MIPS operations

    4 classes of operations (loads and stores, ALU operations, branches and jumps, and floating-point operations)
    Any of the general-purpose or floating-point registers may be loaded or stored
    Loading R0 has no effect
    Single-precision floating-point numbers occupy half a floating-point register
    Conversions between single and double precision must be done explicitly
    All ALU instructions are register-register instructions (add, subtract, AND, OR, XOR, and shifts) with immediate forms provided using a 16-bit sign-extended immediate
    Flow Control:
        Compare instructions: compare two registers to see if the first is less than the second. If true, a 1 is placed in the destination register (to represent true); otherwise a 0 is placed. Also called "set" operations because they set a register
        Jump instructions are differentiated by the two ways to specify the destination address and by whether or not a link is made
        Two types of jumps: plain jump and jump and link which places the return address in
        All branches are conditional specified by instruction which may test the register source for zero or nonzero, whether it contains a data value or the result of a compare, whether it's negative or equal to another register
    Floating point:
        Instructions indicate whether there is single or double precision (.S or .D)
        MIPS64 can perform two 32-bit operations on a single 64-bit register with paired single operations (.PS)

"

"Both SPARC and MIPS share another horrid feature - delayed branches. These create a dependency between instructions, in which the branch takes effect after the next instruction, rather than immediately. When using assembly code, you have to know which instructions have a delayed effect, and what rules apply to the instruction (or, sometimes, instructions) in the "delay slot" following it. The delay slot is restricted in various ways: for instance, you can't put another delayed branch there....SPARC also has a crazy feature all of its own, the "rotating register file", which makes code incredibly hard to understand because it's very hard to follow the movement of data across function calls. On SPARC, the registers are not numbered r0 to r31, they're assigned other names like o1 and g1, and some are remapped at call/return. This legacy feature makes some big assumptions about the typical number of registers that need to be preserved across a call, and forces the programmer to remember which registers get remapped and how they are remapped. " [2]

"On PowerPC?, as on SPARC and MIPS, the mechanism for storing 32-bit immediates can only encode a 32-bit value by splitting it across two instructions: a "load high" followed by an "add". This is a pain. Sometimes the two instructions containing the value are some distance apart. Often you have to decode the address by hand, because the disassembler can't automatically recognise that it is an address. " [3]

in MIPS they have beq and bne but they replace ble etc with stuff like 'set if less than (a, b, r0); beq (r0, zero, LABEL)': http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/pseudojump.html

with variants for addressing mode and type and special registers omitted:

add and beq bne div j jal (jump and link) load mult nor xor or store slt (set to 1 if less than) sll (lsl) srl (lsr) sra (asr) sub

Mips16e [4]:

h) (Sign-Extend Byte/Halfword), ZE(BH) (Zero-extend Byte/Halfword)

DLX

DLX is MIPS for education

with variants for addressing mode and type and special registers omitted:

load, store lhi (load high immediate) mov add sub mult div and or sll (lsl) srl (lsr) sra (asr) slt (set if less than) sgt, sle, sge, sne beqz, bneq bfpg, bfpf (branch on comparison bit in the FP status register) j jal (jump and link) trap rfe (return to user code from exception) cvt (convert) LTF, GTF, LEF, GEF, EQF, NEF (compare and set comparison bit in the FP status register)

Links:

OpenRISC

open source (created in year 2000)

SPARC v8

open source (created in year 1994)

Opinions

"MIPS has branch delay slots which really are a catastrophe. It severly constrains the architectures you can use for an implementation." [5]

That said, even at my most cranky, MIPS assembly is not something I would ever inflict on someone, no matter how much they’d annoyed me. Between the lack of useful addressing modes, the inconsistent register naming (what is $t0? Depends on the assembler you’re using!), the huge number of pseudos that most MIPS assemblers make look like normal instructions but that will clobber $at, the magic of $25 in PIC modes, branch delay slots, and the exciting logic in the assembler for either letting you fill delay slots, padding them with nops, or trying to fill them from one of your instructions depending on the mode, it’s an awful experience.

I’m not really a fan of RISC-V, but RISC-V manages to copy MIPS while avoiding the most awful parts of MIPS. " -- David Chisnall

Links