Community
cancel
Showing results for 
Search instead for 
Did you mean: 

Custom Instructions

Custom Instructions

Altera's Documentation

Altera's Nios II Custom Instruction User Guide describes adding custom instructions to a Nios II processor and using them in C and assembly language programs.

You may call the custom instruction build-in functions for C in your apps. Please check the appendix B of this user guide.

int __builtin_custom_in (int n);

int __builtin_custom_ini (int n, int dataa);

GCC and Custom Floating-Point Instructions

The Nios II processor doesn't have an FPU, but you can direct the nios2-elf-gcc compiler to generate custom instructions in place of library calls for most floating-point operations.

Single Precision

Example

Let's say that your hardware engineer has regenerated your system's Nios II processor to include a custom instruction that converts an integer into a float. He has made N, the 8-bit value that selects the custom instruction, equal to 42. When you compile your C code, add the the command-line option -mcustom-floatis=42 . Then when converting an int into a float, instead of GCC generating this Nios II assembly code

call __floatsisf

it will generate code like

custom 42, r4, r4, zero

which will execute much faster.

GCC Options

Here is a table of single-precision -mcustom-* options. Be aware that if you provide some functions (sin, cos, tan, atan, exp, log), GCC will require you to provide a second option before it will use these more complex hardware operations. The second option is

-funsafe-math-optimizations

This option is GCC's way of saying, "I can't imagine that your transcendental floating-point hardware is IEEE compliant, and I want you to admit this before I'll use it." The option is not required for the other operations. You'll be happy to know that nios2-elf-gcc reports a warning asking for this second option when it's been omitted but it's needed.

Double Precision

It also is possible for nios2-elf-gcc to support double-precision floating-point custom instructions, but the implementation is less straightforward.

X and Y Registers

The nios2-elf-gcc compiler stores double-precision floating-point variables in pairs of general-purpose registers. Since custom instructions are limited to accessing 64 bits of operands and returning 32 bits of result, double-precision floating-point operations must be provided by groups of cooperating custom instructions, which retrieve the necessary 128 bits of operands, perform the necessary operation, and return 64 bits of result. The nios2-elf-gcc compiler assumes that if your hardware engineer provides any double-precision floating-point custom instructions, he also will provide and use internal registers X and Y, as described below.

Note: X and Y refer to internal registers of the custom-instruction logic. They are not part of the Nios II ABI.

X is a 64-bit register, and Y is a 32-bit register. Both of these registers are exposed to the compiler, to any exception handler that uses double-precision floating point, and to any OS that switches context among threads that use double-precision floating point. In all but the first case, you must modify the exception handler or the OS to save and restore the contents of X and Y when necessary.

To support these X and Y registers, a custom double-precision floating-point unit must provide the following five data-movement operations as custom instructions.

-mcustom-fwrx=N:

custom N, zero, src1, src2 /* X = (src2:src1) */

Writes the 64-bit register X with the contents of general-purpose registers src1 and src2 by copying src1 into the least significant half of X and src2 into the most significant half of X.

-mcustom-fwry=N:

custom N, zero, src1, zero /* Y = src1 */

Writes the 32-bit register Y with the contents of general-purpose register src1.

-mcustom-frdxlo=N:

custom N, dest, zero, zero /* dest = X[31:0] */

Reads the least significant half of X, storing it into general-purpose register dest.

-mcustom-frdxhi=N:

custom N, dest, zero, zero /* dest = X[63:32] */

Reads the most significant half of X, storing it into general purpose register dest.

-mcustom-frdy=N:

custom N, dest, zero, zero /* dest = Y */

Reads register Y, storing it into general-purpose register dest.

Example

To do this double-precision floating-point multiply using the registers indicated:

r3:r2 = r5:r4 * r7:r6

The Nios II compiler generates custom instructions for these operations (this isn't legal Nios II assembly language; the opcodes are just representative of the required custom instructions):

fwrx r4, r5 /* Write register X with (r5:r4) */

fmuld r3, r6, r7 /* Multiply, storing half of the result in r3: (r3:Y) = X * r7:r6 */

frdy r2 /* Store the other half of the result in r2: r2 = Y */

The Nios II compiler does not generate fwry, frdxlo, and frdxhi operations, but these operations must be provided so that exception handling and thread code can work correctly. (Consider the case of a context switch that occurs between the fmuld and the frdyin the example.)

GCC Options

Here is a table of double-precision -mcustom-* options. The custom instructions fwrx and frdy are required. The custom essay instructions fwry, frdxlo, and frdxhi are required for context hosting switching (saving and restoring X and Y registers). Just as with single-precision transcendental operations, double-precision transcendental operations will require the option

-funsafe-math-optimizations

Implementations

There are a few FPGA implementations of the floating-point units described here:

Version history
Revision #:
2 of 2
Last update:
‎11-18-2020 02:59 PM
Updated by: