rd, rs, offrd = pc + 4; goto rs + offjalr is a cousin of jal, and the r at the end means register. Both jump and leave a return-address breadcrumb behind (the jal page explains that mechanism). The difference is where they jump *to*. jal jumps to a fixed label decided when you write the program. jalr jumps to an address held in a register — a destination that can be computed while the program runs.
That distinction matters more than it first appears. A fixed jump is like going to a friend's house whose address you already know; a jalr jump is like going to whatever address is written on a card you are handed at runtime. This is what makes returning from a function possible: the caller left a return address in the ra register, and the function gets back by doing a jalr to whatever address ra now contains. In fact the everyday ret instruction is exactly a jalr to ra.
The same ability powers anything where the destination is not known in advance: calling a function whose address was passed in, or picking one of many routines from a table of addresses (the way a big switch statement or an interpreter dispatches).
The form is jalr rd, rs, offset: jump to the address in register rs (optionally plus a small offset), saving the return address into rd. As with jal, the link register it writes gets overwritten, so the same care about preserving ra applies.