I'm not sure what is the range bound for the immediate in lui instruction.
When I assemble:
lui $t0,32768
It successfully went without errors.
However,
lui $t0,-32768
notified that -32768 out of range.
In MIPS the immediate in I-type instructions is always 16-bit long. That means the range will be [0, 65535] if the assembler treats it as unsigned, and [-32768, 32767] for the signed case
However what you can use in the assembly depends on the assembler
For example some assemblers like shell-storm and WeMips accept constants in [-32768, 65535] which is a mix of both 16-bit signed and unsigned, MIPS Converter only accepts hexadecimal values but WebMIPSASM accepts even huge values like 9223372036854775807 and truncate the result to 16 bits
Related
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.
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)
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
Im reviewing a problem where given a MIPS instruction, I have to write down the decimal value of the 4 fields corresponding to the opcode, rs, rt, and the function. I understand that the decimal value for rs and rt are just the decimal representations of the registers (i.e, $s0 is 16) but how could i figure out the 16 bit function code?
You can not determine that value.You need to be given that values.Each function code does different things,there are many instruction that has the same format.
Every instruction has its own opcode & function code. You can find the opcodes here, for example:
https://www.student.cs.uwaterloo.ca/~isg/res/mips/opcodes
For example, addi is 001000 in binary for the first 6 bytes (the opcode), followed by 2x5 bytes for the registers, followed by 16 bytes for the immediate value
add is 000000 (opcode), followed by 3x5 bytes for the registers, 00000 for shift amount (not used for this instruction), followed by 100000 for the function code.
When I try working on unsigned integers in MIPS, the result of every operation I do remains signed (that is, the integers are all in 2's complement), even though every operation I perform is an unsigned one: addu, multu and so fourth...
When I print numbers in the range [2^31, 2^32 - 1] I get their 'overflowed' negative value as if they were signed (I guess they are).
Though, when I try something like this:
li $v0, 1
li $a0, 2147483648 # or any bigger number
syscall
the printed number is always 2147483647 (2^31 - 1)
I'm confused... What am I missing?
PS : I haven't included my code as it isn't very readable (such is assembly code) and putting aside this problem,
seems to be working fine. If anyone feels it is necessary I shall include it right away!
From Wikipedia:
The MIPS32 Instruction Set states that the word unsigned as part of Add and Subtract instructions, is a misnomer. The difference between signed and unsigned versions of commands is not a sign extension (or lack thereof) of the operands, but controls whether a trap is executed on overflow (e.g. Add) or an overflow is ignored (Add unsigned). An immediate operand CONST to these instructions is always sign-extended.
From the MIPS Instruction Reference:
ALL arithmetic immediate values are sign-extended [...] The only difference between signed and unsigned instructions is that signed instructions can generate an overflow exception and unsigned instructions can not.
It looks to me like the real problem is the syscall that you are using to print numbers. It appears to and to always interpret what you pass as signed, and to possibly to bound as as well.