If a thirty-two bit word can represent a MIPS instruction. How can we tell if that instruction is of type R, J, or I?
I'm having a hard time understanding these concepts, I think the opcodes might be different?
Basically MIPS instructions have an opcode stored in the most significant 6 bits which specify the format of the following bits. In particular, R-type instructions always have an opcode of 000000 (with the instruction functionality then further specified by the 6 least significant bits.
MIPS Instruction Coding
Related
I've been trying to learn RISC-V coming from MIPS and initially they don't look to dissimilar, especially the instruction set. Are there any significant differences between the two? Are most of the differences in the backend?
According to Section 2.16 of Patterson, D. A., & Hennessy, J. L. (2018). Computer organization and design: The hardware/software interface. Cambridge, MA: Morgan Kaufmann Publishers. (RISC-V edition):
One of the main differences between RISC-V and MIPS is for conditional
branches other than equal or not equal. Whereas RISC-V simply provides branch
instructions to compare two registers, MIPS relies on a comparison instruction that
sets a register to 0 or 1 depending on whether the comparison is true. Programmers
then follow that comparison instruction with a branch on equal to or not equal
to zero depending on the desired outcome of the comparison. Keeping with its
minimalist philosophy, MIPS only performs less than comparisons, leaving it up to
the programmer to switch order of operands or to switch the condition being tested by the branch to get all the desired outcomes. MIPS has both signed and unsigned
versions of the set on less than instructions: slt and sltu.
When we look beyond the core instructions that are most commonly used, the
other main difference is that the full MIPS is a much larger instruction set than
RISC-V [...]
Figure 2.29 from the book shows the slight differences in instruction formats for the MIPS and the RISC-V:
One thing I want to add that is a bit more specific is that Immediate instructions with RISC-V use the upper 20 bits as compared to the upper 16 bit in MIPS.
For example in MIPS:
lui S0, 0x1234
S0 = 0x1234 0000
And in RISC-V its S0 = 0x0123 4000
I'm reading about the Instruction Decode (ID) phase in the MIPS datapath, and I've got the following quote: "Once operands are known, read the actual data (from registers) or extend the data to 32 bits (immediates)."
Can someone explain what the "extend the data to 32 bits (immediates)" part means? I know that registers all contain 32 bits, and I know what an immediate is. I just don't understand why you need to extend the immediate from 26 to 32 bits.
Thanks!
26-bit immediates are only in jump instructions, and aren't sign- or zero-extended to 32 bit, because they're not displacements to be added/subtracted.
I-type instructions with 16-bit immediates are different.
addi / addiu immediates are sign-extended (by duplicating the top/sign bit of the immediate to all higher bits).
https://en.wikipedia.org/wiki/Two%27s_complement#Sign_extension
This allows 2's complement numbers from -2^15 .. +2^15-1 to be encoded.
(0xFFFF8000 to 0x00007FFF)
ori/andi/xori boolean immediates are zero-extended (by setting all higher bits to zero)
This allows unsigned / 2's complement numbers from 0 .. 2^16-1 to be encoded.
(0x00000000 to 0x0000FFFF)
For other instructions see this instruction-set reference which breaks down each instruction showing 016 || [I15..0] for zero-extension or [I15]16 || [I15..0] for sign-extension.
This makes it possible to use 16-bit immediates as inputs to a 32-bit binary operation that only makes sense with 2 equal-width inputs. (In a simple classic MIPS pipeline, the decode stage fetches operands from registers and/or immediates. Register inputs are always going to be 32-bit, so the ALU is wired up for 32-bit inputs. Extending immediates to 32-bit means the rest of the CPU doesn't have to care whether the data came from an immediate or a register.)
Also sign-extended:
offsets in the reg+imm16 addressing mode used by lw/sw and other load/store instructions
relative branches (PC += imm16<<2)
maybe others, check the manual for instructions I didn't mention to see if they sign- or zero- extend.
You might be wondering "why does addiu sign-extend its immediate even though it's unsigned?"
Remember that there's no subiu, only addiu with a negative immediate. Being able to add or subtract numbers in the range -2^15 .. +2^15-1 is more useful than only being able to add 0 .. 2^16-1.
And usually you don't want to raise an exception on signed overflow, so normally compilers use addu / addiu even on signed integers. addu is badly named: it's not "for unsigned integers", it's just a wrapping-allowed / never-faulting version of add/addi. It sort of makes sense if you think of C, where signed overflow is undefined behaviour (and thus could use add and raise an exception in that case if the compiler wanted to implement it that way), but unsigned integers have well-defined overflow behaviour: base 2 wraparound.
On a 32-bit CPU, most of the operations you do (like adding, subtracting, dereferencing a pointer) are done with 32-bit numbers. When you have a number with fewer bits, you need to somehow decide what those other bits are going to be when you want to use that number in one of those operations. The act of deciding what those new high bits are is called "extending".
Assuming you are just doing a standard zero extension or sign extension, extending is very cheap. However, it does require some circuitry, so it makes sense that a description of the MIPS datapath would mention it.
MIPS ISA has an R type instruction, and the R instruction has an opcode field at its first 6 bits and a funct field at its last 6 bits. So why are the ISA designed like this? How about combine them into a 12-bits field?
My idea is that the three kinds of instructions share a prefix of 6-bit opcode. And for R and I types, the next 5 bits decide source register. If we combine opcode and funct for R instruction, the instruction format is not so consistent between R and I, which may make processor's design complex.
How about if combine them in 12-bits filed?
Since the opcode is the same for some operation in MIPS and if you change the funct than you can't differentiate which operation the instruction does, for example consider the following add(R,0,32) add has opcode 0 and funct 32
And also consider that and(R,0,36) and has also opcode 0 but different funct in this case 36 which means it's and AND operation.
check the MIPS Reference Sheet.
For the following entries, what instructions do they represent respectively?
Binary: 00000001110001011000100000100001
Hexadecimal: 144FFF9D
I'm completely lost on what I'm doing here - searching online has produced a bunch of results that make very little sense to me, but what I've gathered is I'm basically supposed to match up the numbers to their appropriate instructions/registers, but how exactly do I know what those are? Where can I find a comprehensive list? How do I know whether it's an R I or J format function?
The first 6 bits (it is easier to work in binary) are the opcode, from which you can determine how to interpret the rest. This site should get you started: http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
Update: Calling the first 6 bits the opcode is (to be too kind) misleading, but it is enough to tell you how to interpret the rest of the instruction; you may need to look elsewhere (typically at the end of the instruction) for the complete determination of the opcode.
There are 3 Type of MIPS Instructions:
R_type: Opcode must be 000000 (the first 6 bits) and with last 6 bits we can know what is the correct instruction
I_type
j_type
In this case, we have a R-type MIPS instruction and thus :
Opcode rs rt rd shamt funct
000000 01110 00101 10001 00000 100001
addu $s1 , $t6 , $a1
I am trying to write out MIPS binary code for machine instructions which have to do with floating-point registers. But while I can find the opcode for the floating-point instructions, I can't find out what numbers refer to which floating-point registers. My book and the Internet can tell me which number register I would use if I wanted to refer to $t1, but I can't find any information on how I would refer to $f1.
There are 32 floating point registers: $f0..$f31. But every floating point operation is done (in early MIPS processors) in separate processing unit, FPU (Floating point unit), so you can't access floating point registers with ordinary (integer) command. FPU registers for FPU commands and CPU registers for CPU commands.
There is a picture and transparent description
http://www.cim.mcgill.ca/~langer/273/12-coprocessors.pdf
All FPU commands are encoded as Coprocessor Instructions, for coprocessor 1 (CP1)
Check first and last pages of http://www.cs.sunysb.edu/~lw/spim/MIPSinstHex.pdf
Fields ft(5) fs(5) fd(5) are codes of registers (all are 5 bit wide). $f0 will be coded as 0; $f31 as 31 (dec) or 0x1f (hex). For double-register values (64-bit double format), only number of first register from register pair is recorded (only even regnumber is allowed: 0,2 ..30).
Detailed tables of opcodes are here: http://www.math.unipd.it/~sperduti/ARCHITETTURE-1/mips32.pdf (page A-73)