The format for the mips instruction andi $a0, $a0, 0x9AE3
looks correct. It's an I type format opcode rs rt immediate. Why is an invalid mips instruction?
As @Peter says, if the constant is too large to fit in the immediate field, the assembler will either reject that line or translate that into multiple instructions that build some of the constant within the process of doing the operation requested.
However, for andi
the immediate field is 16 bits that are treated as unsigned, which means we get a range of 0x0000-0xFFFF, and 0x9000 is clearly within that range.
Now, if the opcode was addi
, the difference is that for addi
the same 16-bit immediate field is treated as signed, which means we get the range 0xFFFF8000-0x00007FFF, and here 0x9000 is out of that range (so the assembler will either reject that line of assembly code, or substitute with a 2 (or more) instruction sequence, since it cannot be encoded in one instruction).
As a side note, many MIPS assemblers are super friendly, and will take "sensible" instructions and operands that the processor doesn't naturally support and treat them as pseudo instructions that are instead implemented by a sequence of multiple machine code instructions. This is so prevalent in the MIPS mind set as can be evidenced by the reservation of an entire CPU register ($at
/$1
) as temporary storage for such expansions. In RISC V this has gone away, and only pseudo instructions that can reuse the target are allowed and otherwise the (human) assembly programmer has to write an appropriate code sequence (and that might involve identifying a free register). IMHO, this is a good thing, b/c the MIPS assemblers hide things that shouldn't be hidden in assembly — for example, translating some innocent looking instructions into a 3-instruction sequence, and when these occur inside a loop, with some thought, much better could have been done (if the assembly programmer had not had that "assistance" by the assembler and was alerted to consider the situation in terms of what the hardware can more directly).
Let's also note that in RISC V all immediates are sign extended, so they've also removed the different handling of immediate for andi
vs. addi
. As @Peter also notes, the RISC V immediates are smaller as well, and both of these increase the workload of programmers and compilers, but make the hardware more efficient by only needing one hardware mechanism for enlarging immediates (i.e. sign extension and no zero extension), and by making better use of encoding bits (more bits for opcodes, for greater instruction set longevity and custom instruction set expansion).