1#include <stdio.h> 2#include <stdlib.h> 3#include <signal.h> 4#include <setjmp.h> 5 6#define MAX_ARR 24 7#define PERROR \ 8 printf("This test is testing mips32r2 instructions in fpu64 mode.\n"); 9#define FLAGS_RM_MASK 0xFFFFFFFF 10 11typedef enum { 12 CVTLS, CVTLD, ROUNDLS, ROUNDLD, 13 TRUNCLS, TRUNCLD, FLOORLS, FLOORLD, 14 CEILLS, CEILLD 15} flt_round_op_t; 16 17const char *flt_round_op_names[] = { 18 "cvt.l.s", "cvt.l.d", "round.l.s", "round.l.d", 19 "trunc.l.s", "trunc.l.d", "floor.l.s", "floor.l.d" 20 "ceil.l.s", "ceil.l.d" 21}; 22 23typedef enum { 24 TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t; 25char *round_mode_name[] = { "near", "zero", "+inf", "-inf" }; 26 27const float fs_f[] = { 28 0, 456.25, 3, -1, 29 1384.5, -7.25, 1000000000, -5786.25, 30 1752, 0.015625, 0.03125, -248562.75, 31 -45786.5, 456, 34.03125, 45786.75, 32 1752065, 107, -45667.25, -7, 33 -347856.5, 356047, -1.25, 23.0625 34}; 35 36const double fs_d[] = { 37 0, 456.25, 3, -1, 38 1384.5, -7.25, 1000000000, -5786.25, 39 1752, 0.015625, 0.03125, -24856226678933.75, 40 -45786.5, 456, 34.03125, 45786.75, 41 1752065, 107, -45667.25, -7, 42 -347856.5, 356047, -1.25, 23.0625 43}; 44 45#define UNOPsl(op) \ 46 __asm__ __volatile__( \ 47 op" $f0, %2" "\n\t" \ 48 "sdc1 $f0, 0(%1)" "\n\t" \ 49 "cfc1 %0, $31" "\n\t" \ 50 : "=r" (fcsr) \ 51 : "r"(&fd_l), "f"(fs_f[i]) \ 52 : "$f0" \ 53 ); 54 55#define UNOPdl(op) \ 56 __asm__ __volatile__( \ 57 op" $f0, %2" "\n\t" \ 58 "sdc1 $f0, 0(%1)" "\n\t" \ 59 "cfc1 %0, $31" "\n\t" \ 60 : "=r" (fcsr) \ 61 : "r"(&fd_l), "f"(fs_d[i]) \ 62 : "$f0" \ 63 ); 64 65#define TEST_FPU64 \ 66 __asm__ __volatile__( \ 67 "cvt.l.s $f0, $f0" "\n\t" \ 68 : \ 69 : \ 70 : "$f0" \ 71 ); 72 73#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64) 74void set_rounding_mode(round_mode_t mode) 75{ 76 switch(mode) { 77 case TO_NEAREST: 78 __asm__ volatile("ctc1 $zero, $31" "\n\t"); 79 break; 80 case TO_ZERO: 81 __asm__ volatile("li $t0, 0x1" "\n\t" 82 "ctc1 $t0, $31" "\n\t"); 83 break; 84 case TO_PLUS_INFINITY: 85 __asm__ volatile("li $t0, 0x2" "\n\t" 86 "ctc1 $t0, $31" "\n\t"); 87 break; 88 case TO_MINUS_INFINITY: 89 __asm__ volatile("li $t0, 0x3" "\n\t" 90 "ctc1 $t0, $31" "\n\t"); 91 break; 92 } 93} 94 95struct test { 96 void (*test)(void); 97 int sig; 98 int code; 99}; 100 101static void handler(int sig) 102{ 103 PERROR; 104 exit(0); 105} 106 107int FCSRRoundingMode(flt_round_op_t op) 108{ 109 long long int fd_l; 110 int i; 111 int fcsr = 0; 112 round_mode_t rm; 113 for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) { 114 printf("roundig mode: %s\n", round_mode_name[rm]); 115 for (i = 0; i < MAX_ARR; i++) { 116 set_rounding_mode(rm); 117 switch(op) { 118 case CVTLS: 119 UNOPsl("cvt.l.s"); 120 printf("%s %lld %f\n", 121 flt_round_op_names[op], fd_l, fs_f[i]); 122 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 123 break; 124 case CVTLD: 125 UNOPdl("cvt.l.d"); 126 printf("%s %lld %lf\n", 127 flt_round_op_names[op], fd_l, fs_d[i]); 128 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 129 break; 130 case ROUNDLS: 131 UNOPsl("round.l.s"); 132 printf("%s %lld %f\n", 133 flt_round_op_names[op], fd_l, fs_f[i]); 134 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 135 break; 136 case ROUNDLD: 137 UNOPdl("round.l.d"); 138 printf("%s %lld %lf\n", 139 flt_round_op_names[op], fd_l, fs_d[i]); 140 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 141 break; 142 case TRUNCLS: 143 UNOPsl("trunc.l.s"); 144 printf("%s %lld %f\n", 145 flt_round_op_names[op], fd_l, fs_f[i]); 146 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 147 break; 148 case TRUNCLD: 149 UNOPdl("trunc.l.d"); 150 printf("%s %lld %lf\n", 151 flt_round_op_names[op], fd_l, fs_d[i]); 152 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 153 break; 154 case FLOORLS: 155 UNOPsl("floor.l.s"); 156 printf("%s %lld %f\n", 157 flt_round_op_names[op], fd_l, fs_f[i]); 158 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 159 break; 160 case FLOORLD: 161 UNOPdl("floor.l.d"); 162 printf("%s %lld %lf\n", 163 flt_round_op_names[op], fd_l, fs_d[i]); 164 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 165 break; 166 case CEILLS: 167 UNOPsl("ceil.l.s"); 168 printf("%s %lld %f\n", 169 flt_round_op_names[op], fd_l, fs_f[i]); 170 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 171 break; 172 case CEILLD: 173 UNOPdl("ceil.l.d"); 174 printf("%s %lld %lf\n", 175 flt_round_op_names[op], fd_l, fs_d[i]); 176 printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); 177 break; 178 default: 179 printf("error\n"); 180 break; 181 } 182 } 183 } 184 return 0; 185} 186#endif 187 188 189int main() 190{ 191#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64) 192 flt_round_op_t op; 193 signal(SIGILL, handler); 194 /* Test fpu64 mode. */ 195 TEST_FPU64; 196 printf("-------------------------- %s --------------------------\n", 197 "test FPU Conversion Operations Using the FCSR Rounding Mode"); 198 for (op = CVTLS; op <= CEILLD; op++) 199 FCSRRoundingMode(op); 200#else 201 PERROR; 202#endif 203 return 0; 204} 205