1 /* $OpenBSD: asi.c,v 1.2 2003/07/12 07:09:25 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 30 #include <machine/psl.h> 31 #include <machine/ctlreg.h> 32 33 #include <stdlib.h> 34 #include <limits.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <err.h> 38 #include <errno.h> 39 #include "fpregs.h" 40 41 struct fpquad { 42 u_int32_t x1; 43 u_int32_t x2; 44 u_int32_t x3; 45 u_int32_t x4; 46 }; 47 48 int compare_regs(union fpregs *, union fpregs *); 49 void dump_reg(union fpregs *); 50 void dump_regs(union fpregs *, union fpregs *, union fpregs *); 51 int compare_quads(struct fpquad *, struct fpquad *); 52 void c_stqa_asi(int, union fpregs *, struct fpquad *); 53 void c_ldqa_asi(int, union fpregs *, struct fpquad *); 54 void asm_ldqa_asi(int, struct fpquad *); 55 void asm_stqa_asi(int, struct fpquad *); 56 void asm_ldqa_imm(int asi, struct fpquad *); 57 void asm_stqa_imm(int asi, struct fpquad *); 58 void asm_stqa_primary(struct fpquad *); 59 void asm_ldqa_primary(struct fpquad *); 60 void asm_stqa_secondary(struct fpquad *); 61 void asm_ldqa_secondary(struct fpquad *); 62 void asm_stqa_primary_nofault(struct fpquad *); 63 void asm_ldqa_primary_nofault(struct fpquad *); 64 void asm_stqa_secondary_nofault(struct fpquad *); 65 void asm_ldqa_secondary_nofault(struct fpquad *); 66 void asm_stqa_primary_little(struct fpquad *); 67 void asm_ldqa_primary_little(struct fpquad *); 68 void asm_stqa_secondary_little(struct fpquad *); 69 void asm_ldqa_secondary_little(struct fpquad *); 70 void asm_stqa_primary_nofault_little(struct fpquad *); 71 void asm_ldqa_primary_nofault_little(struct fpquad *); 72 void asm_stqa_secondary_nofault_little(struct fpquad *); 73 void asm_ldqa_secondary_nofault_little(struct fpquad *); 74 void check_asi(int, union fpregs *, union fpregs *, union fpregs *); 75 void check_asi_asi(int, union fpregs *, union fpregs *, union fpregs *); 76 void check_asi_imm(int, union fpregs *, union fpregs *, union fpregs *); 77 int main(int, char *[]); 78 79 int 80 compare_regs(union fpregs *fr1, union fpregs *fr2) 81 { 82 return (memcmp(fr1, fr2, sizeof(*fr2))); 83 } 84 85 void 86 dump_reg(union fpregs *fr) 87 { 88 int i; 89 90 for (i = 0; i < 64; i++) { 91 if ((i & 3) == 0) 92 printf("f%-2d:", i); 93 printf(" %08x", fr->f_reg32[i]); 94 if ((i & 3) == 3) 95 printf("\n"); 96 } 97 } 98 99 void 100 dump_regs(union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 101 { 102 printf("BEFORE ASM\n"); 103 dump_reg(fr1); 104 printf("AFTER ASM\n"); 105 dump_reg(fr2); 106 printf("MANUAL\n"); 107 dump_reg(fr3); 108 } 109 110 int 111 compare_quads(struct fpquad *q1, struct fpquad *q2) 112 { 113 return (memcmp(q1, q2, sizeof(*q2))); 114 } 115 116 void 117 c_stqa_asi(int asi, union fpregs *frp, struct fpquad *q) 118 { 119 if (asi == ASI_PRIMARY || 120 asi == ASI_PRIMARY_NOFAULT || 121 asi == ASI_SECONDARY || 122 asi == ASI_SECONDARY_NOFAULT) { 123 q->x1 = frp->f_reg32[0]; 124 q->x2 = frp->f_reg32[0 + 1]; 125 q->x3 = frp->f_reg32[0 + 2]; 126 q->x4 = frp->f_reg32[0 + 3]; 127 return; 128 } 129 if (asi == ASI_PRIMARY_LITTLE || 130 asi == ASI_PRIMARY_NOFAULT_LITTLE || 131 asi == ASI_SECONDARY_LITTLE || 132 asi == ASI_SECONDARY_NOFAULT_LITTLE) { 133 q->x4 = htole32(frp->f_reg32[0]); 134 q->x3 = htole32(frp->f_reg32[0 + 1]); 135 q->x2 = htole32(frp->f_reg32[0 + 2]); 136 q->x1 = htole32(frp->f_reg32[0 + 3]); 137 return; 138 } 139 errx(1, "c_stqa_asi: bad asi %d", asi); 140 } 141 142 void 143 c_ldqa_asi(int asi, union fpregs *frp, struct fpquad *q) 144 { 145 if (asi == ASI_PRIMARY || 146 asi == ASI_PRIMARY_NOFAULT || 147 asi == ASI_SECONDARY || 148 asi == ASI_SECONDARY_NOFAULT) { 149 frp->f_reg32[0] = q->x1; 150 frp->f_reg32[0 + 1] = q->x2; 151 frp->f_reg32[0 + 2] = q->x3; 152 frp->f_reg32[0 + 3] = q->x4; 153 return; 154 } 155 if (asi == ASI_PRIMARY_LITTLE || 156 asi == ASI_PRIMARY_NOFAULT_LITTLE || 157 asi == ASI_SECONDARY_LITTLE || 158 asi == ASI_SECONDARY_NOFAULT_LITTLE) { 159 frp->f_reg32[0] = htole32(q->x4); 160 frp->f_reg32[0 + 1] = htole32(q->x3); 161 frp->f_reg32[0 + 2] = htole32(q->x2); 162 frp->f_reg32[0 + 3] = htole32(q->x1); 163 return; 164 } 165 errx(1, "c_ldqa_asi: bad asi %d", asi); 166 } 167 168 void 169 asm_stqa_imm(int asi, struct fpquad *q) 170 { 171 switch (asi) { 172 case ASI_PRIMARY: 173 asm_stqa_primary(q); 174 break; 175 case ASI_SECONDARY: 176 asm_stqa_secondary(q); 177 break; 178 case ASI_PRIMARY_NOFAULT: 179 asm_stqa_primary_nofault(q); 180 break; 181 case ASI_SECONDARY_NOFAULT: 182 asm_stqa_secondary_nofault(q); 183 break; 184 case ASI_PRIMARY_LITTLE: 185 asm_stqa_primary_little(q); 186 break; 187 case ASI_SECONDARY_LITTLE: 188 asm_stqa_secondary_little(q); 189 break; 190 case ASI_PRIMARY_NOFAULT_LITTLE: 191 asm_stqa_primary_nofault_little(q); 192 break; 193 case ASI_SECONDARY_NOFAULT_LITTLE: 194 asm_stqa_secondary_nofault_little(q); 195 break; 196 default: 197 errx(1, "asm_stqa_imm: bad asi %d", asi); 198 } 199 } 200 201 void 202 asm_ldqa_imm(int asi, struct fpquad *q) 203 { 204 switch (asi) { 205 case ASI_PRIMARY: 206 asm_ldqa_primary(q); 207 break; 208 case ASI_SECONDARY: 209 asm_ldqa_secondary(q); 210 break; 211 case ASI_PRIMARY_NOFAULT: 212 asm_ldqa_primary_nofault(q); 213 break; 214 case ASI_SECONDARY_NOFAULT: 215 asm_ldqa_secondary_nofault(q); 216 break; 217 case ASI_PRIMARY_LITTLE: 218 asm_ldqa_primary_little(q); 219 break; 220 case ASI_SECONDARY_LITTLE: 221 asm_ldqa_secondary_little(q); 222 break; 223 case ASI_PRIMARY_NOFAULT_LITTLE: 224 asm_ldqa_primary_nofault_little(q); 225 break; 226 case ASI_SECONDARY_NOFAULT_LITTLE: 227 asm_ldqa_secondary_nofault_little(q); 228 break; 229 default: 230 errx(1, "asm_ldqa_imm: bad asi %d", asi); 231 } 232 } 233 234 void 235 check_asi(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 236 { 237 check_asi_asi(asi, fr1, fr2, fr3); 238 check_asi_imm(asi, fr1, fr2, fr3); 239 } 240 241 void 242 check_asi_asi(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 243 { 244 struct fpquad q1; 245 246 initfpregs(fr1); 247 initfpregs(fr2); 248 initfpregs(fr3); 249 250 q1.x1 = 0x01234567; 251 q1.x2 = 0x89abcdef; 252 q1.x3 = 0x55aa55aa; 253 q1.x4 = 0xa5a5a5a5; 254 255 loadfpregs(fr1); 256 asm_ldqa_asi(asi, &q1); 257 savefpregs(fr2); 258 259 c_ldqa_asi(asi, fr3, &q1); 260 261 if (compare_regs(fr2, fr3)) { 262 printf("ASI 0x%x failed\n", asi); 263 dump_regs(fr1, fr2, fr3); 264 exit(1); 265 } 266 } 267 268 void 269 check_asi_imm(int asi, union fpregs *fr1, union fpregs *fr2, union fpregs *fr3) 270 { 271 struct fpquad q1; 272 273 initfpregs(fr1); 274 initfpregs(fr2); 275 initfpregs(fr3); 276 277 q1.x1 = 0x01234567; 278 q1.x2 = 0x89abcdef; 279 q1.x3 = 0x55aa55aa; 280 q1.x4 = 0xa5a5a5a5; 281 282 loadfpregs(fr1); 283 asm_ldqa_imm(asi, &q1); 284 savefpregs(fr2); 285 286 c_ldqa_asi(asi, fr3, &q1); 287 288 if (compare_regs(fr2, fr3)) { 289 printf("ASI 0x%x failed\n", asi); 290 dump_regs(fr1, fr2, fr3); 291 exit(1); 292 } 293 } 294 295 int 296 main(int argc, char *argv[]) 297 { 298 union fpregs fr1, fr2, fr3; 299 300 check_asi(ASI_PRIMARY, &fr1, &fr2, &fr3); 301 check_asi(ASI_PRIMARY_NOFAULT, &fr1, &fr2, &fr3); 302 check_asi(ASI_PRIMARY_LITTLE, &fr1, &fr2, &fr3); 303 check_asi(ASI_PRIMARY_NOFAULT_LITTLE, &fr1, &fr2, &fr3); 304 check_asi(ASI_SECONDARY, &fr1, &fr2, &fr3); 305 check_asi(ASI_SECONDARY_NOFAULT, &fr1, &fr2, &fr3); 306 check_asi(ASI_SECONDARY_LITTLE, &fr1, &fr2, &fr3); 307 check_asi(ASI_SECONDARY_NOFAULT_LITTLE, &fr1, &fr2, &fr3); 308 return (0); 309 } 310