See MIPS Run

Dominic Sweetman

Mentioned 11

Sweetman has revised his bestselling bible for MIPS programmers, embedded systems designers, developers, and programmers who need an in-depth understanding of the architecture and specific guidance for writing software for MIPS-based systems, which are increasingly Linux-based.

More on Amazon.com

Mentioned in questions and answers.

Does anyone know of a web site where I can find a list of 32-bit MIPS instructions/opcodes, with the following features:

  • Clearly distinguishes between real opcodes and assembly-language macros
  • Describes the instruction behavior including differences depending on privilege level.
  • Indicates in which instruction set revision the instruction was introduced/revised (e.g. MIPS I, MIPS II, MIPS32, etc.)
  • Includes privileged instructions such as syscall.

I am aware of numerous web sites which document "part of" the instruction set, mostly for teaching purposes. They tend to leave out or only partially describe floating-point and privileged instructions.

In case you're wondering, I'm looking at Verilog code for a MIPS processor subset, and trying to figure out exactly to what extent it complies with the instruction sets of any real MIPS processors! Thanks for any pointers.

I can only partially answer the question: I'd recommend See MIPS Run by Dominic Sweetman, if you're not already referring to it. I have the first edition of the book, the second edition is now current.

  • table 8.2 lists each opcode and expected behavior, differentiating assembler macros and listing the instructions they decompose to. Unfortunately it does not differentiate user vs kernel mode.
  • table 8.6 lists the ISA level where each instruction was introduced, including obscure variants like the LSI MiniRISC
  • syscall is present in the table, though lacking much description

The first edition mentions the kernel. supervisor, and user privilege levels but does not discuss what operations are allowed in each. I do not know what changes were made in the second edition.

I am reading the book 'Computer Organization and Design' by Patterson and Hennessy and got interested in MIPS.

I have doubts in finding the range of a jump/branch instruction. Also in determining the number of branch/jump instructions required to get to a specific address.

Can someone provide an explanation of how this has to be calculated i.e. Considering PC at a specific address and finding the number of branch/jump instructions needed to go to a different address? For example, what if PC is at 0x10001010, what is the range of addresses of branch and jump instructions?

Or can you direct me to some online resource or book which would help me in getting a better understanding of these?

The following is all for MIPS-32.

Branch B, BEQ, BNE, etc. instructions have a 16 bit signed word offset field, allowing a branch to an address +/- 128kBytes from the current location. A jump J instruction specifies an address within the current 256MByte region specified by PC's most significant 4 bits : 26<<2 bits(this is not a relative address). To branch to an arbitrary address anywhere in the 4GB address space, use JR (jump register) which jumps to an address contained in a general purpose register.

It takes either a single branch or jump instruction, or a register load followed by a JR to jump to an arbitrary address, depending how far away the address is.

The best book for MIPS programming is still See MIPS Run. You can also find MIPS architecture reference manuals at mips.com (registration required). The most relevant document is MIPS32® Architecture for Programmers Volume II: The MIPS32® Instruction Set.

I've know 8086 Assembly and now I'm learning MIPS Assembly by reading the books MIPS Assembly Language Programming and See MIPS Run, but I never stopped to think about the coding standards/best practices of Assembly. I want to turn me in a better developer each day, then want to know this to improve myself. How can I learn more about assembly coding standards and best practices?

Best practice is a social phenomenon, depending on the society that you will be working in, so your best answer would be to read existing MIPS asm code from whatever environment you expect to interact with.

Examples that come to mind from my own world are the assembler sections of Linux kernel, the MIPS startup code from GCC or the assembler fragments of the MIPS port of glibc.

If you'll primarily be interacting with other projects, it's best to absorb and imitate the coding practices of that community.

I am working on a MIPS32 like CPU and I am wondering how the MIPS32 exception and interrupt handling works exactly. The MIPS32 Privileged Resource Architecture guide doesn't give much information. I am wondering about several things which are:

  1. What happens if there is an exception or interrupt in an exception or interrupt handler?

  2. MIPS32 has 5 hardware interrupts and 2 software interrupts in the cause register. Are the software interrupts exceptions or are exceptions just shown in the exception code value?

  3. Is there a different interrupt and exception vector?

  4. What happens if there are 2 exceptions that go off in the pipeline before it clears itself for the exception? For example there is an overflow exception followed by another exception, and an interrupt. What happens?

Links to any useful resources will be appreciated.

  1. Exception handlers should not re-enable exceptions until after they have saved EPC, SR etc.
  2. The software interrupts are exceptions.
  3. Some MIPS CPUs have been built with different interrupt and exception vectors, but this turns out not to be very useful.
  4. MIPS has precise exceptions: i.e. exceptions appear in instruction sequence and only the first exception in the pipeline will be architecturally visible.

See MIPS Run Linux is the best and most readable reference for MIPS exceptions and the MIPS PRA.

