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