Multiply and Divide Instructions
I have learned that RV32I does not have multiplication and division. The extended RV32M has it.
mul is simpler. div is the quotient and rem is the remainder.
The instruction formats are almost the same, basically the variant is determined by the func code.
Because the product of two 32-bit numbers is 64-bit numbers, the processing of one instruction will be more complicated, so it is divided into two instructions to calculate the low and high bits. mulh gets the high 32 bits, mul gets the low 32 bits.
For a positive mul result, mulh should be all 0's. For a negative mul result, mulh should be all f's. You can check for overflow like this.
h: Both numbers are signed.
hu: Both are unsigned.
hsu: one signed and one unsigned.
Division implementation: For example, the following /3 implementation is a solution that multiplies a number approximately 1/3.
Compared with MIPS-32, using a register as the target register, its processing instructions will be more complex, resulting in poorer architectural performance and slightly slower operation.
RV32F and RV32D
Added new floating point registers.
flw fld fsw fsd: load, write (single precision, double precision).
fxxx.s: Operation instruction, which also includes square root and magnitude value comparison.
fmadd.s fmsub.d This class is usually used for some multiplication followed by addition and subtraction operations, such as matrix operations.
Add alone is more accurate than this mix because multiply-add is rounded twice, while add is only rounded once.
Mixed instructions require 4 registers, two multiply, one add, and one dest. The format is as follows:
Up is F and down is D. Replace the func part with rm.
Branching is then achieved through assignment.
feq.s, feq.d, flt.s, flt.d, fle.s, fle.d, assign 1 to true.
flt x5,f1,f2 # 如果 f1 < f2,则 x5 = 1;否则 x5 = 0
bne x5,x0,Exit # 如果 x5!= 0,则跳转到 Exit
The floating-point extension also supports some type conversions, such as fcvt .w .d is from double to signed integer.
w:signed integer
wu:unsigned integer
s:float point
d:double point
fmv is to move data into or out of registers.
Sign injection: Copy the first source operand except the sign bit to dest.
fsgnj: The sign bit of the result is the same as the sign bit of the second source operand.
fsgnjn: Negates the sign bit of the second source operand.
fsgnjx: XOR the sign bits of the two source operands.
So actually:
fmv.s rd, rs
fsgnj.s rd, rs, rs # 以上两个一样
fmv.d rd, rs
dsgnj.s rd, rs, rs # 以上两个一样
fneg.s rd, rs
fsgnjn.s rd, rs, rs # 以上两个一样
fabs.s rd,rs
fsgnjx.s rd, rs, rs # 以上两个一样,因为00 11异或都是0
fclass is a classification instruction, read and judge which of the following rs belongs to, and write the corresponding value to the lower 10 bits of rd (set one of them to 1, and all other bits to 0). Classification is useful for math library operations.