Annotation of sys/arch/m88k/m88k/m88100_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: m88100_machdep.c,v 1.3 2007/05/20 20:12:31 miod Exp $ */
! 2: /*
! 3: * Mach Operating System
! 4: * Copyright (c) 1993-1991 Carnegie Mellon University
! 5: * Copyright (c) 1991 OMRON Corporation
! 6: * All Rights Reserved.
! 7: *
! 8: * Permission to use, copy, modify and distribute this software and its
! 9: * documentation is hereby granted, provided that both the copyright
! 10: * notice and this permission notice appear in all copies of the
! 11: * software, derivative works or modified versions, and any portions
! 12: * thereof, and that both notices appear in supporting documentation.
! 13: *
! 14: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 15: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 16: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 17: *
! 18: * Carnegie Mellon requests users of this software to return to
! 19: *
! 20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 21: * School of Computer Science
! 22: * Carnegie Mellon University
! 23: * Pittsburgh PA 15213-3890
! 24: *
! 25: * any improvements or extensions that they make and grant Carnegie the
! 26: * rights to redistribute these changes.
! 27: */
! 28:
! 29: #include "assym.h" /* EF_xxx */
! 30:
! 31: #include <sys/param.h>
! 32: #include <sys/systm.h>
! 33:
! 34: #include <machine/asm_macro.h>
! 35: #include <m88k/m88100.h>
! 36:
! 37: /*
! 38: * Data Access Emulation for M88100 exceptions
! 39: */
! 40:
! 41: #define DMT_BYTE 1
! 42: #define DMT_HALF 2
! 43: #define DMT_WORD 4
! 44:
! 45: const struct {
! 46: unsigned char offset;
! 47: unsigned char size;
! 48: } dmt_en_info[16] = {
! 49: {0, 0}, {3, DMT_BYTE}, {2, DMT_BYTE}, {2, DMT_HALF},
! 50: {1, DMT_BYTE}, {0, 0}, {0, 0}, {0, 0},
! 51: {0, DMT_BYTE}, {0, 0}, {0, 0}, {0, 0},
! 52: {0, DMT_HALF}, {0, 0}, {0, 0}, {0, DMT_WORD}
! 53: };
! 54:
! 55: #ifdef DATA_DEBUG
! 56: int data_access_emulation_debug = 0;
! 57: #define DAE_DEBUG(stuff) \
! 58: do { \
! 59: if (data_access_emulation_debug != 0) { \
! 60: stuff; \
! 61: } \
! 62: } while (0)
! 63: #else
! 64: #define DAE_DEBUG(stuff)
! 65: #endif
! 66:
! 67: void
! 68: dae_print(unsigned *eframe)
! 69: {
! 70: int x;
! 71: unsigned dmax, dmdx, dmtx;
! 72:
! 73: if (!ISSET(eframe[EF_DMT0], DMT_VALID))
! 74: return;
! 75:
! 76: for (x = 0; x < 3; x++) {
! 77: dmtx = eframe[EF_DMT0 + x * 3];
! 78: if (!ISSET(dmtx, DMT_VALID))
! 79: continue;
! 80:
! 81: dmdx = eframe[EF_DMD0 + x * 3];
! 82: dmax = eframe[EF_DMA0 + x * 3];
! 83:
! 84: if (ISSET(dmtx, DMT_WRITE))
! 85: printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n",
! 86: x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax,
! 87: DMT_ENBITS(dmtx),
! 88: dmtx & DMT_DOUB1 ? "double": "not double",
! 89: dmtx & DMT_LOCKBAR ? "xmem": "not xmem");
! 90: else
! 91: printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n",
! 92: x, dmtx, dmtx & DMT_DAS ? 's' : 'u',
! 93: DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx),
! 94: dmtx & DMT_DOUB1 ? "double": "not double",
! 95: dmtx & DMT_LOCKBAR ? "xmem": "not xmem");
! 96: }
! 97: }
! 98:
! 99: void
! 100: data_access_emulation(unsigned *eframe)
! 101: {
! 102: int x;
! 103: unsigned dmax, dmdx, dmtx;
! 104: unsigned v, reg;
! 105:
! 106: dmtx = eframe[EF_DMT0];
! 107: if (!ISSET(dmtx, DMT_VALID))
! 108: return;
! 109:
! 110: for (x = 0; x < 3; x++) {
! 111: dmtx = eframe[EF_DMT0 + x * 3];
! 112: if (!ISSET(dmtx, DMT_VALID) || ISSET(dmtx, DMT_SKIP))
! 113: continue;
! 114:
! 115: dmdx = eframe[EF_DMD0 + x * 3];
! 116: dmax = eframe[EF_DMA0 + x * 3];
! 117:
! 118: DAE_DEBUG(
! 119: if (ISSET(dmtx, DMT_WRITE))
! 120: printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n",
! 121: x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax,
! 122: DMT_ENBITS(dmtx),
! 123: dmtx & DMT_DOUB1 ? "double": "not double",
! 124: dmtx & DMT_LOCKBAR ? "xmem": "not xmem");
! 125: else
! 126: printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n",
! 127: x, dmtx, dmtx & DMT_DAS ? 's' : 'u',
! 128: DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx),
! 129: dmtx & DMT_DOUB1 ? "double": "not double",
! 130: dmtx & DMT_LOCKBAR ? "xmem": "not xmem")
! 131: );
! 132:
! 133: dmax += dmt_en_info[DMT_ENBITS(dmtx)].offset;
! 134: reg = DMT_DREGBITS(dmtx);
! 135:
! 136: if (!ISSET(dmtx, DMT_LOCKBAR)) {
! 137: /* the fault is not during an XMEM */
! 138:
! 139: if (x == 2 && ISSET(dmtx, DMT_DOUB1)) {
! 140: /* pipeline 2 (earliest stage) for a double */
! 141:
! 142: if (ISSET(dmtx, DMT_WRITE)) {
! 143: /*
! 144: * STORE DOUBLE WILL BE REINITIATED
! 145: * BY rte
! 146: */
! 147: } else {
! 148: /* EMULATE ld.d INSTRUCTION */
! 149: v = do_load_word(dmax, dmtx & DMT_DAS);
! 150: if (reg != 0)
! 151: eframe[EF_R0 + reg] = v;
! 152: v = do_load_word(dmax ^ 4,
! 153: dmtx & DMT_DAS);
! 154: if (reg != 31)
! 155: eframe[EF_R0 + reg + 1] = v;
! 156: }
! 157: } else {
! 158: /* not pipeline #2 with a double */
! 159: if (dmtx & DMT_WRITE) {
! 160: switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
! 161: case DMT_BYTE:
! 162: DAE_DEBUG(
! 163: printf("[byte %x -> [%x(%c)]\n",
! 164: dmdx & 0xff, dmax,
! 165: ISSET(dmtx, DMT_DAS) ? 's' : 'u')
! 166: );
! 167: do_store_byte(dmax, dmdx,
! 168: dmtx & DMT_DAS);
! 169: break;
! 170: case DMT_HALF:
! 171: DAE_DEBUG(
! 172: printf("[half %x -> [%x(%c)]\n",
! 173: dmdx & 0xffff, dmax,
! 174: ISSET(dmtx, DMT_DAS) ? 's' : 'u')
! 175: );
! 176: do_store_half(dmax, dmdx,
! 177: dmtx & DMT_DAS);
! 178: break;
! 179: case DMT_WORD:
! 180: DAE_DEBUG(
! 181: printf("[word %x -> [%x(%c)]\n",
! 182: dmdx, dmax,
! 183: ISSET(dmtx, DMT_DAS) ? 's' : 'u')
! 184: );
! 185: do_store_word(dmax, dmdx,
! 186: dmtx & DMT_DAS);
! 187: break;
! 188: }
! 189: } else {
! 190: /* else it's a read */
! 191: switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
! 192: case DMT_BYTE:
! 193: v = do_load_byte(dmax,
! 194: dmtx & DMT_DAS);
! 195: if (!ISSET(dmtx, DMT_SIGNED))
! 196: v &= 0x000000ff;
! 197: break;
! 198: case DMT_HALF:
! 199: v = do_load_half(dmax,
! 200: dmtx & DMT_DAS);
! 201: if (!ISSET(dmtx, DMT_SIGNED))
! 202: v &= 0x0000ffff;
! 203: break;
! 204: case DMT_WORD:
! 205: v = do_load_word(dmax,
! 206: dmtx & DMT_DAS);
! 207: break;
! 208: }
! 209: DAE_DEBUG(
! 210: if (reg == 0)
! 211: printf("[no write to r0 done]\n");
! 212: else
! 213: printf("[r%d <- %x]\n", reg, v);
! 214: );
! 215: if (reg != 0)
! 216: eframe[EF_R0 + reg] = v;
! 217: }
! 218: }
! 219: } else {
! 220: /* if lockbar is set... it's part of an XMEM */
! 221: /*
! 222: * According to Motorola's "General Information",
! 223: * the DMT_DOUB1 bit is never set in this case, as it
! 224: * should be.
! 225: * If lockbar is set (as it is if we're here) and if
! 226: * the write is not set, then it's the same as if DOUB1
! 227: * was set...
! 228: */
! 229: if (!ISSET(dmtx, DMT_WRITE)) {
! 230: if (x != 2) {
! 231: /* RERUN xmem WITH DMD(x+1) */
! 232: x++;
! 233: dmdx = eframe[EF_DMD0 + x * 3];
! 234: } else {
! 235: /* RERUN xmem WITH DMD2 */
! 236: }
! 237:
! 238: if (dmt_en_info[DMT_ENBITS(dmtx)].size ==
! 239: DMT_WORD) {
! 240: v = do_xmem_word(dmax, dmdx,
! 241: dmtx & DMT_DAS);
! 242: } else {
! 243: v = do_xmem_byte(dmax, dmdx,
! 244: dmtx & DMT_DAS);
! 245: }
! 246: if (reg != 0)
! 247: eframe[EF_R0 + reg] = v;
! 248: } else {
! 249: if (x == 0) {
! 250: if (reg != 0)
! 251: eframe[EF_R0 + reg] = dmdx;
! 252: eframe[EF_SFIP] = eframe[EF_SNIP];
! 253: eframe[EF_SNIP] = eframe[EF_SXIP];
! 254: eframe[EF_SXIP] = 0;
! 255: /* xmem RERUN ON rte */
! 256: eframe[EF_DMT0] = 0;
! 257: return;
! 258: }
! 259: }
! 260: }
! 261: }
! 262: eframe[EF_DMT0] = 0;
! 263: }
! 264:
! 265: /*
! 266: * Routines to patch the kernel code on 88100 systems not affected by
! 267: * the xxx.usr bug.
! 268: */
! 269:
! 270: void
! 271: m88100_apply_patches()
! 272: {
! 273: #ifdef ERRATA__XXX_USR
! 274: if (((get_cpu_pid() & PID_VN) >> VN_SHIFT) > 10) {
! 275: /*
! 276: * Patch DAE helpers.
! 277: * before after
! 278: * branch branch
! 279: * NOP jmp.n r1
! 280: * xxx.usr xxx.usr
! 281: * NOP; NOP; NOP
! 282: * jmp r1
! 283: */
! 284: ((u_int32_t *)(do_load_word))[1] = 0xf400c401;
! 285: ((u_int32_t *)(do_load_half))[1] = 0xf400c401;
! 286: ((u_int32_t *)(do_load_byte))[1] = 0xf400c401;
! 287: ((u_int32_t *)(do_store_word))[1] = 0xf400c401;
! 288: ((u_int32_t *)(do_store_half))[1] = 0xf400c401;
! 289: ((u_int32_t *)(do_store_byte))[1] = 0xf400c401;
! 290: ((u_int32_t *)(do_xmem_word))[1] = 0xf400c401;
! 291: ((u_int32_t *)(do_xmem_byte))[1] = 0xf400c401;
! 292: }
! 293: #endif
! 294: }
CVSweb