I know x86 Assembly (and have worked with FPGA etc') , Never wrote for a RISC, I have the opportunity to take a course in MIPS, but I'm busy as it is, so my question is, I know that every thing I learn is beneficial in some way, but really, how much beneficial? (I am a low level enthusiastic, but is this a must?)

(I'm aware of mips-is-it-important, but I feel that my case is slightly different as I already know some kind of Assembly)

Thanks.

One interesting thing about MIPS is that you have to manage the Translation Lookaside Buffer (TLB) manually. You don't have to do that with x86 (or most other ISAs that I've programmed). In that way it is RISCier than the other RISC CPUs. A lot of networking and storage gear has embedded MIPS cpus. A start-up I worked at in the early part of this decade did a 16 core MIPS CPU with encryption accelerators (as two of the coprocessors). That design was bought by Juniper Networks and is used in their adaptive services PIC in their routers.

So, as others have said MIPS is a pretty good example of a RISC ISA, and it is still getting plenty of design wins. I think it is useful to learn.

I found the first edition of the following book to be a good way to learn it:

http://www.amazon.com/Second-Morgan-Kaufmann-Computer-Architecture/dp/0120884216/ref=sr_1_1?ie=UTF8&s=books&qid=1237328559&sr=1-1

Long story short: I'd like to get the pointer to the current process' first level translation table on MIPS.

On x86 I get it from CR3. On ARM I use TTBR for this purpose. How to do this on MIPS (without accessing current task_struct->mm->pgd)?

Here is some elaboration on why I need it.

I have to get some info on the current process in Linux running in QEMU system emulator. My code runs on the host, as a part of QEMU. Lets assume that I know all the relevant offsets in the guest kernel structures.

When the guest is in kernel mode (if it's not a kernel thread), it is possible to get the current task_struct directly, via thread_info that is located on the kernel stack.

However, when the guest is in user mode, I have to traverse the task_struct list, comparing each task->mm->pgd (actually the appropriate physical address) to the current translation table pointer. The latter is what I'm looking for.

The PTE base address can be read from the MIPS CP0 Context register (#4).

See chapter 16 of See MIPS Run: Low-level Memory Management and the TLB.

The Background

I am a student just beginning to learn MIPS for one of my courses, and my professor is not allowing the usage of pseudo-instructions such as Load Address (la) in our code. I am wondering what an example of the correct usage of standard instructions would look like to store the address of a declared variable into a register for use later in the code.

My Solution

I have currently been attempting to use this code, though I am getting a syntax error in the lui instruction.

main:
.data
    Array:
    .space 80             #Declares that Array will hold 20 integers
.text
    lui  $s0, Array       #loads most significant bits into $s0
    ori  $s0, $s0, Array  #loads least significant bits into $s0

My Question

From what I understand, this should result in the address of Array being placed into $s0. However, as that does not seem to be the case, I'm wondering if anyone would be able to help me out on what I should be doing here.

You need to refer to a label in the data section in the lui and ori instructions. The following works for gnu assembler (as):

    .data
    Array:
    .space 80             #Declares that Array will hold 20 integers
...
.text
    lui $s0, %hi(Array)
    ori $s0, %lo(Array)
    lw  $s1, 0($s0)       # load 1st word of Array
...

The %hi and %lo directives tell the linker what is going on, so that it can put the address of the label "Array" in the machine code. (NOTE: this likely doesn't work for SPIM or MARS.)

See this question.

See MIPS Run is the canonical book on MIPS CPUs. This book explains the MIPS instruction set, CPU architecture and how they relate to MIPS Linux.

Below is the stack trace of NetBSD 5.1 kernel crash. Basic data collected from minicore is :

-------------------------------------------------------------
                       VALID MAGIC: 0xdfeedfee
--------------------------PANIC STRING-----------------------  
panic string is :cache error @ EPC 0xffffffff80359a78 

L1D_CACHE_ERROR_LOG 0

L1D_CACHE_INTERRUPT 0 

status 0x8305, cause 0x78

Stack Trace :

sys/arch/evbmips/navasota/md_dump.c:52: 803e092c :

sys/arch/evbmips/rmixl/machdep.c:1247: 8032c468 :

sys/kern/subr_prf.c:313: 802934ec :

sys/bcm/soc/miim.c:1588: 804b6be0 :

sys/bcm/soc/phy/phyreg.c:1049: 806eb6fc :

sys/bcm/soc/phy/wc40.c:9257: 808a7914 :

sys/bcm/soc/phy/wc40.c:3664: 808acbe4 :

sys/bcm/soc/phyctrl.c:1124: 804bc6ac :

sys/bcm/bcm/esw/port.c:10104: 805fbd48 <_bcm_port_link_get+0x298>:

sys/bcm/bcm/esw/bcm_elink.c:1812: 805b803c <_bcm_esw_linkscan_update+0x27bc>:

sys/bcm/bcm/esw/bcm_elink.c:3201: 805ba83c <_bcm_esw_linkscan_thread+0x35c

??:0: 8031ab9c :

This is running on MIPS. I need help on two different things here :

1) I see that MIPS is managing its cache by software. What is this architecture? Will be great if someone helps me out with few pointers. When In my attempt to understand that, I find that this may be related to cache coherence issue. (Or any hardware problem ?)

2) What should be good starting point to debug this? Want to understand on how to decode status and cause mentioned above.

You can download MIPS architecture reference manuals from Imagination here. You should get a copy of See MIPS run for user friendly explanation of how the processors work.

Your Cause register has an Excode of 30, which corresponds to CacheErr. See MIPS Run says that this is caused by an ECC or parity error in a cache, which sounds like a hardware failure.

The Status register also shows an ECC/parity error.

Try running the code on a different machine and see if it still fails.

Could someone give some scenarios, that can lead the linker into an error

not enough GOT space for local GOT entries

GOT stands for Global Offset Table. The GOT is a 128Kbyte table of pointers to external symbols. Each link unit has its own GOT, which is used to enable the link unit to access symbols in other link units. This is explained in more detail in chapter 16 of See MIPS Run.

It would appear that the code that you are attempting to link references too many (>~32k) external symbols.

I'd like to run more MIPS assembly programs. I can run the emulator (MARS) and I can run basic assembly programs. Now I have for instance this program to study, which is OK for my current level:

.data
prompt: .asciiz "\n Please Input a Value: "
bye: .asciiz "\n Bye!"
.globl main
.text

main:
   li $v0, 4
   la $a0, prompt
   syscall

   li $v0, 5
   syscall
   beqz $v0, end
   move $a0, $v0
   li $v0, 1
   syscall
   b main


end:
   li $v0, 4
   la $a0, bye
   syscall

   li $v0, 10
   syscall

I have 2 book that discuss the theory but they are more about the electronics and how CPU is contructed and not so much teach you how to write complete programs (the books I follow are Computer Organization and Design and a book in Swedish called Datorsystem and while these books describe fairly well the background and individual instruction, I need more pointer to complete programs that I can learn from modifying, some similar simple programs with basic i/o like the one above. Since many programs in the books make assumptions that are not realistic e.g. that a certain value already is in a certain register. Practicing on the program above is really good since it is a complete program. Can you help me?

All this assumes that you want to become a competent MIPS assembly programmer:

  • See MIPS Run is the canonical book on MIPS CPUs. This book explains the MIPS instruction set, CPU architecture and how they relate to MIPS Linux.

  • Get a MIPS cross compiler toolchain, like the free Mentor/CodeSourcery toolchain, use it to compile your favorite C/C++ programs into MIPS, and study the assembler output.

  • You can download and study a MIPS port of Linux from Timesys.

  • You can find a free and complete MIPS simulator here (MARS and SPIM are not complete enough for anything more than homework problems). If you want to run MIPS programs on cheap real hardware, start with OpenWrt.

I have no programming experience except the most basic ability to read some ASM operands (MIPS).

Due to a serious medical condition, I have the luxury of having 1 year of free time. I cannot work or go out much during this time so I've decided I want to learn ASM.

I am interested in hacking games; specifically GameCube (PowerPC ASM) and PlayStation (MIPS ASM).

What is the best way for someone like me to learn ASM properly?

I want to be fluent enough that I can write simple programs and it is important that I can really understand it, so I can view game's functions in a disassembler (using breakpoints and such).

I will essentially need to reverse engineer small amounts of the game that take my interest so I can hack/change/modify certain properties (completely legal of course).

This is just a hobby for me. I have no interest in getting a job in this field; my university major is completely unrelated to programming, and I can't take programming courses at my university.

If you want to understand MIPS assembler you should get a copy of See MIPS Run. This book assumes you have a reasonable knowledge of the C language. If you are not familiar with C, there are many books available. Programming in C by Stephen G. Kochan is the first useful looking on I found on Amazon, though I've never read it.

(You might find learning Python to be a bit of a side-track if your goal is to understand how a particular game works.)

I have an objdump of the crashing method. I found that the crash is due to a bad memory access. The memory address is present in the MIPS register a0. Is there a way to track on how the register got this address other than backtracking (walkthrough) the objdump step by step(a0 got it from s3 and so on).

And I have one more question.

How is paging done in kernel. There must be no concept of Virtual Address in Kernel since all of them are already in memory. This question I got since in my crash there is something called BADVA(is it BAD Virtual Address) holding a bad address.

Here is the crash report

Cpu 0
Registries dump
Status: 10000302    KERNEL EXL 
**Cause : 00803c08    TLBL**
**BadVA : fdca9b68**
PrId  : 01019378

The proximate cause of the crash is that no TLB entry matches the virtual address in BadVA, and that this happened while the CPU is in exception mode.

The BadVA address (fdca9b68) is in the KSEG2 region of the virtual address space. This region is used for mapped addresses in the MIPS Linux Kernel (typically used for Kernel Modules). I would suspect a bug in a kernel module.

If you want to understand what is going on in a MIPS CPU you should buy and study See MIPS Run.