1 /* $OpenBSD: goodfreg.c,v 1.2 2003/07/12 04:23:16 jason Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <sys/types.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <err.h> 32 #include "fpregs.h" 33 34 struct fpquad { 35 u_int32_t x1; 36 u_int32_t x2; 37 u_int32_t x3; 38 u_int32_t x4; 39 }; 40 41 void asm_ldq_f0(struct fpquad *); 42 void asm_ldq_f4(struct fpquad *); 43 void asm_ldq_f8(struct fpquad *); 44 void asm_ldq_f12(struct fpquad *); 45 void asm_ldq_f16(struct fpquad *); 46 void asm_ldq_f20(struct fpquad *); 47 void asm_ldq_f24(struct fpquad *); 48 void asm_ldq_f28(struct fpquad *); 49 void asm_ldq_f32(struct fpquad *); 50 void asm_ldq_f36(struct fpquad *); 51 void asm_ldq_f40(struct fpquad *); 52 void asm_ldq_f44(struct fpquad *); 53 void asm_ldq_f48(struct fpquad *); 54 void asm_ldq_f52(struct fpquad *); 55 void asm_ldq_f56(struct fpquad *); 56 void asm_ldq_f60(struct fpquad *); 57 58 void asm_stq_f0(struct fpquad *); 59 void asm_stq_f4(struct fpquad *); 60 void asm_stq_f8(struct fpquad *); 61 void asm_stq_f12(struct fpquad *); 62 void asm_stq_f16(struct fpquad *); 63 void asm_stq_f20(struct fpquad *); 64 void asm_stq_f24(struct fpquad *); 65 void asm_stq_f28(struct fpquad *); 66 void asm_stq_f32(struct fpquad *); 67 void asm_stq_f36(struct fpquad *); 68 void asm_stq_f40(struct fpquad *); 69 void asm_stq_f44(struct fpquad *); 70 void asm_stq_f48(struct fpquad *); 71 void asm_stq_f52(struct fpquad *); 72 void asm_stq_f56(struct fpquad *); 73 void asm_stq_f60(struct fpquad *); 74 75 int compare_regs(union fpregs *, union fpregs *); 76 void dump_reg(union fpregs *); 77 void dump_regs(union fpregs *, union fpregs *, union fpregs *); 78 int compare_quads(struct fpquad *, struct fpquad *); 79 void check_saves(union fpregs *, union fpregs *, union fpregs *); 80 void c_stq(union fpregs *, int, struct fpquad *); 81 void c_ldq(union fpregs *, int, struct fpquad *); 82 void asm_ldq(int, struct fpquad *); 83 void asm_stq(int, struct fpquad *); 84 void check_reg(int, union fpregs *, union fpregs *, union fpregs *); 85 void check_regs(union fpregs *, union fpregs *, union fpregs *); 86 int main(void); 87 88 int 89 compare_regs(union fpregs *fr1, union fpregs *fr2) 90 { 91 return (memcmp(fr1, fr2, sizeof(*fr2))); 92 } 93 94 void 95 dump_reg(union fpregs *fr) 96 { 97 int i; 98 99 for (i = 0; i < 64; i++) { 100 if ((i & 3) == 0) 101 printf("f%-2d:", i); 102 printf(" %08x", fr->f_reg32[i]); 103 if ((i & 3) == 3) 104 printf("\n"); 105 } 106 } 107 108 void 109 dump_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 110 { 111 printf("BEFORE ASM\n"); 112 dump_reg(fr1); 113 printf("AFTER ASM\n"); 114 dump_reg(fr2); 115 printf("MANUAL\n"); 116 dump_reg(fr3); 117 } 118 119 int 120 compare_quads(struct fpquad *q1, struct fpquad *q2) 121 { 122 return (memcmp(q1, q2, sizeof(*q2))); 123 } 124 125 /* 126 * Verify that savefpregs, loadfpregs, and initfpregs actually seem to work. 127 */ 128 void 129 check_saves(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 130 { 131 memset(fr1, 0x55, sizeof(*fr1)); 132 memset(fr2, 0x55, sizeof(*fr2)); 133 memset(fr3, 0x55, sizeof(*fr3)); 134 loadfpregs(fr1); 135 if (compare_regs(fr1, fr2)) 136 errx(1, "check_saves: loadfpregs1 differs"); 137 138 savefpregs(fr2); 139 if (compare_regs(fr1, fr2) || compare_regs(fr2, fr3)) 140 errx(1, "check_saves: savefpregs1 differs"); 141 142 memset(fr1, 0xaa, sizeof(*fr1)); 143 memset(fr2, 0xaa, sizeof(*fr2)); 144 memset(fr3, 0xaa, sizeof(*fr3)); 145 loadfpregs(fr1); 146 if (compare_regs(fr1, fr2)) 147 errx(1, "check_saves: loadfpregs2 differs"); 148 149 savefpregs(fr2); 150 if (compare_regs(fr1, fr2) || compare_regs(fr2, fr3)) 151 errx(1, "check_saves: savefpregs2 differs"); 152 153 memset(fr1, 0xff, sizeof(*fr1)); 154 initfpregs(fr2); 155 if (compare_regs(fr1, fr2)) 156 errx(1, "check_saves: initfpregs differs"); 157 } 158 159 void 160 c_stq(union fpregs *frp, int freg, struct fpquad *q) 161 { 162 q->x1 = frp->f_reg32[freg]; 163 q->x2 = frp->f_reg32[freg + 1]; 164 q->x3 = frp->f_reg32[freg + 2]; 165 q->x4 = frp->f_reg32[freg + 3]; 166 } 167 168 void 169 c_ldq(union fpregs *frp, int freg, struct fpquad *q) 170 { 171 frp->f_reg32[freg] = q->x1; 172 frp->f_reg32[freg + 1] = q->x2; 173 frp->f_reg32[freg + 2] = q->x3; 174 frp->f_reg32[freg + 3] = q->x4; 175 } 176 177 void 178 asm_ldq(int freg, struct fpquad *q) 179 { 180 switch (freg) { 181 case 0: 182 asm_ldq_f0(q); 183 break; 184 case 4: 185 asm_ldq_f4(q); 186 break; 187 case 8: 188 asm_ldq_f8(q); 189 break; 190 case 12: 191 asm_ldq_f12(q); 192 break; 193 case 16: 194 asm_ldq_f16(q); 195 break; 196 case 20: 197 asm_ldq_f20(q); 198 break; 199 case 24: 200 asm_ldq_f24(q); 201 break; 202 case 28: 203 asm_ldq_f28(q); 204 break; 205 case 32: 206 asm_ldq_f32(q); 207 break; 208 case 36: 209 asm_ldq_f36(q); 210 break; 211 case 40: 212 asm_ldq_f40(q); 213 break; 214 case 44: 215 asm_ldq_f44(q); 216 break; 217 case 48: 218 asm_ldq_f48(q); 219 break; 220 case 52: 221 asm_ldq_f52(q); 222 break; 223 case 56: 224 asm_ldq_f56(q); 225 break; 226 case 60: 227 asm_ldq_f60(q); 228 break; 229 default: 230 errx(1, "asm_ldq: bad freg %d", freg); 231 } 232 } 233 234 void 235 asm_stq(int freg, struct fpquad *q) 236 { 237 switch (freg) { 238 case 0: 239 asm_stq_f0(q); 240 break; 241 case 4: 242 asm_stq_f4(q); 243 break; 244 case 8: 245 asm_stq_f8(q); 246 break; 247 case 12: 248 asm_stq_f12(q); 249 break; 250 case 16: 251 asm_stq_f16(q); 252 break; 253 case 20: 254 asm_stq_f20(q); 255 break; 256 case 24: 257 asm_stq_f24(q); 258 break; 259 case 28: 260 asm_stq_f28(q); 261 break; 262 case 32: 263 asm_stq_f32(q); 264 break; 265 case 36: 266 asm_stq_f36(q); 267 break; 268 case 40: 269 asm_stq_f40(q); 270 break; 271 case 44: 272 asm_stq_f44(q); 273 break; 274 case 48: 275 asm_stq_f48(q); 276 break; 277 case 52: 278 asm_stq_f52(q); 279 break; 280 case 56: 281 asm_stq_f56(q); 282 break; 283 case 60: 284 asm_stq_f60(q); 285 break; 286 default: 287 errx(1, "asm_stq: bad freg %d", freg); 288 } 289 } 290 291 void 292 check_reg(int freg, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 293 { 294 struct fpquad q1, q2, q3; 295 296 initfpregs(fr1); 297 initfpregs(fr2); 298 initfpregs(fr3); 299 300 loadfpregs(fr1); 301 q1.x1 = 0x01234567; 302 q1.x2 = 0x89abcdef; 303 q1.x3 = 0x55aa55aa; 304 q1.x4 = 0xa5a5a5a5; 305 asm_ldq(freg, &q1); 306 savefpregs(fr2); 307 308 c_ldq(fr3, freg, &q1); 309 310 if (compare_regs(fr2, fr3)) { 311 errx(1, "ldq: c/asm differ"); 312 dump_regs(fr1, fr2, fr3); 313 } 314 315 q2.x1 = q2.x2 = q2.x3 = q2.x4 = 0; 316 q3.x1 = q3.x2 = q3.x3 = q3.x4 = 1; 317 asm_stq(freg, &q2); 318 c_stq(fr3, freg, &q3); 319 320 if (compare_quads(&q1, &q3)) 321 errx(1, "c_stq %d differs...", freg); 322 323 if (compare_quads(&q1, &q2)) 324 errx(1, "asm_stq %d differs...", freg); 325 } 326 327 void 328 check_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 329 { 330 int i; 331 332 for (i = 0; i < 16; i++) 333 check_reg(i * 4, fr1, fr2, fr3); 334 } 335 336 int 337 main() 338 { 339 union fpregs fr1, fr2, fr3; 340 341 check_saves(&fr1, &fr2, &fr3); 342 check_regs(&fr1, &fr2, &fr3); 343 return (0); 344 } 345