|
|
1.1 root 1: /* automatically generated by m68k-insns-auto.sh, do not edit! */ 1.1.1.5 ! root 2: _TME_RCSID("$Id: m68k-insns-auto.sh,v 1.26 2009/08/29 19:38:23 fredette Exp $"); 1.1 root 3: 4: #include "m68k-impl.h" 5: 6: 7: /* this does a 8-bit "add SRC, DST": */ 8: TME_M68K_INSN(tme_m68k_add8) 9: { 10: tme_uint8_t res, op0, op1; 11: tme_uint8_t flags; 12: 13: /* load the operand(s): */ 14: op0 = *((tme_uint8_t *) _op0); 15: op1 = *((tme_uint8_t *) _op1); 16: 17: /* perform the operation: */ 18: res = op1 + op0; 19: 20: /* store the result: */ 21: *((tme_uint8_t *) _op1) = res; 22: 23: /* set the flags: */ 24: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 25: if (res == 0) flags |= TME_M68K_FLAG_Z; 26: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xff) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 27: if (op0 > (op1 ^ 0xff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 28: ic->tme_m68k_ireg_ccr = flags; 29: 30: TME_M68K_INSN_OK; 31: } 32: 33: /* this does a 8-bit "sub SRC, DST": */ 34: TME_M68K_INSN(tme_m68k_sub8) 35: { 36: tme_uint8_t res, op0, op1; 37: tme_uint8_t flags; 38: 39: /* load the operand(s): */ 40: op0 = *((tme_uint8_t *) _op0); 41: op1 = *((tme_uint8_t *) _op1); 42: 43: /* perform the operation: */ 44: res = op1 - op0; 45: 46: /* store the result: */ 47: *((tme_uint8_t *) _op1) = res; 48: 49: /* set the flags: */ 50: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 51: if (res == 0) flags |= TME_M68K_FLAG_Z; 52: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 53: if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 54: ic->tme_m68k_ireg_ccr = flags; 55: 56: TME_M68K_INSN_OK; 57: } 58: 59: /* this does a 8-bit "cmp SRC, DST": */ 60: TME_M68K_INSN(tme_m68k_cmp8) 61: { 62: tme_uint8_t res, op0, op1; 63: tme_uint8_t flags; 64: 65: /* load the operand(s): */ 66: op0 = *((tme_uint8_t *) _op0); 67: op1 = *((tme_uint8_t *) _op1); 68: 69: /* perform the operation: */ 70: res = op1 - op0; 71: 72: /* set the flags: */ 73: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 74: if (res == 0) flags |= TME_M68K_FLAG_Z; 75: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 76: if (op0 > op1) flags |= TME_M68K_FLAG_C; 77: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 78: ic->tme_m68k_ireg_ccr = flags; 79: 80: TME_M68K_INSN_OK; 81: } 82: 83: /* this does a 8-bit "neg DST": */ 84: TME_M68K_INSN(tme_m68k_neg8) 85: { 86: tme_uint8_t res, op1; 87: tme_uint8_t flags; 88: 89: /* load the operand(s): */ 90: op1 = *((tme_uint8_t *) _op1); 91: 92: /* perform the operation: */ 93: res = 0 - op1; 94: 95: /* store the result: */ 96: *((tme_uint8_t *) _op1) = res; 97: 98: /* set the flags: */ 99: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 100: if (res == 0) flags |= TME_M68K_FLAG_Z; 101: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 102: if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 103: ic->tme_m68k_ireg_ccr = flags; 104: 105: TME_M68K_INSN_OK; 106: } 107: 108: /* this does a 8-bit "or SRC, DST": */ 109: TME_M68K_INSN(tme_m68k_or8) 110: { 111: tme_uint8_t res, op0, op1; 112: tme_uint8_t flags; 113: 114: /* load the operand(s): */ 115: op0 = *((tme_uint8_t *) _op0); 116: op1 = *((tme_uint8_t *) _op1); 117: 118: /* perform the operation: */ 119: res = op1 | op0; 120: 121: /* store the result: */ 122: *((tme_uint8_t *) _op1) = res; 123: 124: /* set the flags: */ 125: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 126: if (res == 0) flags |= TME_M68K_FLAG_Z; 127: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 128: ic->tme_m68k_ireg_ccr = flags; 129: 130: TME_M68K_INSN_OK; 131: } 132: 133: /* this does a 8-bit "and SRC, DST": */ 134: TME_M68K_INSN(tme_m68k_and8) 135: { 136: tme_uint8_t res, op0, op1; 137: tme_uint8_t flags; 138: 139: /* load the operand(s): */ 140: op0 = *((tme_uint8_t *) _op0); 141: op1 = *((tme_uint8_t *) _op1); 142: 143: /* perform the operation: */ 144: res = op1 & op0; 145: 146: /* store the result: */ 147: *((tme_uint8_t *) _op1) = res; 148: 149: /* set the flags: */ 150: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 151: if (res == 0) flags |= TME_M68K_FLAG_Z; 152: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 153: ic->tme_m68k_ireg_ccr = flags; 154: 155: TME_M68K_INSN_OK; 156: } 157: 158: /* this does a 8-bit "eor SRC, DST": */ 159: TME_M68K_INSN(tme_m68k_eor8) 160: { 161: tme_uint8_t res, op0, op1; 162: tme_uint8_t flags; 163: 164: /* load the operand(s): */ 165: op0 = *((tme_uint8_t *) _op0); 166: op1 = *((tme_uint8_t *) _op1); 167: 168: /* perform the operation: */ 169: res = op1 ^ op0; 170: 171: /* store the result: */ 172: *((tme_uint8_t *) _op1) = res; 173: 174: /* set the flags: */ 175: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 176: if (res == 0) flags |= TME_M68K_FLAG_Z; 177: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 178: ic->tme_m68k_ireg_ccr = flags; 179: 180: TME_M68K_INSN_OK; 181: } 182: 183: /* this does a 8-bit "not DST": */ 184: TME_M68K_INSN(tme_m68k_not8) 185: { 186: tme_uint8_t res, op1; 187: tme_uint8_t flags; 188: 189: /* load the operand(s): */ 190: op1 = *((tme_uint8_t *) _op1); 191: 192: /* perform the operation: */ 193: res = ~ op1; 194: 195: /* store the result: */ 196: *((tme_uint8_t *) _op1) = res; 197: 198: /* set the flags: */ 199: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 200: if (res == 0) flags |= TME_M68K_FLAG_Z; 201: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 202: ic->tme_m68k_ireg_ccr = flags; 203: 204: TME_M68K_INSN_OK; 205: } 206: 207: /* this does a 8-bit "tst DST": */ 208: TME_M68K_INSN(tme_m68k_tst8) 209: { 210: tme_uint8_t res, op1; 211: tme_uint8_t flags; 212: 213: /* load the operand(s): */ 214: op1 = *((tme_uint8_t *) _op1); 215: 216: /* perform the operation: */ 217: res = op1; 218: 219: /* set the flags: */ 220: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 221: if (res == 0) flags |= TME_M68K_FLAG_Z; 222: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 223: ic->tme_m68k_ireg_ccr = flags; 224: 225: TME_M68K_INSN_OK; 226: } 227: 228: /* this does a 8-bit "move DST": */ 229: TME_M68K_INSN(tme_m68k_move8) 230: { 231: tme_uint8_t res, op1; 232: tme_uint8_t flags; 233: 234: /* load the operand(s): */ 235: op1 = *((tme_uint8_t *) _op1); 236: 237: /* perform the operation: */ 238: res = op1; 239: 240: /* store the result: */ 241: *((tme_uint8_t *) _op0) = res; 242: 243: /* set the flags: */ 244: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 245: if (res == 0) flags |= TME_M68K_FLAG_Z; 246: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 247: ic->tme_m68k_ireg_ccr = flags; 248: 249: TME_M68K_INSN_OK; 250: } 251: 252: /* this does a 8-bit "clr DST": */ 253: TME_M68K_INSN(tme_m68k_clr8) 254: { 255: tme_uint8_t res; 256: tme_uint8_t flags; 257: 258: /* load the operand(s): */ 259: 260: /* perform the operation: */ 261: res = 0; 262: 263: /* store the result: */ 264: *((tme_uint8_t *) _op1) = res; 265: 266: /* set the flags: */ 267: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 268: if (res == 0) flags |= TME_M68K_FLAG_Z; 269: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 270: ic->tme_m68k_ireg_ccr = flags; 271: 272: TME_M68K_INSN_OK; 273: } 274: 275: /* this does a 8-bit "negx DST": */ 276: TME_M68K_INSN(tme_m68k_negx8) 277: { 278: tme_uint8_t res, op1; 279: tme_uint8_t flags; 280: 281: /* load the operand(s): */ 282: op1 = *((tme_uint8_t *) _op1); 283: 284: /* perform the operation: */ 285: res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 286: 287: /* store the result: */ 288: *((tme_uint8_t *) _op1) = res; 289: 290: /* set the flags: */ 291: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 292: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 293: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 294: if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 295: ic->tme_m68k_ireg_ccr = flags; 296: 297: TME_M68K_INSN_OK; 298: } 299: 300: /* this does a 8-bit "addx SRC, DST": */ 301: TME_M68K_INSN(tme_m68k_addx8) 302: { 303: tme_uint8_t res, op0, op1; 304: tme_uint8_t flags; 305: 306: /* load the operand(s): */ 307: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 308: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 309: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 310: tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3); 311: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3); 312: tme_uint16_t memory; 313: 314: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 315: if (memory) { 316: TME_M68K_INSN_CANFAULT; 317: if (!TME_M68K_SEQUENCE_RESTARTING) { 318: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 319: ic->_tme_m68k_ea_function_code = function_code; 320: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 321: } 322: tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8); 1.1.1.4 root 323: if (!TME_M68K_SEQUENCE_RESTARTING) { 324: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 325: ic->_tme_m68k_ea_function_code = function_code; 326: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 327: } 328: tme_m68k_read_memx8(ic); 1.1 root 329: op1 = ic->tme_m68k_ireg_memx8; 330: op0 = ic->tme_m68k_ireg_memy8; 331: } 332: else { 333: op0 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_src) << 2); 334: op1 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2); 335: } 336: 337: /* perform the operation: */ 338: res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 339: 340: /* store the result: */ 341: if (memory) { 342: if (!TME_M68K_SEQUENCE_RESTARTING) { 343: ic->tme_m68k_ireg_memx8 = res; 344: ic->_tme_m68k_ea_function_code = function_code; 345: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 346: } 347: tme_m68k_write_memx8(ic); 348: } 349: else { 350: ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2) = res; 351: } 352: 353: /* set the flags: */ 354: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 355: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 356: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xff) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 357: if (op0 > (op1 ^ 0xff) || (op0 == (op1 ^ 0xff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 358: ic->tme_m68k_ireg_ccr = flags; 359: 360: TME_M68K_INSN_OK; 361: } 362: 363: /* this does a 8-bit "subx SRC, DST": */ 364: TME_M68K_INSN(tme_m68k_subx8) 365: { 366: tme_uint8_t res, op0, op1; 367: tme_uint8_t flags; 368: 369: /* load the operand(s): */ 370: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 371: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 372: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 373: tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3); 374: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3); 375: tme_uint16_t memory; 376: 377: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 378: if (memory) { 379: TME_M68K_INSN_CANFAULT; 380: if (!TME_M68K_SEQUENCE_RESTARTING) { 381: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 382: ic->_tme_m68k_ea_function_code = function_code; 383: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 384: } 385: tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8); 1.1.1.4 root 386: if (!TME_M68K_SEQUENCE_RESTARTING) { 387: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 388: ic->_tme_m68k_ea_function_code = function_code; 389: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 390: } 391: tme_m68k_read_memx8(ic); 1.1 root 392: op1 = ic->tme_m68k_ireg_memx8; 393: op0 = ic->tme_m68k_ireg_memy8; 394: } 395: else { 396: op0 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_src) << 2); 397: op1 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2); 398: } 399: 400: /* perform the operation: */ 401: res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 402: 403: /* store the result: */ 404: if (memory) { 405: if (!TME_M68K_SEQUENCE_RESTARTING) { 406: ic->tme_m68k_ireg_memx8 = res; 407: ic->_tme_m68k_ea_function_code = function_code; 408: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 409: } 410: tme_m68k_write_memx8(ic); 411: } 412: else { 413: ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2) = res; 414: } 415: 416: /* set the flags: */ 417: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 418: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 419: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 420: if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 421: ic->tme_m68k_ireg_ccr = flags; 422: 423: TME_M68K_INSN_OK; 424: } 425: 426: /* this does a 8-bit "cmpm SRC, DST": */ 427: TME_M68K_INSN(tme_m68k_cmpm8) 428: { 429: tme_uint8_t res, op0, op1; 430: tme_uint8_t flags; 431: 432: /* load the operand(s): */ 433: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 434: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 435: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 436: tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3); 437: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3); 438: 439: TME_M68K_INSN_CANFAULT; 440: 441: if (!TME_M68K_SEQUENCE_RESTARTING) { 442: ic->_tme_m68k_ea_function_code = function_code; 443: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 444: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust; 445: } 446: tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8); 1.1.1.4 root 447: if (!TME_M68K_SEQUENCE_RESTARTING) { 448: ic->_tme_m68k_ea_function_code = function_code; 449: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 450: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust; 451: } 452: tme_m68k_read_memx8(ic); 1.1 root 453: op1 = ic->tme_m68k_ireg_memx8; 454: op0 = ic->tme_m68k_ireg_memy8; 455: 456: /* perform the operation: */ 457: res = op1 - op0; 458: 459: /* set the flags: */ 460: flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 461: if (res == 0) flags |= TME_M68K_FLAG_Z; 462: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V; 463: if (op0 > op1) flags |= TME_M68K_FLAG_C; 464: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 465: ic->tme_m68k_ireg_ccr = flags; 466: 467: TME_M68K_INSN_OK; 468: } 469: 470: /* the btst function on a 8-byte EA: */ 471: TME_M68K_INSN(tme_m68k_btst8) 472: { 473: tme_uint8_t value, bit; 474: bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1)); 475: value = TME_M68K_INSN_OP1(tme_uint8_t); 476: if (value & bit) { 477: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 478: } 479: else { 480: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 481: } 482: TME_M68K_INSN_OK; 483: } 484: 485: /* the bchg function on a 8-byte EA: */ 486: TME_M68K_INSN(tme_m68k_bchg8) 487: { 488: tme_uint8_t value, bit; 489: bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1)); 490: value = TME_M68K_INSN_OP1(tme_uint8_t); 491: if (value & bit) { 492: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 493: } 494: else { 495: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 496: } 497: TME_M68K_INSN_OP1(tme_uint8_t) = value ^ bit; 498: TME_M68K_INSN_OK; 499: } 500: 501: /* the bclr function on a 8-byte EA: */ 502: TME_M68K_INSN(tme_m68k_bclr8) 503: { 504: tme_uint8_t value, bit; 505: bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1)); 506: value = TME_M68K_INSN_OP1(tme_uint8_t); 507: if (value & bit) { 508: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 509: } 510: else { 511: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 512: } 513: TME_M68K_INSN_OP1(tme_uint8_t) = value & ~bit; 514: TME_M68K_INSN_OK; 515: } 516: 517: /* the bset function on a 8-byte EA: */ 518: TME_M68K_INSN(tme_m68k_bset8) 519: { 520: tme_uint8_t value, bit; 521: bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1)); 522: value = TME_M68K_INSN_OP1(tme_uint8_t); 523: if (value & bit) { 524: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 525: } 526: else { 527: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 528: } 529: TME_M68K_INSN_OP1(tme_uint8_t) = value | bit; 530: TME_M68K_INSN_OK; 531: } 532: 533: /* the asl function on a 8-byte EA: */ 534: TME_M68K_INSN(tme_m68k_asl8) 535: { 536: unsigned int count; 1.1.1.2 root 537: tme_uint8_t sign_bits, sign_bits_mask; 1.1 root 538: tme_uint8_t res; 539: tme_uint8_t flags; 540: 541: /* get the count and operand: */ 542: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 543: res = TME_M68K_INSN_OP1(tme_uint8_t); 544: 545: /* generate the X, V, and C flags assuming the count is zero: */ 546: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 547: 548: /* if the count is nonzero, update the result and 549: generate the X, V, and C flags: */ 550: if (count > 0) { 551: 552: /* we need to see how the sign of the result will change during 553: shifting in order to generate V. 554: 555: in general, the idea is to get all of the bits that will ever 1.1.1.2 root 556: appear in the sign position into sign_bits, with a mask in 557: sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or 558: sign_bits_mask, clear V, else set V. 1.1 root 559: 1.1.1.2 root 560: start by loading the operand into sign_bits and setting 561: sign_bits_mask to all-bits-one. 1.1 root 562: 563: if the shift count is exactly 8 - 1, then all of the bits 564: of the operand will appear in the sign position. 565: 566: if the shift count is less than 8 - 1, then some of the 567: less significant bits of the operand will never appear in the 1.1.1.2 root 568: sign position, so we can shift sign_bits_mask to ignore them. 1.1 root 569: 570: if the shift count is greater than 8 - 1, then all of the 571: bits in the operand, plus at least one zero bit, will appear in 572: the sign position. the only way that the sign bit will never 573: change during the shift is if the operand was zero to begin with. 1.1.1.2 root 574: without any changes to sign_bits or sign_bits_mask, the final 575: test will always work, except when sign_bits is all-bits-one. 576: the magic below clears the least-significant bit of sign_bits 577: iff sign_bits is all-bits-one: */ 1.1 root 578: sign_bits = res; 579: if (63 > SHIFTMAX_INT8_T 580: && count > 8) { 581: res = 0; 582: } 583: res <<= (count - 1); 584: flags = (res >> (8 - 1)); 585: flags *= TME_M68K_FLAG_C; 586: flags |= (flags * TME_M68K_FLAG_X); 587: res <<= 1; 1.1.1.2 root 588: sign_bits_mask = (tme_uint8_t) -1; 1.1 root 589: if (count != 8 - 1) { 590: if (count < 8) { 1.1.1.2 root 591: sign_bits_mask <<= ((8 - 1) - count); 1.1 root 592: } 593: else { 1.1.1.2 root 594: sign_bits ^= !(sign_bits + 1); 1.1 root 595: } 596: } 1.1.1.2 root 597: sign_bits &= sign_bits_mask; 598: if (sign_bits != 0 && sign_bits != sign_bits_mask) { 1.1 root 599: flags |= TME_M68K_FLAG_V; 600: } 601: } 602: 603: /* store the result: */ 604: TME_M68K_INSN_OP1(tme_uint8_t) = res; 605: 606: /* generate the N flag. we cast to tme_uint8_t as soon as we 607: know the bit we want is within the range of the type, to try 608: to affect the generated assembly: */ 609: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 610: 611: /* generate the Z flag: */ 612: if (res == 0) flags |= TME_M68K_FLAG_Z; 613: 614: /* store the flags: */ 615: ic->tme_m68k_ireg_ccr = flags; 616: TME_M68K_INSN_OK; 617: } 618: 619: /* the asr function on a 8-byte EA: */ 620: TME_M68K_INSN(tme_m68k_asr8) 621: { 622: unsigned int count; 623: tme_int8_t res; 624: tme_uint8_t flags; 625: 626: /* get the count and operand: */ 627: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 628: res = TME_M68K_INSN_OP1(tme_int8_t); 629: 630: /* generate the X, V, and C flags assuming the count is zero: */ 631: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 632: 633: /* if the count is nonzero, update the result and 634: generate the X, V, and C flags: */ 635: if (count > 0) { 636: if (63 > SHIFTMAX_INT8_T 637: && count > 8) { 1.1.1.3 root 638: res = 0 - (res < 0); 1.1 root 639: } 1.1.1.3 root 640: #ifdef SHIFTSIGNED_INT8_T 1.1 root 641: res >>= (count - 1); 1.1.1.3 root 642: #else /* !SHIFTSIGNED_INT8_T */ 643: for (; --count > 0; ) { 644: res = (res & ~((tme_int8_t) 1)) / 2; 645: } 646: #endif /* !SHIFTSIGNED_INT8_T */ 1.1 root 647: flags = (res & 1); 648: flags *= TME_M68K_FLAG_C; 649: flags |= (flags * TME_M68K_FLAG_X); 1.1.1.3 root 650: #ifdef SHIFTSIGNED_INT8_T 1.1 root 651: res >>= 1; 1.1.1.3 root 652: #else /* !SHIFTSIGNED_INT8_T */ 653: res = (res & ~((tme_int8_t) 1)) / 2; 654: #endif /* !SHIFTSIGNED_INT8_T */ 1.1 root 655: } 656: 657: /* store the result: */ 658: TME_M68K_INSN_OP1(tme_int8_t) = res; 659: 660: /* generate the N flag. we cast to tme_uint8_t as soon as we 661: know the bit we want is within the range of the type, to try 662: to affect the generated assembly: */ 663: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 664: 665: /* generate the Z flag: */ 666: if (res == 0) flags |= TME_M68K_FLAG_Z; 667: 668: /* store the flags: */ 669: ic->tme_m68k_ireg_ccr = flags; 670: TME_M68K_INSN_OK; 671: } 672: 673: /* the lsl function on a 8-byte EA: */ 674: TME_M68K_INSN(tme_m68k_lsl8) 675: { 676: unsigned int count; 677: tme_uint8_t res; 678: tme_uint8_t flags; 679: 680: /* get the count and operand: */ 681: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 682: res = TME_M68K_INSN_OP1(tme_uint8_t); 683: 684: /* generate the X, V, and C flags assuming the count is zero: */ 685: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 686: 687: /* if the count is nonzero, update the result and 688: generate the X, V, and C flags: */ 689: if (count > 0) { 690: if (63 > SHIFTMAX_INT8_T 691: && count > 8) { 692: res = 0; 693: } 694: res <<= (count - 1); 695: flags = (res >> (8 - 1)); 696: flags *= TME_M68K_FLAG_C; 697: flags |= (flags * TME_M68K_FLAG_X); 698: res <<= 1; 699: } 700: 701: /* store the result: */ 702: TME_M68K_INSN_OP1(tme_uint8_t) = res; 703: 704: /* generate the N flag. we cast to tme_uint8_t as soon as we 705: know the bit we want is within the range of the type, to try 706: to affect the generated assembly: */ 707: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 708: 709: /* generate the Z flag: */ 710: if (res == 0) flags |= TME_M68K_FLAG_Z; 711: 712: /* store the flags: */ 713: ic->tme_m68k_ireg_ccr = flags; 714: TME_M68K_INSN_OK; 715: } 716: 717: /* the lsr function on a 8-byte EA: */ 718: TME_M68K_INSN(tme_m68k_lsr8) 719: { 720: unsigned int count; 721: tme_uint8_t res; 722: tme_uint8_t flags; 723: 724: /* get the count and operand: */ 725: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 726: res = TME_M68K_INSN_OP1(tme_uint8_t); 727: 728: /* generate the X, V, and C flags assuming the count is zero: */ 729: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 730: 731: /* if the count is nonzero, update the result and 732: generate the X, V, and C flags: */ 733: if (count > 0) { 734: if (63 > SHIFTMAX_INT8_T 735: && count > 8) { 736: res = 0; 737: } 738: res >>= (count - 1); 739: flags = (res & 1); 740: flags *= TME_M68K_FLAG_C; 741: flags |= (flags * TME_M68K_FLAG_X); 742: res >>= 1; 743: } 744: 745: /* store the result: */ 746: TME_M68K_INSN_OP1(tme_uint8_t) = res; 747: 748: /* generate the N flag. we cast to tme_uint8_t as soon as we 749: know the bit we want is within the range of the type, to try 750: to affect the generated assembly: */ 751: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 752: 753: /* generate the Z flag: */ 754: if (res == 0) flags |= TME_M68K_FLAG_Z; 755: 756: /* store the flags: */ 757: ic->tme_m68k_ireg_ccr = flags; 758: TME_M68K_INSN_OK; 759: } 760: 761: /* the rol function on a 8-byte EA: */ 762: TME_M68K_INSN(tme_m68k_rol8) 763: { 764: unsigned int count; 765: tme_uint8_t res; 766: tme_uint8_t flags; 767: 768: /* get the count and operand: */ 769: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 770: res = TME_M68K_INSN_OP1(tme_uint8_t); 771: 772: /* generate the X, V, and C flags assuming the count is zero: */ 773: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 774: 775: /* if the count is nonzero, update the result and 776: generate the X, V, and C flags: */ 777: if (count > 0) { 778: count &= (8 - 1); 779: res = (res << count) | (res >> (8 - count)); 780: flags |= ((res & 1) * TME_M68K_FLAG_C); 781: } 782: 783: /* store the result: */ 784: TME_M68K_INSN_OP1(tme_uint8_t) = res; 785: 786: /* generate the N flag. we cast to tme_uint8_t as soon as we 787: know the bit we want is within the range of the type, to try 788: to affect the generated assembly: */ 789: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 790: 791: /* generate the Z flag: */ 792: if (res == 0) flags |= TME_M68K_FLAG_Z; 793: 794: /* store the flags: */ 795: ic->tme_m68k_ireg_ccr = flags; 796: TME_M68K_INSN_OK; 797: } 798: 799: /* the ror function on a 8-byte EA: */ 800: TME_M68K_INSN(tme_m68k_ror8) 801: { 802: unsigned int count; 803: tme_uint8_t res; 804: tme_uint8_t flags; 805: 806: /* get the count and operand: */ 807: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 808: res = TME_M68K_INSN_OP1(tme_uint8_t); 809: 810: /* generate the X, V, and C flags assuming the count is zero: */ 811: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 812: 813: /* if the count is nonzero, update the result and 814: generate the X, V, and C flags: */ 815: if (count > 0) { 816: count &= (8 - 1); 817: res = (res << (8 - count)) | (res >> count); 818: flags |= ((res >> (8 - 1)) * TME_M68K_FLAG_C); 819: } 820: 821: /* store the result: */ 822: TME_M68K_INSN_OP1(tme_uint8_t) = res; 823: 824: /* generate the N flag. we cast to tme_uint8_t as soon as we 825: know the bit we want is within the range of the type, to try 826: to affect the generated assembly: */ 827: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 828: 829: /* generate the Z flag: */ 830: if (res == 0) flags |= TME_M68K_FLAG_Z; 831: 832: /* store the flags: */ 833: ic->tme_m68k_ireg_ccr = flags; 834: TME_M68K_INSN_OK; 835: } 836: 837: /* the roxl function on a 8-byte EA: */ 838: TME_M68K_INSN(tme_m68k_roxl8) 839: { 840: unsigned int count; 841: tme_uint8_t xbit; 842: tme_uint8_t res; 843: tme_uint8_t flags; 844: 845: /* get the count and operand: */ 846: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 847: res = TME_M68K_INSN_OP1(tme_uint8_t); 848: 849: /* generate the X, V, and C flags assuming the count is zero: */ 850: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 851: xbit = (flags / TME_M68K_FLAG_X); 852: flags |= (xbit * TME_M68K_FLAG_C); 853: 854: /* if the count is nonzero, update the result and 855: generate the X, V, and C flags: */ 856: if (count > 0) { 857: count %= (8 + 1); 858: flags = xbit; 859: if (count > 0) { 860: flags = (res >> (8 - count)) & 1; 861: if (8 > SHIFTMAX_INT8_T 862: && count == 8) { 863: res = 0 | (xbit << (8 - 1)) | (res >> ((8 + 1) - 8)); 864: } 865: else if (8 > SHIFTMAX_INT8_T 866: && count == 1) { 867: res = (res << 1) | (xbit << (1 - 1)) | 0; 868: } 869: else { 870: res = (res << count) | (xbit << (count - 1)) | (res >> ((8 + 1) - count)); 871: } 872: } 873: flags *= TME_M68K_FLAG_C; 874: flags |= (flags * TME_M68K_FLAG_X); 875: } 876: 877: /* store the result: */ 878: TME_M68K_INSN_OP1(tme_uint8_t) = res; 879: 880: /* generate the N flag. we cast to tme_uint8_t as soon as we 881: know the bit we want is within the range of the type, to try 882: to affect the generated assembly: */ 883: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 884: 885: /* generate the Z flag: */ 886: if (res == 0) flags |= TME_M68K_FLAG_Z; 887: 888: /* store the flags: */ 889: ic->tme_m68k_ireg_ccr = flags; 890: TME_M68K_INSN_OK; 891: } 892: 893: /* the roxr function on a 8-byte EA: */ 894: TME_M68K_INSN(tme_m68k_roxr8) 895: { 896: unsigned int count; 897: tme_uint8_t xbit; 898: tme_uint8_t res; 899: tme_uint8_t flags; 900: 901: /* get the count and operand: */ 902: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 903: res = TME_M68K_INSN_OP1(tme_uint8_t); 904: 905: /* generate the X, V, and C flags assuming the count is zero: */ 906: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 907: xbit = (flags / TME_M68K_FLAG_X); 908: flags |= (xbit * TME_M68K_FLAG_C); 909: 910: /* if the count is nonzero, update the result and 911: generate the X, V, and C flags: */ 912: if (count > 0) { 913: count %= (8 + 1); 914: flags = xbit; 915: if (count > 0) { 916: flags = (res >> (count - 1)) & 1; 917: if (8 > SHIFTMAX_INT8_T 918: && count == 8) { 919: res = (res << ((8 + 1) - 8)) | (xbit << (8 - 8)) | 0; 920: } 921: else if (8 > SHIFTMAX_INT8_T 922: && count == 1) { 923: res = 0 | (xbit << (8 - 1)) | (res >> 1); 924: } 925: else { 926: res = (res << ((8 + 1) - count)) | (xbit << (8 - count)) | (res >> count); 927: } 928: } 929: flags *= TME_M68K_FLAG_C; 930: flags |= (flags * TME_M68K_FLAG_X); 931: } 932: 933: /* store the result: */ 934: TME_M68K_INSN_OP1(tme_uint8_t) = res; 935: 936: /* generate the N flag. we cast to tme_uint8_t as soon as we 937: know the bit we want is within the range of the type, to try 938: to affect the generated assembly: */ 939: flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N; 940: 941: /* generate the Z flag: */ 942: if (res == 0) flags |= TME_M68K_FLAG_Z; 943: 944: /* store the flags: */ 945: ic->tme_m68k_ireg_ccr = flags; 946: TME_M68K_INSN_OK; 947: } 948: 949: /* cas8: */ 950: TME_M68K_INSN(tme_m68k_cas8) 951: { 1.1.1.4 root 952: struct tme_m68k_rmw rmw; 1.1 root 953: struct tme_m68k_tlb *tlb; 954: int ireg_dc, ireg_du; 1.1.1.4 root 955: tme_uint8_t value_dc, value_du, value_mem; 1.1 root 956: 957: /* start the read/modify/write cycle: */ 1.1.1.4 root 958: rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address; 959: rmw.tme_m68k_rmw_address_count = 1; 960: rmw.tme_m68k_rmw_size = sizeof(tme_uint8_t); 961: if (tme_m68k_rmw_start(ic, 962: &rmw)) { 1.1 root 963: TME_M68K_INSN_OK; 964: } 965: 1.1.1.4 root 966: /* get the compare and update registers: */ 967: ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 968: ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3); 969: 970: /* if we can do the fast compare-and-exchange: */ 971: if (!rmw.tme_m68k_rmw_slow_reads[0]) { 972: 973: /* get the compare and update values in big-endian byte order: */ 974: value_dc = ic->tme_m68k_ireg_uint8(ireg_dc << 2); 975: value_du = ic->tme_m68k_ireg_uint8(ireg_du << 2); 976: 977: /* get this TLB entry: */ 978: tlb = rmw.tme_m68k_rmw_tlbs[0]; 979: 980: /* this TLB entry must allow fast reading and fast writing 981: to the same memory: */ 982: assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF 983: && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read); 984: 985: /* do the compare-and-exchange: */ 986: value_mem = 987: tme_memory_atomic_cx8(((tme_shared tme_uint8_t *) 988: (tlb->tme_m68k_tlb_emulator_off_read 989: + ic->_tme_m68k_ea_address)), 990: value_dc, 991: value_du, 992: tlb->tme_m68k_tlb_bus_rwlock, 993: sizeof(tme_uint8_t)); 994: ic->tme_m68k_ireg_memx8 = (value_mem); 995: } 996: 997: /* compare the compare operand to the effective address operand: */ 998: tme_m68k_cmp8(ic, &ic->tme_m68k_ireg_uint8(ireg_dc << 2), &ic->tme_m68k_ireg_memx8); 1.1 root 999: 1.1.1.4 root 1000: /* if the comparison succeeded: */ 1.1 root 1001: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 1002: 1003: /* write the update operand to the effective address operand: */ 1004: ic->tme_m68k_ireg_memx8 = ic->tme_m68k_ireg_uint8(ireg_du << 2); 1.1 root 1005: } 1006: 1.1.1.4 root 1007: /* otherwise, the comparison failed: */ 1008: else { 1.1 root 1009: 1.1.1.4 root 1010: /* write the effective address operand to the compare operand: */ 1011: ic->tme_m68k_ireg_uint8(ireg_dc << 2) = ic->tme_m68k_ireg_memx8; 1012: } 1013: 1014: /* finish the read/modify/write cycle: */ 1015: tme_m68k_rmw_finish(ic, 1016: &rmw, 1017: (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0); 1.1 root 1018: TME_M68K_INSN_OK; 1019: } 1020: 1021: /* moves8: */ 1022: TME_M68K_INSN(tme_m68k_moves8) 1023: { 1024: int ireg; 1.1.1.4 root 1025: tme_uint8_t ireg_value; 1.1.1.3 root 1026: unsigned int ea_reg; 1027: unsigned int increment; 1028: TME_M68K_INSN_PRIV; 1029: TME_M68K_INSN_CANFAULT; 1.1 root 1030: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 1.1.1.3 root 1031: 1.1.1.4 root 1032: /* in case we're storing the same address register used in a 1033: postincrement or predecrement EA, save the current value 1034: of the register now: */ 1035: ireg_value = ic->tme_m68k_ireg_uint8(ireg << 2); 1036: 1.1.1.3 root 1037: /* we have to handle postincrement and predecrement ourselves: */ 1038: if (!TME_M68K_SEQUENCE_RESTARTING) { 1039: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 1040: increment = TME_M68K_SIZE_8; 1041: if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { 1042: increment = TME_M68K_SIZE_16; 1043: } 1044: switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { 1045: case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; 1046: case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; 1047: default: break; 1048: } 1049: } 1050: 1.1 root 1051: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 1.1.1.3 root 1052: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 1053: ic->tme_m68k_ireg_memx8 = ireg_value; 1.1.1.3 root 1054: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; 1055: } 1056: tme_m68k_write_memx8(ic); 1.1 root 1057: } 1058: else { 1.1.1.3 root 1059: if (!TME_M68K_SEQUENCE_RESTARTING) { 1060: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; 1061: } 1062: tme_m68k_read_memx8(ic); 1.1 root 1063: if (ireg >= TME_M68K_IREG_A0) { 1064: ic->tme_m68k_ireg_uint32(ireg) = 1065: TME_EXT_S8_U32((tme_int8_t) ic->tme_m68k_ireg_memx8); 1066: } 1067: else 1068: ic->tme_m68k_ireg_uint8(ireg << 2) = ic->tme_m68k_ireg_memx8; 1069: } 1070: TME_M68K_INSN_OK; 1071: } 1072: 1073: /* this does a 16-bit "add SRC, DST": */ 1074: TME_M68K_INSN(tme_m68k_add16) 1075: { 1076: tme_uint16_t res, op0, op1; 1077: tme_uint8_t flags; 1078: 1079: /* load the operand(s): */ 1080: op0 = *((tme_uint16_t *) _op0); 1081: op1 = *((tme_uint16_t *) _op1); 1082: 1083: /* perform the operation: */ 1084: res = op1 + op0; 1085: 1086: /* store the result: */ 1087: *((tme_uint16_t *) _op1) = res; 1088: 1089: /* set the flags: */ 1090: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1091: if (res == 0) flags |= TME_M68K_FLAG_Z; 1092: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffff) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1093: if (op0 > (op1 ^ 0xffff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1094: ic->tme_m68k_ireg_ccr = flags; 1095: 1096: TME_M68K_INSN_OK; 1097: } 1098: 1099: /* this does a 16-bit "sub SRC, DST": */ 1100: TME_M68K_INSN(tme_m68k_sub16) 1101: { 1102: tme_uint16_t res, op0, op1; 1103: tme_uint8_t flags; 1104: 1105: /* load the operand(s): */ 1106: op0 = *((tme_uint16_t *) _op0); 1107: op1 = *((tme_uint16_t *) _op1); 1108: 1109: /* perform the operation: */ 1110: res = op1 - op0; 1111: 1112: /* store the result: */ 1113: *((tme_uint16_t *) _op1) = res; 1114: 1115: /* set the flags: */ 1116: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1117: if (res == 0) flags |= TME_M68K_FLAG_Z; 1118: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1119: if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1120: ic->tme_m68k_ireg_ccr = flags; 1121: 1122: TME_M68K_INSN_OK; 1123: } 1124: 1125: /* this does a 16-bit "cmp SRC, DST": */ 1126: TME_M68K_INSN(tme_m68k_cmp16) 1127: { 1128: tme_uint16_t res, op0, op1; 1129: tme_uint8_t flags; 1130: 1131: /* load the operand(s): */ 1132: op0 = *((tme_uint16_t *) _op0); 1133: op1 = *((tme_uint16_t *) _op1); 1134: 1135: /* perform the operation: */ 1136: res = op1 - op0; 1137: 1138: /* set the flags: */ 1139: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1140: if (res == 0) flags |= TME_M68K_FLAG_Z; 1141: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1142: if (op0 > op1) flags |= TME_M68K_FLAG_C; 1143: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1144: ic->tme_m68k_ireg_ccr = flags; 1145: 1146: TME_M68K_INSN_OK; 1147: } 1148: 1149: /* this does a 16-bit "neg DST": */ 1150: TME_M68K_INSN(tme_m68k_neg16) 1151: { 1152: tme_uint16_t res, op1; 1153: tme_uint8_t flags; 1154: 1155: /* load the operand(s): */ 1156: op1 = *((tme_uint16_t *) _op1); 1157: 1158: /* perform the operation: */ 1159: res = 0 - op1; 1160: 1161: /* store the result: */ 1162: *((tme_uint16_t *) _op1) = res; 1163: 1164: /* set the flags: */ 1165: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1166: if (res == 0) flags |= TME_M68K_FLAG_Z; 1167: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1168: if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1169: ic->tme_m68k_ireg_ccr = flags; 1170: 1171: TME_M68K_INSN_OK; 1172: } 1173: 1174: /* this does a 16-bit "or SRC, DST": */ 1175: TME_M68K_INSN(tme_m68k_or16) 1176: { 1177: tme_uint16_t res, op0, op1; 1178: tme_uint8_t flags; 1179: 1180: /* load the operand(s): */ 1181: op0 = *((tme_uint16_t *) _op0); 1182: op1 = *((tme_uint16_t *) _op1); 1183: 1184: /* perform the operation: */ 1185: res = op1 | op0; 1186: 1187: /* store the result: */ 1188: *((tme_uint16_t *) _op1) = res; 1189: 1190: /* set the flags: */ 1191: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1192: if (res == 0) flags |= TME_M68K_FLAG_Z; 1193: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1194: ic->tme_m68k_ireg_ccr = flags; 1195: 1196: TME_M68K_INSN_OK; 1197: } 1198: 1199: /* this does a 16-bit "and SRC, DST": */ 1200: TME_M68K_INSN(tme_m68k_and16) 1201: { 1202: tme_uint16_t res, op0, op1; 1203: tme_uint8_t flags; 1204: 1205: /* load the operand(s): */ 1206: op0 = *((tme_uint16_t *) _op0); 1207: op1 = *((tme_uint16_t *) _op1); 1208: 1209: /* perform the operation: */ 1210: res = op1 & op0; 1211: 1212: /* store the result: */ 1213: *((tme_uint16_t *) _op1) = res; 1214: 1215: /* set the flags: */ 1216: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1217: if (res == 0) flags |= TME_M68K_FLAG_Z; 1218: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1219: ic->tme_m68k_ireg_ccr = flags; 1220: 1221: TME_M68K_INSN_OK; 1222: } 1223: 1224: /* this does a 16-bit "eor SRC, DST": */ 1225: TME_M68K_INSN(tme_m68k_eor16) 1226: { 1227: tme_uint16_t res, op0, op1; 1228: tme_uint8_t flags; 1229: 1230: /* load the operand(s): */ 1231: op0 = *((tme_uint16_t *) _op0); 1232: op1 = *((tme_uint16_t *) _op1); 1233: 1234: /* perform the operation: */ 1235: res = op1 ^ op0; 1236: 1237: /* store the result: */ 1238: *((tme_uint16_t *) _op1) = res; 1239: 1240: /* set the flags: */ 1241: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1242: if (res == 0) flags |= TME_M68K_FLAG_Z; 1243: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1244: ic->tme_m68k_ireg_ccr = flags; 1245: 1246: TME_M68K_INSN_OK; 1247: } 1248: 1249: /* this does a 16-bit "not DST": */ 1250: TME_M68K_INSN(tme_m68k_not16) 1251: { 1252: tme_uint16_t res, op1; 1253: tme_uint8_t flags; 1254: 1255: /* load the operand(s): */ 1256: op1 = *((tme_uint16_t *) _op1); 1257: 1258: /* perform the operation: */ 1259: res = ~ op1; 1260: 1261: /* store the result: */ 1262: *((tme_uint16_t *) _op1) = res; 1263: 1264: /* set the flags: */ 1265: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1266: if (res == 0) flags |= TME_M68K_FLAG_Z; 1267: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1268: ic->tme_m68k_ireg_ccr = flags; 1269: 1270: TME_M68K_INSN_OK; 1271: } 1272: 1273: /* this does a 16-bit "tst DST": */ 1274: TME_M68K_INSN(tme_m68k_tst16) 1275: { 1276: tme_uint16_t res, op1; 1277: tme_uint8_t flags; 1278: 1279: /* load the operand(s): */ 1280: op1 = *((tme_uint16_t *) _op1); 1281: 1282: /* perform the operation: */ 1283: res = op1; 1284: 1285: /* set the flags: */ 1286: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1287: if (res == 0) flags |= TME_M68K_FLAG_Z; 1288: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1289: ic->tme_m68k_ireg_ccr = flags; 1290: 1291: TME_M68K_INSN_OK; 1292: } 1293: 1294: /* this does a 16-bit "move DST": */ 1295: TME_M68K_INSN(tme_m68k_move16) 1296: { 1297: tme_uint16_t res, op1; 1298: tme_uint8_t flags; 1299: 1300: /* load the operand(s): */ 1301: op1 = *((tme_uint16_t *) _op1); 1302: 1303: /* perform the operation: */ 1304: res = op1; 1305: 1306: /* store the result: */ 1307: *((tme_uint16_t *) _op0) = res; 1308: 1309: /* set the flags: */ 1310: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1311: if (res == 0) flags |= TME_M68K_FLAG_Z; 1312: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1313: ic->tme_m68k_ireg_ccr = flags; 1314: 1315: TME_M68K_INSN_OK; 1316: } 1317: 1318: /* this does a 16-bit "clr DST": */ 1319: TME_M68K_INSN(tme_m68k_clr16) 1320: { 1321: tme_uint16_t res; 1322: tme_uint8_t flags; 1323: 1324: /* load the operand(s): */ 1325: 1326: /* perform the operation: */ 1327: res = 0; 1328: 1329: /* store the result: */ 1330: *((tme_uint16_t *) _op1) = res; 1331: 1332: /* set the flags: */ 1333: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1334: if (res == 0) flags |= TME_M68K_FLAG_Z; 1335: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1336: ic->tme_m68k_ireg_ccr = flags; 1337: 1338: TME_M68K_INSN_OK; 1339: } 1340: 1341: /* this does a 16-bit "cmpa SRC, DST": */ 1342: TME_M68K_INSN(tme_m68k_cmpa16) 1343: { 1344: tme_uint32_t res, op0, op1; 1345: tme_uint8_t flags; 1346: 1347: /* load the operand(s): */ 1348: op0 = (tme_uint32_t) ((tme_int32_t) *((tme_int16_t *) _op0)); 1349: op1 = *((tme_uint32_t *) _op1); 1350: 1351: /* perform the operation: */ 1352: res = op1 - op0; 1353: 1354: /* set the flags: */ 1355: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 1356: if (res == 0) flags |= TME_M68K_FLAG_Z; 1357: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 1358: if (op0 > op1) flags |= TME_M68K_FLAG_C; 1359: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1360: ic->tme_m68k_ireg_ccr = flags; 1361: 1362: TME_M68K_INSN_OK; 1363: } 1364: 1365: /* this does a 16-bit "negx DST": */ 1366: TME_M68K_INSN(tme_m68k_negx16) 1367: { 1368: tme_uint16_t res, op1; 1369: tme_uint8_t flags; 1370: 1371: /* load the operand(s): */ 1372: op1 = *((tme_uint16_t *) _op1); 1373: 1374: /* perform the operation: */ 1375: res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 1376: 1377: /* store the result: */ 1378: *((tme_uint16_t *) _op1) = res; 1379: 1380: /* set the flags: */ 1381: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1382: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 1383: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1384: if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1385: ic->tme_m68k_ireg_ccr = flags; 1386: 1387: TME_M68K_INSN_OK; 1388: } 1389: 1390: /* this does a 16-bit "addx SRC, DST": */ 1391: TME_M68K_INSN(tme_m68k_addx16) 1392: { 1393: tme_uint16_t res, op0, op1; 1394: tme_uint8_t flags; 1395: 1396: /* load the operand(s): */ 1397: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 1398: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 1399: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 1400: tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t); 1401: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t); 1402: tme_uint16_t memory; 1403: 1404: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 1405: if (memory) { 1406: TME_M68K_INSN_CANFAULT; 1407: if (!TME_M68K_SEQUENCE_RESTARTING) { 1408: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 1409: ic->_tme_m68k_ea_function_code = function_code; 1410: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 1411: } 1412: tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16); 1.1.1.4 root 1413: if (!TME_M68K_SEQUENCE_RESTARTING) { 1414: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 1415: ic->_tme_m68k_ea_function_code = function_code; 1416: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 1417: } 1418: tme_m68k_read_memx16(ic); 1.1 root 1419: op1 = ic->tme_m68k_ireg_memx16; 1420: op0 = ic->tme_m68k_ireg_memy16; 1421: } 1422: else { 1423: op0 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_src) << 1); 1424: op1 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1); 1425: } 1426: 1427: /* perform the operation: */ 1428: res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 1429: 1430: /* store the result: */ 1431: if (memory) { 1432: if (!TME_M68K_SEQUENCE_RESTARTING) { 1433: ic->tme_m68k_ireg_memx16 = res; 1434: ic->_tme_m68k_ea_function_code = function_code; 1435: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 1436: } 1437: tme_m68k_write_memx16(ic); 1438: } 1439: else { 1440: ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1) = res; 1441: } 1442: 1443: /* set the flags: */ 1444: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1445: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 1446: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffff) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1447: if (op0 > (op1 ^ 0xffff) || (op0 == (op1 ^ 0xffff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1448: ic->tme_m68k_ireg_ccr = flags; 1449: 1450: TME_M68K_INSN_OK; 1451: } 1452: 1453: /* this does a 16-bit "subx SRC, DST": */ 1454: TME_M68K_INSN(tme_m68k_subx16) 1455: { 1456: tme_uint16_t res, op0, op1; 1457: tme_uint8_t flags; 1458: 1459: /* load the operand(s): */ 1460: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 1461: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 1462: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 1463: tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t); 1464: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t); 1465: tme_uint16_t memory; 1466: 1467: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 1468: if (memory) { 1469: TME_M68K_INSN_CANFAULT; 1470: if (!TME_M68K_SEQUENCE_RESTARTING) { 1471: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 1472: ic->_tme_m68k_ea_function_code = function_code; 1473: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 1474: } 1475: tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16); 1.1.1.4 root 1476: if (!TME_M68K_SEQUENCE_RESTARTING) { 1477: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 1478: ic->_tme_m68k_ea_function_code = function_code; 1479: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 1480: } 1481: tme_m68k_read_memx16(ic); 1.1 root 1482: op1 = ic->tme_m68k_ireg_memx16; 1483: op0 = ic->tme_m68k_ireg_memy16; 1484: } 1485: else { 1486: op0 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_src) << 1); 1487: op1 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1); 1488: } 1489: 1490: /* perform the operation: */ 1491: res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 1492: 1493: /* store the result: */ 1494: if (memory) { 1495: if (!TME_M68K_SEQUENCE_RESTARTING) { 1496: ic->tme_m68k_ireg_memx16 = res; 1497: ic->_tme_m68k_ea_function_code = function_code; 1498: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 1499: } 1500: tme_m68k_write_memx16(ic); 1501: } 1502: else { 1503: ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1) = res; 1504: } 1505: 1506: /* set the flags: */ 1507: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1508: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 1509: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1510: if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 1511: ic->tme_m68k_ireg_ccr = flags; 1512: 1513: TME_M68K_INSN_OK; 1514: } 1515: 1516: /* this does a 16-bit "cmpm SRC, DST": */ 1517: TME_M68K_INSN(tme_m68k_cmpm16) 1518: { 1519: tme_uint16_t res, op0, op1; 1520: tme_uint8_t flags; 1521: 1522: /* load the operand(s): */ 1523: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 1524: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 1525: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 1526: tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t); 1527: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t); 1528: 1529: TME_M68K_INSN_CANFAULT; 1530: 1531: if (!TME_M68K_SEQUENCE_RESTARTING) { 1532: ic->_tme_m68k_ea_function_code = function_code; 1533: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 1534: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust; 1535: } 1536: tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16); 1.1.1.4 root 1537: if (!TME_M68K_SEQUENCE_RESTARTING) { 1538: ic->_tme_m68k_ea_function_code = function_code; 1539: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 1540: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust; 1541: } 1542: tme_m68k_read_memx16(ic); 1.1 root 1543: op1 = ic->tme_m68k_ireg_memx16; 1544: op0 = ic->tme_m68k_ireg_memy16; 1545: 1546: /* perform the operation: */ 1547: res = op1 - op0; 1548: 1549: /* set the flags: */ 1550: flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1551: if (res == 0) flags |= TME_M68K_FLAG_Z; 1552: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V; 1553: if (op0 > op1) flags |= TME_M68K_FLAG_C; 1554: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 1555: ic->tme_m68k_ireg_ccr = flags; 1556: 1557: TME_M68K_INSN_OK; 1558: } 1559: 1.1.1.4 root 1560: /* a move of an address register to a predecrement or 1561: postincrement EA with that same address register, must 1562: store the original value of the address register. since the 1563: predecrement and postincrement code in the executer updates 1564: the address register before the move has happened, we wrap 1565: the normal move function in this one, that gives an op1 1566: argument that is the original value of the address register: */ 1567: TME_M68K_INSN(tme_m68k_move_srpd16) 1568: { 1569: /* NB: both this function and tme_m68k_move16() 1570: get the source operand as _op1, and the destination 1571: operand as _op0: */ 1572: if (!TME_M68K_SEQUENCE_RESTARTING) { 1573: *((tme_uint16_t *) _op0) 1574: = (*((tme_uint16_t *) _op1) 1575: + sizeof(tme_uint16_t)); 1576: } 1577: tme_m68k_move16(ic, _op0, _op0); 1578: } 1579: 1580: /* a move of an address register to a predecrement or 1581: postincrement EA with that same address register, must 1582: store the original value of the address register. since the 1583: predecrement and postincrement code in the executer updates 1584: the address register before the move has happened, we wrap 1585: the normal move function in this one, that gives an op1 1586: argument that is the original value of the address register: */ 1587: TME_M68K_INSN(tme_m68k_move_srpi16) 1588: { 1589: /* NB: both this function and tme_m68k_move16() 1590: get the source operand as _op1, and the destination 1591: operand as _op0: */ 1592: if (!TME_M68K_SEQUENCE_RESTARTING) { 1593: *((tme_uint16_t *) _op0) 1594: = (*((tme_uint16_t *) _op1) 1595: - sizeof(tme_uint16_t)); 1596: } 1597: tme_m68k_move16(ic, _op0, _op0); 1598: } 1599: 1.1 root 1600: /* the suba function on a 16-byte EA: */ 1601: TME_M68K_INSN(tme_m68k_suba16) 1602: { 1603: *((tme_int32_t *) _op1) -= *((tme_int16_t *) _op0); 1604: TME_M68K_INSN_OK; 1605: } 1606: 1607: /* the adda function on a 16-byte EA: */ 1608: TME_M68K_INSN(tme_m68k_adda16) 1609: { 1610: *((tme_int32_t *) _op1) += *((tme_int16_t *) _op0); 1611: TME_M68K_INSN_OK; 1612: } 1613: 1614: /* the movea function on a 16-byte EA: */ 1615: TME_M68K_INSN(tme_m68k_movea16) 1616: { 1617: *((tme_int32_t *) _op0) = *((tme_int16_t *) _op1); 1618: TME_M68K_INSN_OK; 1619: } 1620: 1621: /* the asl function on a 16-byte EA: */ 1622: TME_M68K_INSN(tme_m68k_asl16) 1623: { 1624: unsigned int count; 1.1.1.2 root 1625: tme_uint16_t sign_bits, sign_bits_mask; 1.1 root 1626: tme_uint16_t res; 1627: tme_uint8_t flags; 1628: 1629: /* get the count and operand: */ 1630: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1631: res = TME_M68K_INSN_OP1(tme_uint16_t); 1632: 1633: /* generate the X, V, and C flags assuming the count is zero: */ 1634: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1635: 1636: /* if the count is nonzero, update the result and 1637: generate the X, V, and C flags: */ 1638: if (count > 0) { 1639: 1640: /* we need to see how the sign of the result will change during 1641: shifting in order to generate V. 1642: 1643: in general, the idea is to get all of the bits that will ever 1.1.1.2 root 1644: appear in the sign position into sign_bits, with a mask in 1645: sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or 1646: sign_bits_mask, clear V, else set V. 1.1 root 1647: 1.1.1.2 root 1648: start by loading the operand into sign_bits and setting 1649: sign_bits_mask to all-bits-one. 1.1 root 1650: 1651: if the shift count is exactly 16 - 1, then all of the bits 1652: of the operand will appear in the sign position. 1653: 1654: if the shift count is less than 16 - 1, then some of the 1655: less significant bits of the operand will never appear in the 1.1.1.2 root 1656: sign position, so we can shift sign_bits_mask to ignore them. 1.1 root 1657: 1658: if the shift count is greater than 16 - 1, then all of the 1659: bits in the operand, plus at least one zero bit, will appear in 1660: the sign position. the only way that the sign bit will never 1661: change during the shift is if the operand was zero to begin with. 1.1.1.2 root 1662: without any changes to sign_bits or sign_bits_mask, the final 1663: test will always work, except when sign_bits is all-bits-one. 1664: the magic below clears the least-significant bit of sign_bits 1665: iff sign_bits is all-bits-one: */ 1.1 root 1666: sign_bits = res; 1667: if (63 > SHIFTMAX_INT16_T 1668: && count > 16) { 1669: res = 0; 1670: } 1671: res <<= (count - 1); 1672: flags = (res >> (16 - 1)); 1673: flags *= TME_M68K_FLAG_C; 1674: flags |= (flags * TME_M68K_FLAG_X); 1675: res <<= 1; 1.1.1.2 root 1676: sign_bits_mask = (tme_uint16_t) -1; 1.1 root 1677: if (count != 16 - 1) { 1678: if (count < 16) { 1.1.1.2 root 1679: sign_bits_mask <<= ((16 - 1) - count); 1.1 root 1680: } 1681: else { 1.1.1.2 root 1682: sign_bits ^= !(sign_bits + 1); 1.1 root 1683: } 1684: } 1.1.1.2 root 1685: sign_bits &= sign_bits_mask; 1686: if (sign_bits != 0 && sign_bits != sign_bits_mask) { 1.1 root 1687: flags |= TME_M68K_FLAG_V; 1688: } 1689: } 1690: 1691: /* store the result: */ 1692: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1693: 1694: /* generate the N flag. we cast to tme_uint8_t as soon as we 1695: know the bit we want is within the range of the type, to try 1696: to affect the generated assembly: */ 1697: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1698: 1699: /* generate the Z flag: */ 1700: if (res == 0) flags |= TME_M68K_FLAG_Z; 1701: 1702: /* store the flags: */ 1703: ic->tme_m68k_ireg_ccr = flags; 1704: TME_M68K_INSN_OK; 1705: } 1706: 1707: /* the asr function on a 16-byte EA: */ 1708: TME_M68K_INSN(tme_m68k_asr16) 1709: { 1710: unsigned int count; 1711: tme_int16_t res; 1712: tme_uint8_t flags; 1713: 1714: /* get the count and operand: */ 1715: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1716: res = TME_M68K_INSN_OP1(tme_int16_t); 1717: 1718: /* generate the X, V, and C flags assuming the count is zero: */ 1719: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1720: 1721: /* if the count is nonzero, update the result and 1722: generate the X, V, and C flags: */ 1723: if (count > 0) { 1724: if (63 > SHIFTMAX_INT16_T 1725: && count > 16) { 1.1.1.3 root 1726: res = 0 - (res < 0); 1.1 root 1727: } 1.1.1.3 root 1728: #ifdef SHIFTSIGNED_INT16_T 1.1 root 1729: res >>= (count - 1); 1.1.1.3 root 1730: #else /* !SHIFTSIGNED_INT16_T */ 1731: for (; --count > 0; ) { 1732: res = (res & ~((tme_int16_t) 1)) / 2; 1733: } 1734: #endif /* !SHIFTSIGNED_INT16_T */ 1.1 root 1735: flags = (res & 1); 1736: flags *= TME_M68K_FLAG_C; 1737: flags |= (flags * TME_M68K_FLAG_X); 1.1.1.3 root 1738: #ifdef SHIFTSIGNED_INT16_T 1.1 root 1739: res >>= 1; 1.1.1.3 root 1740: #else /* !SHIFTSIGNED_INT16_T */ 1741: res = (res & ~((tme_int16_t) 1)) / 2; 1742: #endif /* !SHIFTSIGNED_INT16_T */ 1.1 root 1743: } 1744: 1745: /* store the result: */ 1746: TME_M68K_INSN_OP1(tme_int16_t) = res; 1747: 1748: /* generate the N flag. we cast to tme_uint8_t as soon as we 1749: know the bit we want is within the range of the type, to try 1750: to affect the generated assembly: */ 1751: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1752: 1753: /* generate the Z flag: */ 1754: if (res == 0) flags |= TME_M68K_FLAG_Z; 1755: 1756: /* store the flags: */ 1757: ic->tme_m68k_ireg_ccr = flags; 1758: TME_M68K_INSN_OK; 1759: } 1760: 1761: /* the lsl function on a 16-byte EA: */ 1762: TME_M68K_INSN(tme_m68k_lsl16) 1763: { 1764: unsigned int count; 1765: tme_uint16_t res; 1766: tme_uint8_t flags; 1767: 1768: /* get the count and operand: */ 1769: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1770: res = TME_M68K_INSN_OP1(tme_uint16_t); 1771: 1772: /* generate the X, V, and C flags assuming the count is zero: */ 1773: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1774: 1775: /* if the count is nonzero, update the result and 1776: generate the X, V, and C flags: */ 1777: if (count > 0) { 1778: if (63 > SHIFTMAX_INT16_T 1779: && count > 16) { 1780: res = 0; 1781: } 1782: res <<= (count - 1); 1783: flags = (res >> (16 - 1)); 1784: flags *= TME_M68K_FLAG_C; 1785: flags |= (flags * TME_M68K_FLAG_X); 1786: res <<= 1; 1787: } 1788: 1789: /* store the result: */ 1790: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1791: 1792: /* generate the N flag. we cast to tme_uint8_t as soon as we 1793: know the bit we want is within the range of the type, to try 1794: to affect the generated assembly: */ 1795: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1796: 1797: /* generate the Z flag: */ 1798: if (res == 0) flags |= TME_M68K_FLAG_Z; 1799: 1800: /* store the flags: */ 1801: ic->tme_m68k_ireg_ccr = flags; 1802: TME_M68K_INSN_OK; 1803: } 1804: 1805: /* the lsr function on a 16-byte EA: */ 1806: TME_M68K_INSN(tme_m68k_lsr16) 1807: { 1808: unsigned int count; 1809: tme_uint16_t res; 1810: tme_uint8_t flags; 1811: 1812: /* get the count and operand: */ 1813: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1814: res = TME_M68K_INSN_OP1(tme_uint16_t); 1815: 1816: /* generate the X, V, and C flags assuming the count is zero: */ 1817: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1818: 1819: /* if the count is nonzero, update the result and 1820: generate the X, V, and C flags: */ 1821: if (count > 0) { 1822: if (63 > SHIFTMAX_INT16_T 1823: && count > 16) { 1824: res = 0; 1825: } 1826: res >>= (count - 1); 1827: flags = (res & 1); 1828: flags *= TME_M68K_FLAG_C; 1829: flags |= (flags * TME_M68K_FLAG_X); 1830: res >>= 1; 1831: } 1832: 1833: /* store the result: */ 1834: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1835: 1836: /* generate the N flag. we cast to tme_uint8_t as soon as we 1837: know the bit we want is within the range of the type, to try 1838: to affect the generated assembly: */ 1839: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1840: 1841: /* generate the Z flag: */ 1842: if (res == 0) flags |= TME_M68K_FLAG_Z; 1843: 1844: /* store the flags: */ 1845: ic->tme_m68k_ireg_ccr = flags; 1846: TME_M68K_INSN_OK; 1847: } 1848: 1849: /* the rol function on a 16-byte EA: */ 1850: TME_M68K_INSN(tme_m68k_rol16) 1851: { 1852: unsigned int count; 1853: tme_uint16_t res; 1854: tme_uint8_t flags; 1855: 1856: /* get the count and operand: */ 1857: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1858: res = TME_M68K_INSN_OP1(tme_uint16_t); 1859: 1860: /* generate the X, V, and C flags assuming the count is zero: */ 1861: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1862: 1863: /* if the count is nonzero, update the result and 1864: generate the X, V, and C flags: */ 1865: if (count > 0) { 1866: count &= (16 - 1); 1867: res = (res << count) | (res >> (16 - count)); 1868: flags |= ((res & 1) * TME_M68K_FLAG_C); 1869: } 1870: 1871: /* store the result: */ 1872: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1873: 1874: /* generate the N flag. we cast to tme_uint8_t as soon as we 1875: know the bit we want is within the range of the type, to try 1876: to affect the generated assembly: */ 1877: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1878: 1879: /* generate the Z flag: */ 1880: if (res == 0) flags |= TME_M68K_FLAG_Z; 1881: 1882: /* store the flags: */ 1883: ic->tme_m68k_ireg_ccr = flags; 1884: TME_M68K_INSN_OK; 1885: } 1886: 1887: /* the ror function on a 16-byte EA: */ 1888: TME_M68K_INSN(tme_m68k_ror16) 1889: { 1890: unsigned int count; 1891: tme_uint16_t res; 1892: tme_uint8_t flags; 1893: 1894: /* get the count and operand: */ 1895: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1896: res = TME_M68K_INSN_OP1(tme_uint16_t); 1897: 1898: /* generate the X, V, and C flags assuming the count is zero: */ 1899: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1900: 1901: /* if the count is nonzero, update the result and 1902: generate the X, V, and C flags: */ 1903: if (count > 0) { 1904: count &= (16 - 1); 1905: res = (res << (16 - count)) | (res >> count); 1906: flags |= ((res >> (16 - 1)) * TME_M68K_FLAG_C); 1907: } 1908: 1909: /* store the result: */ 1910: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1911: 1912: /* generate the N flag. we cast to tme_uint8_t as soon as we 1913: know the bit we want is within the range of the type, to try 1914: to affect the generated assembly: */ 1915: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1916: 1917: /* generate the Z flag: */ 1918: if (res == 0) flags |= TME_M68K_FLAG_Z; 1919: 1920: /* store the flags: */ 1921: ic->tme_m68k_ireg_ccr = flags; 1922: TME_M68K_INSN_OK; 1923: } 1924: 1925: /* the roxl function on a 16-byte EA: */ 1926: TME_M68K_INSN(tme_m68k_roxl16) 1927: { 1928: unsigned int count; 1929: tme_uint8_t xbit; 1930: tme_uint16_t res; 1931: tme_uint8_t flags; 1932: 1933: /* get the count and operand: */ 1934: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1935: res = TME_M68K_INSN_OP1(tme_uint16_t); 1936: 1937: /* generate the X, V, and C flags assuming the count is zero: */ 1938: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1939: xbit = (flags / TME_M68K_FLAG_X); 1940: flags |= (xbit * TME_M68K_FLAG_C); 1941: 1942: /* if the count is nonzero, update the result and 1943: generate the X, V, and C flags: */ 1944: if (count > 0) { 1945: count %= (16 + 1); 1946: flags = xbit; 1947: if (count > 0) { 1948: flags = (res >> (16 - count)) & 1; 1949: if (16 > SHIFTMAX_INT16_T 1950: && count == 16) { 1951: res = 0 | (xbit << (16 - 1)) | (res >> ((16 + 1) - 16)); 1952: } 1953: else if (16 > SHIFTMAX_INT16_T 1954: && count == 1) { 1955: res = (res << 1) | (xbit << (1 - 1)) | 0; 1956: } 1957: else { 1958: res = (res << count) | (xbit << (count - 1)) | (res >> ((16 + 1) - count)); 1959: } 1960: } 1961: flags *= TME_M68K_FLAG_C; 1962: flags |= (flags * TME_M68K_FLAG_X); 1963: } 1964: 1965: /* store the result: */ 1966: TME_M68K_INSN_OP1(tme_uint16_t) = res; 1967: 1968: /* generate the N flag. we cast to tme_uint8_t as soon as we 1969: know the bit we want is within the range of the type, to try 1970: to affect the generated assembly: */ 1971: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 1972: 1973: /* generate the Z flag: */ 1974: if (res == 0) flags |= TME_M68K_FLAG_Z; 1975: 1976: /* store the flags: */ 1977: ic->tme_m68k_ireg_ccr = flags; 1978: TME_M68K_INSN_OK; 1979: } 1980: 1981: /* the roxr function on a 16-byte EA: */ 1982: TME_M68K_INSN(tme_m68k_roxr16) 1983: { 1984: unsigned int count; 1985: tme_uint8_t xbit; 1986: tme_uint16_t res; 1987: tme_uint8_t flags; 1988: 1989: /* get the count and operand: */ 1990: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 1991: res = TME_M68K_INSN_OP1(tme_uint16_t); 1992: 1993: /* generate the X, V, and C flags assuming the count is zero: */ 1994: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1995: xbit = (flags / TME_M68K_FLAG_X); 1996: flags |= (xbit * TME_M68K_FLAG_C); 1997: 1998: /* if the count is nonzero, update the result and 1999: generate the X, V, and C flags: */ 2000: if (count > 0) { 2001: count %= (16 + 1); 2002: flags = xbit; 2003: if (count > 0) { 2004: flags = (res >> (count - 1)) & 1; 2005: if (16 > SHIFTMAX_INT16_T 2006: && count == 16) { 2007: res = (res << ((16 + 1) - 16)) | (xbit << (16 - 16)) | 0; 2008: } 2009: else if (16 > SHIFTMAX_INT16_T 2010: && count == 1) { 2011: res = 0 | (xbit << (16 - 1)) | (res >> 1); 2012: } 2013: else { 2014: res = (res << ((16 + 1) - count)) | (xbit << (16 - count)) | (res >> count); 2015: } 2016: } 2017: flags *= TME_M68K_FLAG_C; 2018: flags |= (flags * TME_M68K_FLAG_X); 2019: } 2020: 2021: /* store the result: */ 2022: TME_M68K_INSN_OP1(tme_uint16_t) = res; 2023: 2024: /* generate the N flag. we cast to tme_uint8_t as soon as we 2025: know the bit we want is within the range of the type, to try 2026: to affect the generated assembly: */ 2027: flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N; 2028: 2029: /* generate the Z flag: */ 2030: if (res == 0) flags |= TME_M68K_FLAG_Z; 2031: 2032: /* store the flags: */ 2033: ic->tme_m68k_ireg_ccr = flags; 2034: TME_M68K_INSN_OK; 2035: } 2036: 2037: /* the movep_rm function on a 16-bit dreg: */ 2038: TME_M68K_INSN(tme_m68k_movep_rm16) 2039: { 2040: unsigned int function_code; 2041: tme_uint32_t linear_address; 2042: tme_uint16_t value; 2043: int dreg; 2044: 2045: TME_M68K_INSN_CANFAULT; 2046: 2047: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2048: linear_address = TME_M68K_INSN_OP1(tme_uint32_t); 2049: linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP); 2050: dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 2051: value = ic->tme_m68k_ireg_uint16(dreg << 1); 2052: if (!TME_M68K_SEQUENCE_RESTARTING) { 2053: ic->_tme_m68k_ea_function_code = function_code; 2054: ic->_tme_m68k_ea_address = linear_address; 2055: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 8, 8); 2056: } 2057: tme_m68k_write_memx8(ic); 2058: linear_address += 2; 2059: if (!TME_M68K_SEQUENCE_RESTARTING) { 2060: ic->_tme_m68k_ea_function_code = function_code; 2061: ic->_tme_m68k_ea_address = linear_address; 2062: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 0, 8); 2063: } 2064: tme_m68k_write_memx8(ic); 2065: linear_address += 2; 2066: TME_M68K_INSN_OK; 2067: } 2068: 2069: /* the movem_rm function on 16-bit registers: */ 2070: TME_M68K_INSN(tme_m68k_movem_rm16) 2071: { 2072: int ireg, direction; 2073: tme_uint16_t mask, bit; 2074: unsigned int ea_mode; 2075: tme_uint32_t addend; 1.1.1.4 root 2076: tme_uint32_t total_size; 2077: /* get the register mask, and figure out the total size 2078: of the transfer: */ 2079: mask = TME_M68K_INSN_SPECOP; 2080: total_size = 0; 2081: if (mask != 0) { 2082: TME_M68K_INSN_CANFAULT; 2083: bit = mask; 2084: do { 2085: total_size += sizeof(tme_uint16_t); 2086: bit &= (bit - 1); 2087: } while (bit != 0); 2088: } 1.1 root 2089: 2090: /* figure out what direction to move in, and where to start from: */ 2091: ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); 2092: direction = 1; 2093: ireg = TME_M68K_IREG_D0; 2094: if (ea_mode == 4) { 2095: direction = -1; 2096: ireg = TME_M68K_IREG_A7; 2097: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 2098: 2099: /* "For the MC68020, MC68030, MC68040, and CPU32, if 2100: the addressing register is also moved to memory, the 2101: value written is the initial register value decremented 2102: by the size of the operation. The MC68000 and MC68010 2103: write the initial register value (not decremented)." */ 2104: if (ic->tme_m68k_type >= TME_M68K_M68020) { 2105: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 2106: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 2107: = (ic->_tme_m68k_ea_address - total_size); 2108: } 2109: 2110: /* predecrement the effective address for the first transfer: */ 1.1 root 2111: ic->_tme_m68k_ea_address -= sizeof(tme_uint16_t); 2112: } 2113: } 2114: addend = (tme_uint32_t) (direction * sizeof(tme_uint16_t)); 2115: 2116: /* do the transfer: */ 2117: for (bit = 1; bit != 0; bit <<= 1) { 2118: if (mask & bit) { 2119: if (!TME_M68K_SEQUENCE_RESTARTING) { 2120: ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg << 1); 2121: } 2122: tme_m68k_write_memx16(ic); 2123: if (!TME_M68K_SEQUENCE_RESTARTING) { 2124: ic->_tme_m68k_ea_address += addend; 2125: } 2126: } 2127: ireg += direction; 2128: } 2129: 2130: /* if this is the predecrement mode, update the address register: */ 1.1.1.4 root 2131: /* "For the MC68020, MC68030, MC68040, and CPU32, if 2132: the addressing register is also moved to memory, the 2133: value written is the initial register value decremented 2134: by the size of the operation. The MC68000 and MC68010 2135: write the initial register value (not decremented)." */ 2136: if (ea_mode == 4 2137: && ic->tme_m68k_type < TME_M68K_M68020) { 1.1 root 2138: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 2139: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 2140: = (ic->_tme_m68k_ea_address + sizeof(tme_uint16_t)); 2141: } 2142: TME_M68K_INSN_OK; 2143: } 2144: 2145: /* the movep_mr function on a 16-bit dreg: */ 2146: TME_M68K_INSN(tme_m68k_movep_mr16) 2147: { 2148: unsigned int function_code; 2149: tme_uint32_t linear_address; 2150: int dreg; 2151: 2152: TME_M68K_INSN_CANFAULT; 2153: 2154: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2155: linear_address = TME_M68K_INSN_OP1(tme_uint32_t); 2156: linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP); 2157: dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 2158: if (!TME_M68K_SEQUENCE_RESTARTING) { 2159: ic->_tme_m68k_ea_function_code = function_code; 2160: ic->_tme_m68k_ea_address = linear_address; 2161: } 2162: tme_m68k_read_memx8(ic); 2163: if (!TME_M68K_SEQUENCE_RESTARTING) { 2164: TME_FIELD_DEPOSIT16(ic->tme_m68k_ireg_uint16(dreg << 1), 8, 8, ic->tme_m68k_ireg_memx8); 2165: } 2166: linear_address += 2; 2167: if (!TME_M68K_SEQUENCE_RESTARTING) { 2168: ic->_tme_m68k_ea_function_code = function_code; 2169: ic->_tme_m68k_ea_address = linear_address; 2170: } 2171: tme_m68k_read_memx8(ic); 2172: if (!TME_M68K_SEQUENCE_RESTARTING) { 2173: TME_FIELD_DEPOSIT16(ic->tme_m68k_ireg_uint16(dreg << 1), 0, 8, ic->tme_m68k_ireg_memx8); 2174: } 2175: linear_address += 2; 2176: TME_M68K_INSN_OK; 2177: } 2178: 2179: /* the movem_mr function on 16-bit registers: */ 2180: TME_M68K_INSN(tme_m68k_movem_mr16) 2181: { 2182: int ireg, direction; 2183: tme_uint16_t mask, bit; 2184: unsigned int ea_mode; 2185: tme_uint32_t addend; 1.1.1.4 root 2186: tme_uint32_t total_size; 2187: /* get the register mask, and figure out the total size 2188: of the transfer: */ 2189: mask = TME_M68K_INSN_SPECOP; 2190: total_size = 0; 2191: if (mask != 0) { 2192: TME_M68K_INSN_CANFAULT; 2193: bit = mask; 2194: do { 2195: total_size += sizeof(tme_uint16_t); 2196: bit &= (bit - 1); 2197: } while (bit != 0); 2198: } 1.1 root 2199: 2200: /* figure out what direction to move in, and where to start from: */ 2201: ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); 2202: direction = 1; 2203: ireg = TME_M68K_IREG_D0; 2204: addend = (tme_uint32_t) (direction * sizeof(tme_uint16_t)); 2205: 2206: /* do the transfer: */ 2207: for (bit = 1; bit != 0; bit <<= 1) { 2208: if (mask & bit) { 2209: tme_m68k_read_memx16(ic); 2210: if (!TME_M68K_SEQUENCE_RESTARTING) { 2211: ic->tme_m68k_ireg_uint32(ireg) = TME_EXT_S16_U32((tme_int16_t) ic->tme_m68k_ireg_memx16); 2212: ic->_tme_m68k_ea_address += addend; 2213: } 2214: } 2215: ireg += direction; 2216: } 2217: 2218: /* if this is the postincrement mode, update the address register: */ 2219: if (ea_mode == 3) { 2220: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 2221: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 2222: = ic->_tme_m68k_ea_address; 2223: } 2224: TME_M68K_INSN_OK; 2225: } 2226: 2227: /* chk16: */ 2228: TME_M68K_INSN(tme_m68k_chk16) 2229: { 2230: if (*((tme_int16_t *) _op0) < 0) { 2231: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N; 1.1.1.3 root 2232: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 2233: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 2234: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 2235: } 2236: if (*((tme_int16_t *) _op0) > *((tme_int16_t *) _op1)) { 2237: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N; 1.1.1.3 root 2238: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 2239: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 2240: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 2241: } 2242: TME_M68K_INSN_OK; 2243: } 2244: 2245: /* cas16: */ 2246: TME_M68K_INSN(tme_m68k_cas16) 2247: { 1.1.1.4 root 2248: struct tme_m68k_rmw rmw; 1.1 root 2249: struct tme_m68k_tlb *tlb; 2250: int ireg_dc, ireg_du; 1.1.1.4 root 2251: tme_uint16_t value_dc, value_du, value_mem; 1.1 root 2252: 2253: /* start the read/modify/write cycle: */ 1.1.1.4 root 2254: rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address; 2255: rmw.tme_m68k_rmw_address_count = 1; 2256: rmw.tme_m68k_rmw_size = sizeof(tme_uint16_t); 2257: if (tme_m68k_rmw_start(ic, 2258: &rmw)) { 1.1 root 2259: TME_M68K_INSN_OK; 2260: } 2261: 1.1.1.4 root 2262: /* get the compare and update registers: */ 2263: ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 2264: ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3); 2265: 2266: /* if we can do the fast compare-and-exchange: */ 2267: if (!rmw.tme_m68k_rmw_slow_reads[0]) { 2268: 2269: /* get the compare and update values in big-endian byte order: */ 2270: value_dc = ic->tme_m68k_ireg_uint16(ireg_dc << 1); 2271: value_du = ic->tme_m68k_ireg_uint16(ireg_du << 1); 2272: value_dc = tme_htobe_u16(value_dc); 2273: value_du = tme_htobe_u16(value_du); 2274: 2275: /* get this TLB entry: */ 2276: tlb = rmw.tme_m68k_rmw_tlbs[0]; 2277: 2278: /* this TLB entry must allow fast reading and fast writing 2279: to the same memory: */ 2280: assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF 2281: && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read); 2282: 2283: /* do the compare-and-exchange: */ 2284: value_mem = 2285: tme_memory_atomic_cx16(((tme_shared tme_uint16_t *) 2286: (tlb->tme_m68k_tlb_emulator_off_read 2287: + ic->_tme_m68k_ea_address)), 2288: value_dc, 2289: value_du, 2290: tlb->tme_m68k_tlb_bus_rwlock, 2291: sizeof(tme_uint8_t)); 2292: ic->tme_m68k_ireg_memx16 = tme_betoh_u16(value_mem); 2293: } 2294: 2295: /* compare the compare operand to the effective address operand: */ 2296: tme_m68k_cmp16(ic, &ic->tme_m68k_ireg_uint16(ireg_dc << 1), &ic->tme_m68k_ireg_memx16); 1.1 root 2297: 1.1.1.4 root 2298: /* if the comparison succeeded: */ 1.1 root 2299: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 2300: 2301: /* write the update operand to the effective address operand: */ 2302: ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg_du << 1); 1.1 root 2303: } 2304: 1.1.1.4 root 2305: /* otherwise, the comparison failed: */ 2306: else { 2307: 2308: /* write the effective address operand to the compare operand: */ 2309: ic->tme_m68k_ireg_uint16(ireg_dc << 1) = ic->tme_m68k_ireg_memx16; 2310: } 1.1 root 2311: 1.1.1.4 root 2312: /* finish the read/modify/write cycle: */ 2313: tme_m68k_rmw_finish(ic, 2314: &rmw, 2315: (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0); 1.1 root 2316: TME_M68K_INSN_OK; 2317: } 2318: 2319: /* cas2_16: */ 2320: TME_M68K_INSN(tme_m68k_cas2_16) 2321: { 1.1.1.4 root 2322: struct tme_m68k_rmw rmw; 2323: int ireg_dcx, ireg_dux; 2324: int ireg_dcy, ireg_duy; 2325: const tme_uint16_t specopx = TME_M68K_INSN_SPECOP; 2326: const tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t); 1.1 root 2327: 2328: /* start the read/modify/write cycle: */ 1.1.1.4 root 2329: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2330: rmw.tme_m68k_rmw_addresses[0] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 2331: + TME_FIELD_EXTRACTU(specopx, 12, 4)); 2332: rmw.tme_m68k_rmw_addresses[1] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 2333: + TME_FIELD_EXTRACTU(specopy, 12, 4)); 2334: rmw.tme_m68k_rmw_address_count = 2; 2335: rmw.tme_m68k_rmw_size = sizeof(tme_uint16_t); 2336: if (tme_m68k_rmw_start(ic, 2337: &rmw)) { 1.1 root 2338: TME_M68K_INSN_OK; 2339: } 2340: 1.1.1.4 root 2341: /* do the comparisons: */ 2342: ireg_dcx = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 0, 3); 2343: ireg_dcy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 0, 3); 2344: tme_m68k_cmp16(ic, 2345: &ic->tme_m68k_ireg_uint16(ireg_dcx << 1), 2346: &ic->tme_m68k_ireg_memx16); 1.1 root 2347: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 2348: tme_m68k_cmp16(ic, 2349: &ic->tme_m68k_ireg_uint16(ireg_dcy << 1), 2350: &ic->tme_m68k_ireg_memy16); 1.1 root 2351: } 2352: 1.1.1.4 root 2353: /* if the comparisons succeeded: */ 1.1 root 2354: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 2355: 2356: /* write the update operands to the effective address operands: */ 2357: ireg_dux = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 6, 3); 2358: ireg_duy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 6, 3); 2359: ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg_dux << 1); 2360: ic->tme_m68k_ireg_memy16 = ic->tme_m68k_ireg_uint16(ireg_duy << 1); 1.1 root 2361: } 2362: 1.1.1.4 root 2363: /* otherwise, the comparisons failed: */ 2364: else { 1.1 root 2365: 1.1.1.4 root 2366: /* write the effective address operands to the compare operands. 2367: "If Dc1 and Dc2 specify the same data register and the comparison 2368: fails, memory operand 1 is stored in the data register." */ 2369: ic->tme_m68k_ireg_uint16(ireg_dcy << 1) = ic->tme_m68k_ireg_memy16; 2370: ic->tme_m68k_ireg_uint16(ireg_dcx << 1) = ic->tme_m68k_ireg_memx16; 2371: } 2372: 2373: /* finish the read/modify/write cycle: */ 2374: tme_m68k_rmw_finish(ic, 2375: &rmw, 2376: (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0); 1.1 root 2377: TME_M68K_INSN_OK; 2378: } 2379: 2380: /* moves16: */ 2381: TME_M68K_INSN(tme_m68k_moves16) 2382: { 2383: int ireg; 1.1.1.4 root 2384: tme_uint16_t ireg_value; 1.1.1.3 root 2385: unsigned int ea_reg; 2386: unsigned int increment; 2387: TME_M68K_INSN_PRIV; 2388: TME_M68K_INSN_CANFAULT; 1.1 root 2389: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 1.1.1.3 root 2390: 1.1.1.4 root 2391: /* in case we're storing the same address register used in a 2392: postincrement or predecrement EA, save the current value 2393: of the register now: */ 2394: ireg_value = ic->tme_m68k_ireg_uint16(ireg << 1); 2395: 1.1.1.3 root 2396: /* we have to handle postincrement and predecrement ourselves: */ 2397: if (!TME_M68K_SEQUENCE_RESTARTING) { 2398: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 2399: increment = TME_M68K_SIZE_16; 2400: if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { 2401: increment = TME_M68K_SIZE_16; 2402: } 2403: switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { 2404: case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; 2405: case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; 2406: default: break; 2407: } 2408: } 2409: 1.1 root 2410: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 1.1.1.3 root 2411: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 2412: ic->tme_m68k_ireg_memx16 = ireg_value; 1.1.1.3 root 2413: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; 2414: } 2415: tme_m68k_write_memx16(ic); 1.1 root 2416: } 2417: else { 1.1.1.3 root 2418: if (!TME_M68K_SEQUENCE_RESTARTING) { 2419: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; 2420: } 2421: tme_m68k_read_memx16(ic); 1.1 root 2422: if (ireg >= TME_M68K_IREG_A0) { 2423: ic->tme_m68k_ireg_uint32(ireg) = 2424: TME_EXT_S16_U32((tme_int16_t) ic->tme_m68k_ireg_memx16); 2425: } 2426: else 2427: ic->tme_m68k_ireg_uint16(ireg << 1) = ic->tme_m68k_ireg_memx16; 2428: } 2429: TME_M68K_INSN_OK; 2430: } 2431: 2432: /* this does a 32-bit "add SRC, DST": */ 2433: TME_M68K_INSN(tme_m68k_add32) 2434: { 2435: tme_uint32_t res, op0, op1; 2436: tme_uint8_t flags; 2437: 2438: /* load the operand(s): */ 2439: op0 = *((tme_uint32_t *) _op0); 2440: op1 = *((tme_uint32_t *) _op1); 2441: 2442: /* perform the operation: */ 2443: res = op1 + op0; 2444: 2445: /* store the result: */ 2446: *((tme_uint32_t *) _op1) = res; 2447: 2448: /* set the flags: */ 2449: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2450: if (res == 0) flags |= TME_M68K_FLAG_Z; 2451: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffffffff) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2452: if (op0 > (op1 ^ 0xffffffff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2453: ic->tme_m68k_ireg_ccr = flags; 2454: 2455: TME_M68K_INSN_OK; 2456: } 2457: 2458: /* this does a 32-bit "sub SRC, DST": */ 2459: TME_M68K_INSN(tme_m68k_sub32) 2460: { 2461: tme_uint32_t res, op0, op1; 2462: tme_uint8_t flags; 2463: 2464: /* load the operand(s): */ 2465: op0 = *((tme_uint32_t *) _op0); 2466: op1 = *((tme_uint32_t *) _op1); 2467: 2468: /* perform the operation: */ 2469: res = op1 - op0; 2470: 2471: /* store the result: */ 2472: *((tme_uint32_t *) _op1) = res; 2473: 2474: /* set the flags: */ 2475: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2476: if (res == 0) flags |= TME_M68K_FLAG_Z; 2477: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2478: if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2479: ic->tme_m68k_ireg_ccr = flags; 2480: 2481: TME_M68K_INSN_OK; 2482: } 2483: 2484: /* this does a 32-bit "cmp SRC, DST": */ 2485: TME_M68K_INSN(tme_m68k_cmp32) 2486: { 2487: tme_uint32_t res, op0, op1; 2488: tme_uint8_t flags; 2489: 2490: /* load the operand(s): */ 2491: op0 = *((tme_uint32_t *) _op0); 2492: op1 = *((tme_uint32_t *) _op1); 2493: 2494: /* perform the operation: */ 2495: res = op1 - op0; 2496: 2497: /* set the flags: */ 2498: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2499: if (res == 0) flags |= TME_M68K_FLAG_Z; 2500: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2501: if (op0 > op1) flags |= TME_M68K_FLAG_C; 2502: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2503: ic->tme_m68k_ireg_ccr = flags; 2504: 2505: TME_M68K_INSN_OK; 2506: } 2507: 2508: /* this does a 32-bit "neg DST": */ 2509: TME_M68K_INSN(tme_m68k_neg32) 2510: { 2511: tme_uint32_t res, op1; 2512: tme_uint8_t flags; 2513: 2514: /* load the operand(s): */ 2515: op1 = *((tme_uint32_t *) _op1); 2516: 2517: /* perform the operation: */ 2518: res = 0 - op1; 2519: 2520: /* store the result: */ 2521: *((tme_uint32_t *) _op1) = res; 2522: 2523: /* set the flags: */ 2524: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2525: if (res == 0) flags |= TME_M68K_FLAG_Z; 2526: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2527: if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2528: ic->tme_m68k_ireg_ccr = flags; 2529: 2530: TME_M68K_INSN_OK; 2531: } 2532: 2533: /* this does a 32-bit "or SRC, DST": */ 2534: TME_M68K_INSN(tme_m68k_or32) 2535: { 2536: tme_uint32_t res, op0, op1; 2537: tme_uint8_t flags; 2538: 2539: /* load the operand(s): */ 2540: op0 = *((tme_uint32_t *) _op0); 2541: op1 = *((tme_uint32_t *) _op1); 2542: 2543: /* perform the operation: */ 2544: res = op1 | op0; 2545: 2546: /* store the result: */ 2547: *((tme_uint32_t *) _op1) = res; 2548: 2549: /* set the flags: */ 2550: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2551: if (res == 0) flags |= TME_M68K_FLAG_Z; 2552: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2553: ic->tme_m68k_ireg_ccr = flags; 2554: 2555: TME_M68K_INSN_OK; 2556: } 2557: 2558: /* this does a 32-bit "and SRC, DST": */ 2559: TME_M68K_INSN(tme_m68k_and32) 2560: { 2561: tme_uint32_t res, op0, op1; 2562: tme_uint8_t flags; 2563: 2564: /* load the operand(s): */ 2565: op0 = *((tme_uint32_t *) _op0); 2566: op1 = *((tme_uint32_t *) _op1); 2567: 2568: /* perform the operation: */ 2569: res = op1 & op0; 2570: 2571: /* store the result: */ 2572: *((tme_uint32_t *) _op1) = res; 2573: 2574: /* set the flags: */ 2575: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2576: if (res == 0) flags |= TME_M68K_FLAG_Z; 2577: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2578: ic->tme_m68k_ireg_ccr = flags; 2579: 2580: TME_M68K_INSN_OK; 2581: } 2582: 2583: /* this does a 32-bit "eor SRC, DST": */ 2584: TME_M68K_INSN(tme_m68k_eor32) 2585: { 2586: tme_uint32_t res, op0, op1; 2587: tme_uint8_t flags; 2588: 2589: /* load the operand(s): */ 2590: op0 = *((tme_uint32_t *) _op0); 2591: op1 = *((tme_uint32_t *) _op1); 2592: 2593: /* perform the operation: */ 2594: res = op1 ^ op0; 2595: 2596: /* store the result: */ 2597: *((tme_uint32_t *) _op1) = res; 2598: 2599: /* set the flags: */ 2600: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2601: if (res == 0) flags |= TME_M68K_FLAG_Z; 2602: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2603: ic->tme_m68k_ireg_ccr = flags; 2604: 2605: TME_M68K_INSN_OK; 2606: } 2607: 2608: /* this does a 32-bit "not DST": */ 2609: TME_M68K_INSN(tme_m68k_not32) 2610: { 2611: tme_uint32_t res, op1; 2612: tme_uint8_t flags; 2613: 2614: /* load the operand(s): */ 2615: op1 = *((tme_uint32_t *) _op1); 2616: 2617: /* perform the operation: */ 2618: res = ~ op1; 2619: 2620: /* store the result: */ 2621: *((tme_uint32_t *) _op1) = res; 2622: 2623: /* set the flags: */ 2624: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2625: if (res == 0) flags |= TME_M68K_FLAG_Z; 2626: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2627: ic->tme_m68k_ireg_ccr = flags; 2628: 2629: TME_M68K_INSN_OK; 2630: } 2631: 2632: /* this does a 32-bit "tst DST": */ 2633: TME_M68K_INSN(tme_m68k_tst32) 2634: { 2635: tme_uint32_t res, op1; 2636: tme_uint8_t flags; 2637: 2638: /* load the operand(s): */ 2639: op1 = *((tme_uint32_t *) _op1); 2640: 2641: /* perform the operation: */ 2642: res = op1; 2643: 2644: /* set the flags: */ 2645: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2646: if (res == 0) flags |= TME_M68K_FLAG_Z; 2647: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2648: ic->tme_m68k_ireg_ccr = flags; 2649: 2650: TME_M68K_INSN_OK; 2651: } 2652: 2653: /* this does a 32-bit "move DST": */ 2654: TME_M68K_INSN(tme_m68k_move32) 2655: { 2656: tme_uint32_t res, op1; 2657: tme_uint8_t flags; 2658: 2659: /* load the operand(s): */ 2660: op1 = *((tme_uint32_t *) _op1); 2661: 2662: /* perform the operation: */ 2663: res = op1; 2664: 2665: /* store the result: */ 2666: *((tme_uint32_t *) _op0) = res; 2667: 2668: /* set the flags: */ 2669: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2670: if (res == 0) flags |= TME_M68K_FLAG_Z; 2671: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2672: ic->tme_m68k_ireg_ccr = flags; 2673: 2674: TME_M68K_INSN_OK; 2675: } 2676: 2677: /* this does a 32-bit "moveq DST": */ 2678: TME_M68K_INSN(tme_m68k_moveq32) 2679: { 2680: tme_uint32_t res; 2681: tme_uint8_t flags; 2682: 2683: /* load the operand(s): */ 2684: 2685: /* perform the operation: */ 2686: res = TME_EXT_S8_U32((tme_int8_t) (TME_M68K_INSN_OPCODE & 0xff)); 2687: 2688: /* store the result: */ 2689: *((tme_uint32_t *) _op1) = res; 2690: 2691: /* set the flags: */ 2692: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2693: if (res == 0) flags |= TME_M68K_FLAG_Z; 2694: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2695: ic->tme_m68k_ireg_ccr = flags; 2696: 2697: TME_M68K_INSN_OK; 2698: } 2699: 2700: /* this does a 32-bit "clr DST": */ 2701: TME_M68K_INSN(tme_m68k_clr32) 2702: { 2703: tme_uint32_t res; 2704: tme_uint8_t flags; 2705: 2706: /* load the operand(s): */ 2707: 2708: /* perform the operation: */ 2709: res = 0; 2710: 2711: /* store the result: */ 2712: *((tme_uint32_t *) _op1) = res; 2713: 2714: /* set the flags: */ 2715: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2716: if (res == 0) flags |= TME_M68K_FLAG_Z; 2717: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2718: ic->tme_m68k_ireg_ccr = flags; 2719: 2720: TME_M68K_INSN_OK; 2721: } 2722: 2723: /* this does a 32-bit "negx DST": */ 2724: TME_M68K_INSN(tme_m68k_negx32) 2725: { 2726: tme_uint32_t res, op1; 2727: tme_uint8_t flags; 2728: 2729: /* load the operand(s): */ 2730: op1 = *((tme_uint32_t *) _op1); 2731: 2732: /* perform the operation: */ 2733: res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 2734: 2735: /* store the result: */ 2736: *((tme_uint32_t *) _op1) = res; 2737: 2738: /* set the flags: */ 2739: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2740: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 2741: flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2742: if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2743: ic->tme_m68k_ireg_ccr = flags; 2744: 2745: TME_M68K_INSN_OK; 2746: } 2747: 2748: /* this does a 32-bit "addx SRC, DST": */ 2749: TME_M68K_INSN(tme_m68k_addx32) 2750: { 2751: tme_uint32_t res, op0, op1; 2752: tme_uint8_t flags; 2753: 2754: /* load the operand(s): */ 2755: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2756: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 2757: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 2758: tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t); 2759: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t); 2760: tme_uint16_t memory; 2761: 2762: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 2763: if (memory) { 2764: TME_M68K_INSN_CANFAULT; 2765: if (!TME_M68K_SEQUENCE_RESTARTING) { 2766: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 2767: ic->_tme_m68k_ea_function_code = function_code; 2768: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 2769: } 2770: tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32); 1.1.1.4 root 2771: if (!TME_M68K_SEQUENCE_RESTARTING) { 2772: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 2773: ic->_tme_m68k_ea_function_code = function_code; 2774: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 2775: } 2776: tme_m68k_read_memx32(ic); 1.1 root 2777: op1 = ic->tme_m68k_ireg_memx32; 2778: op0 = ic->tme_m68k_ireg_memy32; 2779: } 2780: else { 2781: op0 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_src)); 2782: op1 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)); 2783: } 2784: 2785: /* perform the operation: */ 2786: res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 2787: 2788: /* store the result: */ 2789: if (memory) { 2790: if (!TME_M68K_SEQUENCE_RESTARTING) { 2791: ic->tme_m68k_ireg_memx32 = res; 2792: ic->_tme_m68k_ea_function_code = function_code; 2793: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 2794: } 2795: tme_m68k_write_memx32(ic); 2796: } 2797: else { 2798: ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)) = res; 2799: } 2800: 2801: /* set the flags: */ 2802: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2803: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 2804: flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffffffff) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2805: if (op0 > (op1 ^ 0xffffffff) || (op0 == (op1 ^ 0xffffffff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2806: ic->tme_m68k_ireg_ccr = flags; 2807: 2808: TME_M68K_INSN_OK; 2809: } 2810: 2811: /* this does a 32-bit "subx SRC, DST": */ 2812: TME_M68K_INSN(tme_m68k_subx32) 2813: { 2814: tme_uint32_t res, op0, op1; 2815: tme_uint8_t flags; 2816: 2817: /* load the operand(s): */ 2818: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2819: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 2820: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 2821: tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t); 2822: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t); 2823: tme_uint16_t memory; 2824: 2825: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)); 2826: if (memory) { 2827: TME_M68K_INSN_CANFAULT; 2828: if (!TME_M68K_SEQUENCE_RESTARTING) { 2829: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust; 2830: ic->_tme_m68k_ea_function_code = function_code; 2831: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 2832: } 2833: tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32); 1.1.1.4 root 2834: if (!TME_M68K_SEQUENCE_RESTARTING) { 2835: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust; 2836: ic->_tme_m68k_ea_function_code = function_code; 2837: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 2838: } 2839: tme_m68k_read_memx32(ic); 1.1 root 2840: op1 = ic->tme_m68k_ireg_memx32; 2841: op0 = ic->tme_m68k_ireg_memy32; 2842: } 2843: else { 2844: op0 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_src)); 2845: op1 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)); 2846: } 2847: 2848: /* perform the operation: */ 2849: res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1); 2850: 2851: /* store the result: */ 2852: if (memory) { 2853: if (!TME_M68K_SEQUENCE_RESTARTING) { 2854: ic->tme_m68k_ireg_memx32 = res; 2855: ic->_tme_m68k_ea_function_code = function_code; 2856: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 2857: } 2858: tme_m68k_write_memx32(ic); 2859: } 2860: else { 2861: ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)) = res; 2862: } 2863: 2864: /* set the flags: */ 2865: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2866: if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z); 2867: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2868: if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 2869: ic->tme_m68k_ireg_ccr = flags; 2870: 2871: TME_M68K_INSN_OK; 2872: } 2873: 2874: /* this does a 32-bit "cmpm SRC, DST": */ 2875: TME_M68K_INSN(tme_m68k_cmpm32) 2876: { 2877: tme_uint32_t res, op0, op1; 2878: tme_uint8_t flags; 2879: 2880: /* load the operand(s): */ 2881: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 2882: int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 2883: int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 2884: tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t); 2885: tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t); 2886: 2887: TME_M68K_INSN_CANFAULT; 2888: 2889: if (!TME_M68K_SEQUENCE_RESTARTING) { 2890: ic->_tme_m68k_ea_function_code = function_code; 2891: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src); 2892: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust; 2893: } 2894: tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32); 1.1.1.4 root 2895: if (!TME_M68K_SEQUENCE_RESTARTING) { 2896: ic->_tme_m68k_ea_function_code = function_code; 2897: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst); 2898: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust; 2899: } 2900: tme_m68k_read_memx32(ic); 1.1 root 2901: op1 = ic->tme_m68k_ireg_memx32; 2902: op0 = ic->tme_m68k_ireg_memy32; 2903: 2904: /* perform the operation: */ 2905: res = op1 - op0; 2906: 2907: /* set the flags: */ 2908: flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 2909: if (res == 0) flags |= TME_M68K_FLAG_Z; 2910: flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V; 2911: if (op0 > op1) flags |= TME_M68K_FLAG_C; 2912: flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X); 2913: ic->tme_m68k_ireg_ccr = flags; 2914: 2915: TME_M68K_INSN_OK; 2916: } 2917: 1.1.1.4 root 2918: /* a move of an address register to a predecrement or 2919: postincrement EA with that same address register, must 2920: store the original value of the address register. since the 2921: predecrement and postincrement code in the executer updates 2922: the address register before the move has happened, we wrap 2923: the normal move function in this one, that gives an op1 2924: argument that is the original value of the address register: */ 2925: TME_M68K_INSN(tme_m68k_move_srpd32) 2926: { 2927: /* NB: both this function and tme_m68k_move32() 2928: get the source operand as _op1, and the destination 2929: operand as _op0: */ 2930: if (!TME_M68K_SEQUENCE_RESTARTING) { 2931: *((tme_uint32_t *) _op0) 2932: = (*((tme_uint32_t *) _op1) 2933: + sizeof(tme_uint32_t)); 2934: } 2935: tme_m68k_move32(ic, _op0, _op0); 2936: } 2937: 2938: /* a move of an address register to a predecrement or 2939: postincrement EA with that same address register, must 2940: store the original value of the address register. since the 2941: predecrement and postincrement code in the executer updates 2942: the address register before the move has happened, we wrap 2943: the normal move function in this one, that gives an op1 2944: argument that is the original value of the address register: */ 2945: TME_M68K_INSN(tme_m68k_move_srpi32) 2946: { 2947: /* NB: both this function and tme_m68k_move32() 2948: get the source operand as _op1, and the destination 2949: operand as _op0: */ 2950: if (!TME_M68K_SEQUENCE_RESTARTING) { 2951: *((tme_uint32_t *) _op0) 2952: = (*((tme_uint32_t *) _op1) 2953: - sizeof(tme_uint32_t)); 2954: } 2955: tme_m68k_move32(ic, _op0, _op0); 2956: } 2957: 1.1 root 2958: /* the suba function on a 32-byte EA: */ 2959: TME_M68K_INSN(tme_m68k_suba32) 2960: { 2961: *((tme_int32_t *) _op1) -= *((tme_int32_t *) _op0); 2962: TME_M68K_INSN_OK; 2963: } 2964: 2965: /* the adda function on a 32-byte EA: */ 2966: TME_M68K_INSN(tme_m68k_adda32) 2967: { 2968: *((tme_int32_t *) _op1) += *((tme_int32_t *) _op0); 2969: TME_M68K_INSN_OK; 2970: } 2971: 2972: /* the movea function on a 32-byte EA: */ 2973: TME_M68K_INSN(tme_m68k_movea32) 2974: { 2975: *((tme_int32_t *) _op0) = *((tme_int32_t *) _op1); 2976: TME_M68K_INSN_OK; 2977: } 2978: 2979: /* the btst function on a 32-byte EA: */ 2980: TME_M68K_INSN(tme_m68k_btst32) 2981: { 2982: tme_uint32_t value, bit; 2983: bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1)); 2984: value = TME_M68K_INSN_OP1(tme_uint32_t); 2985: if (value & bit) { 2986: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 2987: } 2988: else { 2989: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 2990: } 2991: TME_M68K_INSN_OK; 2992: } 2993: 2994: /* the bchg function on a 32-byte EA: */ 2995: TME_M68K_INSN(tme_m68k_bchg32) 2996: { 2997: tme_uint32_t value, bit; 2998: bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1)); 2999: value = TME_M68K_INSN_OP1(tme_uint32_t); 3000: if (value & bit) { 3001: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 3002: } 3003: else { 3004: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 3005: } 3006: TME_M68K_INSN_OP1(tme_uint32_t) = value ^ bit; 3007: TME_M68K_INSN_OK; 3008: } 3009: 3010: /* the bclr function on a 32-byte EA: */ 3011: TME_M68K_INSN(tme_m68k_bclr32) 3012: { 3013: tme_uint32_t value, bit; 3014: bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1)); 3015: value = TME_M68K_INSN_OP1(tme_uint32_t); 3016: if (value & bit) { 3017: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 3018: } 3019: else { 3020: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 3021: } 3022: TME_M68K_INSN_OP1(tme_uint32_t) = value & ~bit; 3023: TME_M68K_INSN_OK; 3024: } 3025: 3026: /* the bset function on a 32-byte EA: */ 3027: TME_M68K_INSN(tme_m68k_bset32) 3028: { 3029: tme_uint32_t value, bit; 3030: bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1)); 3031: value = TME_M68K_INSN_OP1(tme_uint32_t); 3032: if (value & bit) { 3033: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z; 3034: } 3035: else { 3036: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z; 3037: } 3038: TME_M68K_INSN_OP1(tme_uint32_t) = value | bit; 3039: TME_M68K_INSN_OK; 3040: } 3041: 3042: /* the asl function on a 32-byte EA: */ 3043: TME_M68K_INSN(tme_m68k_asl32) 3044: { 3045: unsigned int count; 1.1.1.2 root 3046: tme_uint32_t sign_bits, sign_bits_mask; 1.1 root 3047: tme_uint32_t res; 3048: tme_uint8_t flags; 3049: 3050: /* get the count and operand: */ 3051: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3052: res = TME_M68K_INSN_OP1(tme_uint32_t); 3053: 3054: /* generate the X, V, and C flags assuming the count is zero: */ 3055: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3056: 3057: /* if the count is nonzero, update the result and 3058: generate the X, V, and C flags: */ 3059: if (count > 0) { 3060: 3061: /* we need to see how the sign of the result will change during 3062: shifting in order to generate V. 3063: 3064: in general, the idea is to get all of the bits that will ever 1.1.1.2 root 3065: appear in the sign position into sign_bits, with a mask in 3066: sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or 3067: sign_bits_mask, clear V, else set V. 1.1 root 3068: 1.1.1.2 root 3069: start by loading the operand into sign_bits and setting 3070: sign_bits_mask to all-bits-one. 1.1 root 3071: 3072: if the shift count is exactly 32 - 1, then all of the bits 3073: of the operand will appear in the sign position. 3074: 3075: if the shift count is less than 32 - 1, then some of the 3076: less significant bits of the operand will never appear in the 1.1.1.2 root 3077: sign position, so we can shift sign_bits_mask to ignore them. 1.1 root 3078: 3079: if the shift count is greater than 32 - 1, then all of the 3080: bits in the operand, plus at least one zero bit, will appear in 3081: the sign position. the only way that the sign bit will never 3082: change during the shift is if the operand was zero to begin with. 1.1.1.2 root 3083: without any changes to sign_bits or sign_bits_mask, the final 3084: test will always work, except when sign_bits is all-bits-one. 3085: the magic below clears the least-significant bit of sign_bits 3086: iff sign_bits is all-bits-one: */ 1.1 root 3087: sign_bits = res; 3088: if (63 > SHIFTMAX_INT32_T 3089: && count > 32) { 3090: res = 0; 3091: } 3092: res <<= (count - 1); 3093: flags = (res >> (32 - 1)); 3094: flags *= TME_M68K_FLAG_C; 3095: flags |= (flags * TME_M68K_FLAG_X); 3096: res <<= 1; 1.1.1.2 root 3097: sign_bits_mask = (tme_uint32_t) -1; 1.1 root 3098: if (count != 32 - 1) { 3099: if (count < 32) { 1.1.1.2 root 3100: sign_bits_mask <<= ((32 - 1) - count); 1.1 root 3101: } 3102: else { 1.1.1.2 root 3103: sign_bits ^= !(sign_bits + 1); 1.1 root 3104: } 3105: } 1.1.1.2 root 3106: sign_bits &= sign_bits_mask; 3107: if (sign_bits != 0 && sign_bits != sign_bits_mask) { 1.1 root 3108: flags |= TME_M68K_FLAG_V; 3109: } 3110: } 3111: 3112: /* store the result: */ 3113: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3114: 3115: /* generate the N flag. we cast to tme_uint8_t as soon as we 3116: know the bit we want is within the range of the type, to try 3117: to affect the generated assembly: */ 3118: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3119: 3120: /* generate the Z flag: */ 3121: if (res == 0) flags |= TME_M68K_FLAG_Z; 3122: 3123: /* store the flags: */ 3124: ic->tme_m68k_ireg_ccr = flags; 3125: TME_M68K_INSN_OK; 3126: } 3127: 3128: /* the asr function on a 32-byte EA: */ 3129: TME_M68K_INSN(tme_m68k_asr32) 3130: { 3131: unsigned int count; 3132: tme_int32_t res; 3133: tme_uint8_t flags; 3134: 3135: /* get the count and operand: */ 3136: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3137: res = TME_M68K_INSN_OP1(tme_int32_t); 3138: 3139: /* generate the X, V, and C flags assuming the count is zero: */ 3140: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3141: 3142: /* if the count is nonzero, update the result and 3143: generate the X, V, and C flags: */ 3144: if (count > 0) { 3145: if (63 > SHIFTMAX_INT32_T 3146: && count > 32) { 1.1.1.3 root 3147: res = 0 - (res < 0); 1.1 root 3148: } 1.1.1.3 root 3149: #ifdef SHIFTSIGNED_INT32_T 1.1 root 3150: res >>= (count - 1); 1.1.1.3 root 3151: #else /* !SHIFTSIGNED_INT32_T */ 3152: for (; --count > 0; ) { 3153: res = (res & ~((tme_int32_t) 1)) / 2; 3154: } 3155: #endif /* !SHIFTSIGNED_INT32_T */ 1.1 root 3156: flags = (res & 1); 3157: flags *= TME_M68K_FLAG_C; 3158: flags |= (flags * TME_M68K_FLAG_X); 1.1.1.3 root 3159: #ifdef SHIFTSIGNED_INT32_T 1.1 root 3160: res >>= 1; 1.1.1.3 root 3161: #else /* !SHIFTSIGNED_INT32_T */ 3162: res = (res & ~((tme_int32_t) 1)) / 2; 3163: #endif /* !SHIFTSIGNED_INT32_T */ 1.1 root 3164: } 3165: 3166: /* store the result: */ 3167: TME_M68K_INSN_OP1(tme_int32_t) = res; 3168: 3169: /* generate the N flag. we cast to tme_uint8_t as soon as we 3170: know the bit we want is within the range of the type, to try 3171: to affect the generated assembly: */ 3172: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3173: 3174: /* generate the Z flag: */ 3175: if (res == 0) flags |= TME_M68K_FLAG_Z; 3176: 3177: /* store the flags: */ 3178: ic->tme_m68k_ireg_ccr = flags; 3179: TME_M68K_INSN_OK; 3180: } 3181: 3182: /* the lsl function on a 32-byte EA: */ 3183: TME_M68K_INSN(tme_m68k_lsl32) 3184: { 3185: unsigned int count; 3186: tme_uint32_t res; 3187: tme_uint8_t flags; 3188: 3189: /* get the count and operand: */ 3190: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3191: res = TME_M68K_INSN_OP1(tme_uint32_t); 3192: 3193: /* generate the X, V, and C flags assuming the count is zero: */ 3194: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3195: 3196: /* if the count is nonzero, update the result and 3197: generate the X, V, and C flags: */ 3198: if (count > 0) { 3199: if (63 > SHIFTMAX_INT32_T 3200: && count > 32) { 3201: res = 0; 3202: } 3203: res <<= (count - 1); 3204: flags = (res >> (32 - 1)); 3205: flags *= TME_M68K_FLAG_C; 3206: flags |= (flags * TME_M68K_FLAG_X); 3207: res <<= 1; 3208: } 3209: 3210: /* store the result: */ 3211: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3212: 3213: /* generate the N flag. we cast to tme_uint8_t as soon as we 3214: know the bit we want is within the range of the type, to try 3215: to affect the generated assembly: */ 3216: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3217: 3218: /* generate the Z flag: */ 3219: if (res == 0) flags |= TME_M68K_FLAG_Z; 3220: 3221: /* store the flags: */ 3222: ic->tme_m68k_ireg_ccr = flags; 3223: TME_M68K_INSN_OK; 3224: } 3225: 3226: /* the lsr function on a 32-byte EA: */ 3227: TME_M68K_INSN(tme_m68k_lsr32) 3228: { 3229: unsigned int count; 3230: tme_uint32_t res; 3231: tme_uint8_t flags; 3232: 3233: /* get the count and operand: */ 3234: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3235: res = TME_M68K_INSN_OP1(tme_uint32_t); 3236: 3237: /* generate the X, V, and C flags assuming the count is zero: */ 3238: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3239: 3240: /* if the count is nonzero, update the result and 3241: generate the X, V, and C flags: */ 3242: if (count > 0) { 3243: if (63 > SHIFTMAX_INT32_T 3244: && count > 32) { 3245: res = 0; 3246: } 3247: res >>= (count - 1); 3248: flags = (res & 1); 3249: flags *= TME_M68K_FLAG_C; 3250: flags |= (flags * TME_M68K_FLAG_X); 3251: res >>= 1; 3252: } 3253: 3254: /* store the result: */ 3255: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3256: 3257: /* generate the N flag. we cast to tme_uint8_t as soon as we 3258: know the bit we want is within the range of the type, to try 3259: to affect the generated assembly: */ 3260: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3261: 3262: /* generate the Z flag: */ 3263: if (res == 0) flags |= TME_M68K_FLAG_Z; 3264: 3265: /* store the flags: */ 3266: ic->tme_m68k_ireg_ccr = flags; 3267: TME_M68K_INSN_OK; 3268: } 3269: 3270: /* the rol function on a 32-byte EA: */ 3271: TME_M68K_INSN(tme_m68k_rol32) 3272: { 3273: unsigned int count; 3274: tme_uint32_t res; 3275: tme_uint8_t flags; 3276: 3277: /* get the count and operand: */ 3278: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3279: res = TME_M68K_INSN_OP1(tme_uint32_t); 3280: 3281: /* generate the X, V, and C flags assuming the count is zero: */ 3282: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3283: 3284: /* if the count is nonzero, update the result and 3285: generate the X, V, and C flags: */ 3286: if (count > 0) { 3287: count &= (32 - 1); 3288: res = (res << count) | (res >> (32 - count)); 3289: flags |= ((res & 1) * TME_M68K_FLAG_C); 3290: } 3291: 3292: /* store the result: */ 3293: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3294: 3295: /* generate the N flag. we cast to tme_uint8_t as soon as we 3296: know the bit we want is within the range of the type, to try 3297: to affect the generated assembly: */ 3298: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3299: 3300: /* generate the Z flag: */ 3301: if (res == 0) flags |= TME_M68K_FLAG_Z; 3302: 3303: /* store the flags: */ 3304: ic->tme_m68k_ireg_ccr = flags; 3305: TME_M68K_INSN_OK; 3306: } 3307: 3308: /* the ror function on a 32-byte EA: */ 3309: TME_M68K_INSN(tme_m68k_ror32) 3310: { 3311: unsigned int count; 3312: tme_uint32_t res; 3313: tme_uint8_t flags; 3314: 3315: /* get the count and operand: */ 3316: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3317: res = TME_M68K_INSN_OP1(tme_uint32_t); 3318: 3319: /* generate the X, V, and C flags assuming the count is zero: */ 3320: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3321: 3322: /* if the count is nonzero, update the result and 3323: generate the X, V, and C flags: */ 3324: if (count > 0) { 3325: count &= (32 - 1); 3326: res = (res << (32 - count)) | (res >> count); 3327: flags |= ((res >> (32 - 1)) * TME_M68K_FLAG_C); 3328: } 3329: 3330: /* store the result: */ 3331: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3332: 3333: /* generate the N flag. we cast to tme_uint8_t as soon as we 3334: know the bit we want is within the range of the type, to try 3335: to affect the generated assembly: */ 3336: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3337: 3338: /* generate the Z flag: */ 3339: if (res == 0) flags |= TME_M68K_FLAG_Z; 3340: 3341: /* store the flags: */ 3342: ic->tme_m68k_ireg_ccr = flags; 3343: TME_M68K_INSN_OK; 3344: } 3345: 3346: /* the roxl function on a 32-byte EA: */ 3347: TME_M68K_INSN(tme_m68k_roxl32) 3348: { 3349: unsigned int count; 3350: tme_uint8_t xbit; 3351: tme_uint32_t res; 3352: tme_uint8_t flags; 3353: 3354: /* get the count and operand: */ 3355: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3356: res = TME_M68K_INSN_OP1(tme_uint32_t); 3357: 3358: /* generate the X, V, and C flags assuming the count is zero: */ 3359: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3360: xbit = (flags / TME_M68K_FLAG_X); 3361: flags |= (xbit * TME_M68K_FLAG_C); 3362: 3363: /* if the count is nonzero, update the result and 3364: generate the X, V, and C flags: */ 3365: if (count > 0) { 3366: count %= (32 + 1); 3367: flags = xbit; 3368: if (count > 0) { 3369: flags = (res >> (32 - count)) & 1; 3370: if (32 > SHIFTMAX_INT32_T 3371: && count == 32) { 3372: res = 0 | (xbit << (32 - 1)) | (res >> ((32 + 1) - 32)); 3373: } 3374: else if (32 > SHIFTMAX_INT32_T 3375: && count == 1) { 3376: res = (res << 1) | (xbit << (1 - 1)) | 0; 3377: } 3378: else { 3379: res = (res << count) | (xbit << (count - 1)) | (res >> ((32 + 1) - count)); 3380: } 3381: } 3382: flags *= TME_M68K_FLAG_C; 3383: flags |= (flags * TME_M68K_FLAG_X); 3384: } 3385: 3386: /* store the result: */ 3387: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3388: 3389: /* generate the N flag. we cast to tme_uint8_t as soon as we 3390: know the bit we want is within the range of the type, to try 3391: to affect the generated assembly: */ 3392: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3393: 3394: /* generate the Z flag: */ 3395: if (res == 0) flags |= TME_M68K_FLAG_Z; 3396: 3397: /* store the flags: */ 3398: ic->tme_m68k_ireg_ccr = flags; 3399: TME_M68K_INSN_OK; 3400: } 3401: 3402: /* the roxr function on a 32-byte EA: */ 3403: TME_M68K_INSN(tme_m68k_roxr32) 3404: { 3405: unsigned int count; 3406: tme_uint8_t xbit; 3407: tme_uint32_t res; 3408: tme_uint8_t flags; 3409: 3410: /* get the count and operand: */ 3411: count = TME_M68K_INSN_OP0(tme_uint8_t) & 63; 3412: res = TME_M68K_INSN_OP1(tme_uint32_t); 3413: 3414: /* generate the X, V, and C flags assuming the count is zero: */ 3415: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 3416: xbit = (flags / TME_M68K_FLAG_X); 3417: flags |= (xbit * TME_M68K_FLAG_C); 3418: 3419: /* if the count is nonzero, update the result and 3420: generate the X, V, and C flags: */ 3421: if (count > 0) { 3422: count %= (32 + 1); 3423: flags = xbit; 3424: if (count > 0) { 3425: flags = (res >> (count - 1)) & 1; 3426: if (32 > SHIFTMAX_INT32_T 3427: && count == 32) { 3428: res = (res << ((32 + 1) - 32)) | (xbit << (32 - 32)) | 0; 3429: } 3430: else if (32 > SHIFTMAX_INT32_T 3431: && count == 1) { 3432: res = 0 | (xbit << (32 - 1)) | (res >> 1); 3433: } 3434: else { 3435: res = (res << ((32 + 1) - count)) | (xbit << (32 - count)) | (res >> count); 3436: } 3437: } 3438: flags *= TME_M68K_FLAG_C; 3439: flags |= (flags * TME_M68K_FLAG_X); 3440: } 3441: 3442: /* store the result: */ 3443: TME_M68K_INSN_OP1(tme_uint32_t) = res; 3444: 3445: /* generate the N flag. we cast to tme_uint8_t as soon as we 3446: know the bit we want is within the range of the type, to try 3447: to affect the generated assembly: */ 3448: flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N; 3449: 3450: /* generate the Z flag: */ 3451: if (res == 0) flags |= TME_M68K_FLAG_Z; 3452: 3453: /* store the flags: */ 3454: ic->tme_m68k_ireg_ccr = flags; 3455: TME_M68K_INSN_OK; 3456: } 3457: 3458: /* the movep_rm function on a 32-bit dreg: */ 3459: TME_M68K_INSN(tme_m68k_movep_rm32) 3460: { 3461: unsigned int function_code; 3462: tme_uint32_t linear_address; 3463: tme_uint32_t value; 3464: int dreg; 3465: 3466: TME_M68K_INSN_CANFAULT; 3467: 3468: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 3469: linear_address = TME_M68K_INSN_OP1(tme_uint32_t); 3470: linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP); 3471: dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 3472: value = ic->tme_m68k_ireg_uint32(dreg); 3473: if (!TME_M68K_SEQUENCE_RESTARTING) { 3474: ic->_tme_m68k_ea_function_code = function_code; 3475: ic->_tme_m68k_ea_address = linear_address; 3476: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 24, 8); 3477: } 3478: tme_m68k_write_memx8(ic); 3479: linear_address += 2; 3480: if (!TME_M68K_SEQUENCE_RESTARTING) { 3481: ic->_tme_m68k_ea_function_code = function_code; 3482: ic->_tme_m68k_ea_address = linear_address; 3483: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 16, 8); 3484: } 3485: tme_m68k_write_memx8(ic); 3486: linear_address += 2; 3487: if (!TME_M68K_SEQUENCE_RESTARTING) { 3488: ic->_tme_m68k_ea_function_code = function_code; 3489: ic->_tme_m68k_ea_address = linear_address; 3490: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 8, 8); 3491: } 3492: tme_m68k_write_memx8(ic); 3493: linear_address += 2; 3494: if (!TME_M68K_SEQUENCE_RESTARTING) { 3495: ic->_tme_m68k_ea_function_code = function_code; 3496: ic->_tme_m68k_ea_address = linear_address; 3497: ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 0, 8); 3498: } 3499: tme_m68k_write_memx8(ic); 3500: linear_address += 2; 3501: TME_M68K_INSN_OK; 3502: } 3503: 3504: /* the movem_rm function on 32-bit registers: */ 3505: TME_M68K_INSN(tme_m68k_movem_rm32) 3506: { 3507: int ireg, direction; 3508: tme_uint16_t mask, bit; 3509: unsigned int ea_mode; 3510: tme_uint32_t addend; 1.1.1.4 root 3511: tme_uint32_t total_size; 3512: /* get the register mask, and figure out the total size 3513: of the transfer: */ 3514: mask = TME_M68K_INSN_SPECOP; 3515: total_size = 0; 3516: if (mask != 0) { 3517: TME_M68K_INSN_CANFAULT; 3518: bit = mask; 3519: do { 3520: total_size += sizeof(tme_uint32_t); 3521: bit &= (bit - 1); 3522: } while (bit != 0); 3523: } 1.1 root 3524: 3525: /* figure out what direction to move in, and where to start from: */ 3526: ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); 3527: direction = 1; 3528: ireg = TME_M68K_IREG_D0; 3529: if (ea_mode == 4) { 3530: direction = -1; 3531: ireg = TME_M68K_IREG_A7; 3532: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 3533: 3534: /* "For the MC68020, MC68030, MC68040, and CPU32, if 3535: the addressing register is also moved to memory, the 3536: value written is the initial register value decremented 3537: by the size of the operation. The MC68000 and MC68010 3538: write the initial register value (not decremented)." */ 3539: if (ic->tme_m68k_type >= TME_M68K_M68020) { 3540: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 3541: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 3542: = (ic->_tme_m68k_ea_address - total_size); 3543: } 3544: 3545: /* predecrement the effective address for the first transfer: */ 1.1 root 3546: ic->_tme_m68k_ea_address -= sizeof(tme_uint32_t); 3547: } 3548: } 3549: addend = (tme_uint32_t) (direction * sizeof(tme_uint32_t)); 3550: 3551: /* do the transfer: */ 3552: for (bit = 1; bit != 0; bit <<= 1) { 3553: if (mask & bit) { 3554: if (!TME_M68K_SEQUENCE_RESTARTING) { 3555: ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg); 3556: } 3557: tme_m68k_write_memx32(ic); 3558: if (!TME_M68K_SEQUENCE_RESTARTING) { 3559: ic->_tme_m68k_ea_address += addend; 3560: } 3561: } 3562: ireg += direction; 3563: } 3564: 3565: /* if this is the predecrement mode, update the address register: */ 1.1.1.4 root 3566: /* "For the MC68020, MC68030, MC68040, and CPU32, if 3567: the addressing register is also moved to memory, the 3568: value written is the initial register value decremented 3569: by the size of the operation. The MC68000 and MC68010 3570: write the initial register value (not decremented)." */ 3571: if (ea_mode == 4 3572: && ic->tme_m68k_type < TME_M68K_M68020) { 1.1 root 3573: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 3574: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 3575: = (ic->_tme_m68k_ea_address + sizeof(tme_uint32_t)); 3576: } 3577: TME_M68K_INSN_OK; 3578: } 3579: 3580: /* the movep_mr function on a 32-bit dreg: */ 3581: TME_M68K_INSN(tme_m68k_movep_mr32) 3582: { 3583: unsigned int function_code; 3584: tme_uint32_t linear_address; 3585: int dreg; 3586: 3587: TME_M68K_INSN_CANFAULT; 3588: 3589: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 3590: linear_address = TME_M68K_INSN_OP1(tme_uint32_t); 3591: linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP); 3592: dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 3593: if (!TME_M68K_SEQUENCE_RESTARTING) { 3594: ic->_tme_m68k_ea_function_code = function_code; 3595: ic->_tme_m68k_ea_address = linear_address; 3596: } 3597: tme_m68k_read_memx8(ic); 3598: if (!TME_M68K_SEQUENCE_RESTARTING) { 3599: TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 24, 8, ic->tme_m68k_ireg_memx8); 3600: } 3601: linear_address += 2; 3602: if (!TME_M68K_SEQUENCE_RESTARTING) { 3603: ic->_tme_m68k_ea_function_code = function_code; 3604: ic->_tme_m68k_ea_address = linear_address; 3605: } 3606: tme_m68k_read_memx8(ic); 3607: if (!TME_M68K_SEQUENCE_RESTARTING) { 3608: TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 16, 8, ic->tme_m68k_ireg_memx8); 3609: } 3610: linear_address += 2; 3611: if (!TME_M68K_SEQUENCE_RESTARTING) { 3612: ic->_tme_m68k_ea_function_code = function_code; 3613: ic->_tme_m68k_ea_address = linear_address; 3614: } 3615: tme_m68k_read_memx8(ic); 3616: if (!TME_M68K_SEQUENCE_RESTARTING) { 3617: TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 8, 8, ic->tme_m68k_ireg_memx8); 3618: } 3619: linear_address += 2; 3620: if (!TME_M68K_SEQUENCE_RESTARTING) { 3621: ic->_tme_m68k_ea_function_code = function_code; 3622: ic->_tme_m68k_ea_address = linear_address; 3623: } 3624: tme_m68k_read_memx8(ic); 3625: if (!TME_M68K_SEQUENCE_RESTARTING) { 3626: TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 0, 8, ic->tme_m68k_ireg_memx8); 3627: } 3628: linear_address += 2; 3629: TME_M68K_INSN_OK; 3630: } 3631: 3632: /* the movem_mr function on 32-bit registers: */ 3633: TME_M68K_INSN(tme_m68k_movem_mr32) 3634: { 3635: int ireg, direction; 3636: tme_uint16_t mask, bit; 3637: unsigned int ea_mode; 3638: tme_uint32_t addend; 1.1.1.4 root 3639: tme_uint32_t total_size; 3640: /* get the register mask, and figure out the total size 3641: of the transfer: */ 3642: mask = TME_M68K_INSN_SPECOP; 3643: total_size = 0; 3644: if (mask != 0) { 3645: TME_M68K_INSN_CANFAULT; 3646: bit = mask; 3647: do { 3648: total_size += sizeof(tme_uint32_t); 3649: bit &= (bit - 1); 3650: } while (bit != 0); 3651: } 1.1 root 3652: 3653: /* figure out what direction to move in, and where to start from: */ 3654: ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); 3655: direction = 1; 3656: ireg = TME_M68K_IREG_D0; 3657: addend = (tme_uint32_t) (direction * sizeof(tme_uint32_t)); 3658: 3659: /* do the transfer: */ 3660: for (bit = 1; bit != 0; bit <<= 1) { 3661: if (mask & bit) { 3662: tme_m68k_read_memx32(ic); 3663: if (!TME_M68K_SEQUENCE_RESTARTING) { 3664: ic->tme_m68k_ireg_uint32(ireg) = ic->tme_m68k_ireg_memx32; 3665: ic->_tme_m68k_ea_address += addend; 3666: } 3667: } 3668: ireg += direction; 3669: } 3670: 3671: /* if this is the postincrement mode, update the address register: */ 3672: if (ea_mode == 3) { 3673: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 3674: + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3)) 3675: = ic->_tme_m68k_ea_address; 3676: } 3677: TME_M68K_INSN_OK; 3678: } 3679: 3680: /* chk32: */ 3681: TME_M68K_INSN(tme_m68k_chk32) 3682: { 3683: if (*((tme_int32_t *) _op0) < 0) { 3684: ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N; 1.1.1.3 root 3685: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 3686: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 3687: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 3688: } 3689: if (*((tme_int32_t *) _op0) > *((tme_int32_t *) _op1)) { 3690: ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N; 1.1.1.3 root 3691: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 3692: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 3693: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); 1.1 root 3694: } 3695: TME_M68K_INSN_OK; 3696: } 3697: 3698: /* cas32: */ 3699: TME_M68K_INSN(tme_m68k_cas32) 3700: { 1.1.1.4 root 3701: struct tme_m68k_rmw rmw; 1.1 root 3702: struct tme_m68k_tlb *tlb; 3703: int ireg_dc, ireg_du; 1.1.1.4 root 3704: tme_uint32_t value_dc, value_du, value_mem; 1.1 root 3705: 3706: /* start the read/modify/write cycle: */ 1.1.1.4 root 3707: rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address; 3708: rmw.tme_m68k_rmw_address_count = 1; 3709: rmw.tme_m68k_rmw_size = sizeof(tme_uint32_t); 3710: if (tme_m68k_rmw_start(ic, 3711: &rmw)) { 1.1 root 3712: TME_M68K_INSN_OK; 3713: } 3714: 1.1.1.4 root 3715: /* get the compare and update registers: */ 3716: ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 3717: ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3); 3718: 3719: /* if we can do the fast compare-and-exchange: */ 3720: if (!rmw.tme_m68k_rmw_slow_reads[0]) { 3721: 3722: /* get the compare and update values in big-endian byte order: */ 3723: value_dc = ic->tme_m68k_ireg_uint32(ireg_dc); 3724: value_du = ic->tme_m68k_ireg_uint32(ireg_du); 3725: value_dc = tme_htobe_u32(value_dc); 3726: value_du = tme_htobe_u32(value_du); 3727: 3728: /* get this TLB entry: */ 3729: tlb = rmw.tme_m68k_rmw_tlbs[0]; 3730: 3731: /* this TLB entry must allow fast reading and fast writing 3732: to the same memory: */ 3733: assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF 3734: && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read); 3735: 3736: /* do the compare-and-exchange: */ 3737: value_mem = 3738: tme_memory_atomic_cx32(((tme_shared tme_uint32_t *) 3739: (tlb->tme_m68k_tlb_emulator_off_read 3740: + ic->_tme_m68k_ea_address)), 3741: value_dc, 3742: value_du, 3743: tlb->tme_m68k_tlb_bus_rwlock, 3744: sizeof(tme_uint8_t)); 3745: ic->tme_m68k_ireg_memx32 = tme_betoh_u32(value_mem); 3746: } 1.1 root 3747: 1.1.1.4 root 3748: /* compare the compare operand to the effective address operand: */ 1.1 root 3749: tme_m68k_cmp32(ic, &ic->tme_m68k_ireg_uint32(ireg_dc), &ic->tme_m68k_ireg_memx32); 3750: 1.1.1.4 root 3751: /* if the comparison succeeded: */ 1.1 root 3752: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 3753: 3754: /* write the update operand to the effective address operand: */ 1.1 root 3755: ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg_du); 1.1.1.4 root 3756: } 3757: 3758: /* otherwise, the comparison failed: */ 3759: else { 3760: 3761: /* write the effective address operand to the compare operand: */ 1.1 root 3762: ic->tme_m68k_ireg_uint32(ireg_dc) = ic->tme_m68k_ireg_memx32; 3763: } 3764: 3765: /* finish the read/modify/write cycle: */ 1.1.1.4 root 3766: tme_m68k_rmw_finish(ic, 3767: &rmw, 3768: (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0); 1.1 root 3769: TME_M68K_INSN_OK; 3770: } 3771: 3772: /* cas2_32: */ 3773: TME_M68K_INSN(tme_m68k_cas2_32) 3774: { 1.1.1.4 root 3775: struct tme_m68k_rmw rmw; 3776: int ireg_dcx, ireg_dux; 3777: int ireg_dcy, ireg_duy; 3778: const tme_uint16_t specopx = TME_M68K_INSN_SPECOP; 3779: const tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t); 1.1 root 3780: 3781: /* start the read/modify/write cycle: */ 1.1.1.4 root 3782: ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 3783: rmw.tme_m68k_rmw_addresses[0] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 3784: + TME_FIELD_EXTRACTU(specopx, 12, 4)); 3785: rmw.tme_m68k_rmw_addresses[1] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 3786: + TME_FIELD_EXTRACTU(specopy, 12, 4)); 3787: rmw.tme_m68k_rmw_address_count = 2; 3788: rmw.tme_m68k_rmw_size = sizeof(tme_uint32_t); 3789: if (tme_m68k_rmw_start(ic, 3790: &rmw)) { 1.1 root 3791: TME_M68K_INSN_OK; 3792: } 3793: 1.1.1.4 root 3794: /* do the comparisons: */ 3795: ireg_dcx = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 0, 3); 3796: ireg_dcy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 0, 3); 3797: tme_m68k_cmp32(ic, 3798: &ic->tme_m68k_ireg_uint32(ireg_dcx), 3799: &ic->tme_m68k_ireg_memx32); 1.1 root 3800: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 3801: tme_m68k_cmp32(ic, 3802: &ic->tme_m68k_ireg_uint32(ireg_dcy), 3803: &ic->tme_m68k_ireg_memy32); 1.1 root 3804: } 3805: 1.1.1.4 root 3806: /* if the comparisons succeeded: */ 1.1 root 3807: if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) { 1.1.1.4 root 3808: 3809: /* write the update operands to the effective address operands: */ 3810: ireg_dux = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 6, 3); 3811: ireg_duy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 6, 3); 3812: ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg_dux); 3813: ic->tme_m68k_ireg_memy32 = ic->tme_m68k_ireg_uint32(ireg_duy); 1.1 root 3814: } 3815: 1.1.1.4 root 3816: /* otherwise, the comparisons failed: */ 3817: else { 3818: 3819: /* write the effective address operands to the compare operands. 3820: "If Dc1 and Dc2 specify the same data register and the comparison 3821: fails, memory operand 1 is stored in the data register." */ 3822: ic->tme_m68k_ireg_uint32(ireg_dcy) = ic->tme_m68k_ireg_memy32; 3823: ic->tme_m68k_ireg_uint32(ireg_dcx) = ic->tme_m68k_ireg_memx32; 3824: } 1.1 root 3825: 1.1.1.4 root 3826: /* finish the read/modify/write cycle: */ 3827: tme_m68k_rmw_finish(ic, 3828: &rmw, 3829: (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0); 1.1 root 3830: TME_M68K_INSN_OK; 3831: } 3832: 3833: /* moves32: */ 3834: TME_M68K_INSN(tme_m68k_moves32) 3835: { 3836: int ireg; 1.1.1.4 root 3837: tme_uint32_t ireg_value; 1.1.1.3 root 3838: unsigned int ea_reg; 3839: unsigned int increment; 3840: TME_M68K_INSN_PRIV; 3841: TME_M68K_INSN_CANFAULT; 1.1 root 3842: ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); 1.1.1.3 root 3843: 1.1.1.4 root 3844: /* in case we're storing the same address register used in a 3845: postincrement or predecrement EA, save the current value 3846: of the register now: */ 3847: ireg_value = ic->tme_m68k_ireg_uint32(ireg); 3848: 1.1.1.3 root 3849: /* we have to handle postincrement and predecrement ourselves: */ 3850: if (!TME_M68K_SEQUENCE_RESTARTING) { 3851: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 3852: increment = TME_M68K_SIZE_32; 3853: if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { 3854: increment = TME_M68K_SIZE_16; 3855: } 3856: switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { 3857: case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; 3858: case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; 3859: default: break; 3860: } 3861: } 3862: 1.1 root 3863: if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { 1.1.1.3 root 3864: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 3865: ic->tme_m68k_ireg_memx32 = ireg_value; 1.1.1.3 root 3866: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; 3867: } 3868: tme_m68k_write_memx32(ic); 1.1 root 3869: } 3870: else { 1.1.1.3 root 3871: if (!TME_M68K_SEQUENCE_RESTARTING) { 3872: ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; 3873: } 3874: tme_m68k_read_memx32(ic); 1.1 root 3875: ic->tme_m68k_ireg_uint32(ireg) = ic->tme_m68k_ireg_memx32; 3876: } 3877: TME_M68K_INSN_OK; 3878: } 3879: 3880: /* this reads a 8-bit memx value: */ 3881: void 3882: tme_m68k_read_memx8(struct tme_m68k *ic) 3883: { 1.1.1.5 ! root 3884: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 3885: unsigned int function_code = ic->_tme_m68k_ea_function_code; 3886: tme_uint32_t linear_address = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 3887: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address); 1.1.1.4 root 3888: tme_uint8_t mem_value; 3889: const tme_shared tme_uint8_t *mem; 1.1 root 3890: 1.1.1.3 root 3891: #ifdef _TME_M68K_STATS 3892: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 3893: #endif /* _TME_M68K_STATS */ 3894: 1.1.1.4 root 3895: /* busy this TLB entry: */ 3896: tme_m68k_tlb_busy(tlb); 3897: 3898: /* if we aren't restarting, and this address is properly aligned, 3899: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 3900: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.5 ! root 3901: && tme_m68k_tlb_is_valid(tlb) ! 3902: && tlb->tme_m68k_tlb_bus_context == bus_context ! 3903: && (tlb->tme_m68k_tlb_function_codes_mask ! 3904: & TME_BIT(function_code)) ! 3905: && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 3906: && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 3907: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 3908: 1.1.1.4 root 3909: /* make the emulator memory pointer: */ 3910: mem = (const tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address); 3911: 3912: /* do the 8-bit bus read: */ 3913: mem_value = tme_memory_bus_read8(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 3914: 3915: /* put the value read: */ 3916: ic->tme_m68k_ireg_memx8 = mem_value; 3917: 3918: /* step the transfer count: */ 1.1 root 3919: TME_M68K_SEQUENCE_TRANSFER_STEP; 3920: } 3921: 3922: /* otherwise, do the bus cycles the slow way: */ 3923: else { 3924: tme_m68k_read8(ic, tlb, 3925: &ic->_tme_m68k_ea_function_code, 3926: &ic->_tme_m68k_ea_address, 3927: &ic->tme_m68k_ireg_memx8, 3928: TME_M68K_BUS_CYCLE_NORMAL); 3929: } 3930: 1.1.1.4 root 3931: /* unbusy this TLB entry: */ 3932: tme_m68k_tlb_unbusy(tlb); 3933: 1.1 root 3934: /* log the value read: */ 3935: tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx8, TME_BUS_CYCLE_READ); 3936: tme_m68k_log(ic, 1000, TME_OK, 3937: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 3938: _("read_memx8 %d:0x%08x: 0x%02x"), 1.1 root 3939: ic->_tme_m68k_ea_function_code, 3940: ic->_tme_m68k_ea_address, 3941: ic->tme_m68k_ireg_memx8)); 3942: } 3943: 3944: /* this reads a 8-bit mem value: */ 3945: void 3946: tme_m68k_read_mem8(struct tme_m68k *ic, int ireg) 3947: { 1.1.1.5 ! root 3948: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 3949: unsigned int function_code = ic->_tme_m68k_ea_function_code; 3950: tme_uint32_t linear_address = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 3951: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address); 1.1.1.4 root 3952: tme_uint8_t mem_value; 3953: const tme_shared tme_uint8_t *mem; 1.1 root 3954: 1.1.1.3 root 3955: #ifdef _TME_M68K_STATS 3956: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 3957: #endif /* _TME_M68K_STATS */ 3958: 1.1.1.4 root 3959: /* busy this TLB entry: */ 3960: tme_m68k_tlb_busy(tlb); 3961: 3962: /* if we aren't restarting, and this address is properly aligned, 3963: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 3964: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.5 ! root 3965: && tme_m68k_tlb_is_valid(tlb) ! 3966: && tlb->tme_m68k_tlb_bus_context == bus_context ! 3967: && (tlb->tme_m68k_tlb_function_codes_mask ! 3968: & TME_BIT(function_code)) ! 3969: && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 3970: && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 3971: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 3972: 1.1.1.4 root 3973: /* make the emulator memory pointer: */ 3974: mem = (const tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address); 3975: 3976: /* do the 8-bit bus read: */ 3977: mem_value = tme_memory_bus_read8(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 3978: 3979: /* put the value read: */ 3980: ic->tme_m68k_ireg_uint8(ireg) = mem_value; 3981: 3982: /* step the transfer count: */ 1.1 root 3983: TME_M68K_SEQUENCE_TRANSFER_STEP; 3984: } 3985: 3986: /* otherwise, do the bus cycles the slow way: */ 3987: else { 3988: tme_m68k_read8(ic, tlb, 3989: &ic->_tme_m68k_ea_function_code, 3990: &ic->_tme_m68k_ea_address, 3991: &ic->tme_m68k_ireg_uint8(ireg), 3992: TME_M68K_BUS_CYCLE_NORMAL); 3993: } 3994: 1.1.1.4 root 3995: /* unbusy this TLB entry: */ 3996: tme_m68k_tlb_unbusy(tlb); 3997: 1.1 root 3998: /* log the value read: */ 3999: tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint8(ireg), TME_BUS_CYCLE_READ); 4000: tme_m68k_log(ic, 1000, TME_OK, 4001: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4002: _("read_mem8 %d:0x%08x: 0x%02x"), 1.1 root 4003: ic->_tme_m68k_ea_function_code, 4004: ic->_tme_m68k_ea_address, 4005: ic->tme_m68k_ireg_uint8(ireg))); 4006: } 4007: 4008: /* this writes a 8-bit memx value: */ 4009: void 4010: tme_m68k_write_memx8(struct tme_m68k *ic) 4011: { 1.1.1.5 ! root 4012: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4013: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4014: tme_uint32_t linear_address = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 4015: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address); 1.1.1.4 root 4016: tme_uint8_t mem_value; 4017: tme_shared tme_uint8_t *mem; 1.1 root 4018: 1.1.1.3 root 4019: #ifdef _TME_M68K_STATS 4020: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4021: #endif /* _TME_M68K_STATS */ 4022: 1.1 root 4023: /* log the value written: */ 4024: tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx8, TME_BUS_CYCLE_WRITE); 4025: tme_m68k_log(ic, 1000, TME_OK, 4026: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4027: _("write_memx8 %d:0x%08x: 0x%02x"), 1.1 root 4028: ic->_tme_m68k_ea_function_code, 4029: ic->_tme_m68k_ea_address, 4030: ic->tme_m68k_ireg_memx8)); 4031: 1.1.1.4 root 4032: /* busy this TLB entry: */ 4033: tme_m68k_tlb_busy(tlb); 4034: 4035: /* if we aren't restarting, and this address is properly aligned, 4036: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 4037: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.5 ! root 4038: && tme_m68k_tlb_is_valid(tlb) ! 4039: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4040: && (tlb->tme_m68k_tlb_function_codes_mask ! 4041: & TME_BIT(function_code)) ! 4042: && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4043: && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4044: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4045: 1.1.1.4 root 4046: /* make the emulator memory pointer: */ 4047: mem = (tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address); 4048: 4049: /* get the value to write: */ 4050: mem_value = ic->tme_m68k_ireg_memx8; 4051: 4052: /* do the 8-bit bus write: */ 4053: tme_memory_bus_write8(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4054: 4055: /* step the transfer count: */ 1.1 root 4056: TME_M68K_SEQUENCE_TRANSFER_STEP; 4057: } 4058: 4059: /* otherwise, do the bus cycles the slow way: */ 4060: else { 4061: tme_m68k_write8(ic, tlb, 4062: &ic->_tme_m68k_ea_function_code, 4063: &ic->_tme_m68k_ea_address, 4064: &ic->tme_m68k_ireg_memx8, 4065: TME_M68K_BUS_CYCLE_NORMAL); 4066: } 1.1.1.4 root 4067: 4068: /* unbusy this TLB entry: */ 4069: tme_m68k_tlb_unbusy(tlb); 1.1 root 4070: } 4071: 4072: /* this writes a 8-bit mem value: */ 4073: void 4074: tme_m68k_write_mem8(struct tme_m68k *ic, int ireg) 4075: { 1.1.1.5 ! root 4076: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4077: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4078: tme_uint32_t linear_address = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 4079: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address); 1.1.1.4 root 4080: tme_uint8_t mem_value; 4081: tme_shared tme_uint8_t *mem; 1.1 root 4082: 1.1.1.3 root 4083: #ifdef _TME_M68K_STATS 4084: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4085: #endif /* _TME_M68K_STATS */ 4086: 1.1 root 4087: /* log the value written: */ 4088: tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint8(ireg), TME_BUS_CYCLE_WRITE); 4089: tme_m68k_log(ic, 1000, TME_OK, 4090: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4091: _("write_mem8 %d:0x%08x: 0x%02x"), 1.1 root 4092: ic->_tme_m68k_ea_function_code, 4093: ic->_tme_m68k_ea_address, 4094: ic->tme_m68k_ireg_uint8(ireg))); 4095: 1.1.1.4 root 4096: /* busy this TLB entry: */ 4097: tme_m68k_tlb_busy(tlb); 4098: 4099: /* if we aren't restarting, and this address is properly aligned, 4100: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 4101: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.5 ! root 4102: && tme_m68k_tlb_is_valid(tlb) ! 4103: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4104: && (tlb->tme_m68k_tlb_function_codes_mask ! 4105: & TME_BIT(function_code)) ! 4106: && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4107: && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4108: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4109: 1.1.1.4 root 4110: /* make the emulator memory pointer: */ 4111: mem = (tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address); 4112: 4113: /* get the value to write: */ 4114: mem_value = ic->tme_m68k_ireg_uint8(ireg); 4115: 4116: /* do the 8-bit bus write: */ 4117: tme_memory_bus_write8(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4118: 4119: /* step the transfer count: */ 1.1 root 4120: TME_M68K_SEQUENCE_TRANSFER_STEP; 4121: } 4122: 4123: /* otherwise, do the bus cycles the slow way: */ 4124: else { 4125: tme_m68k_write8(ic, tlb, 4126: &ic->_tme_m68k_ea_function_code, 4127: &ic->_tme_m68k_ea_address, 4128: &ic->tme_m68k_ireg_uint8(ireg), 4129: TME_M68K_BUS_CYCLE_NORMAL); 4130: } 1.1.1.4 root 4131: 4132: /* unbusy this TLB entry: */ 4133: tme_m68k_tlb_unbusy(tlb); 1.1 root 4134: } 4135: 4136: /* this reads a 16-bit memx value: */ 4137: void 4138: tme_m68k_read_memx16(struct tme_m68k *ic) 4139: { 1.1.1.5 ! root 4140: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4141: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4142: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4143: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4144: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4145: tme_uint16_t mem_value; 4146: const tme_shared tme_uint16_t *mem; 1.1 root 4147: 1.1.1.3 root 4148: #ifdef _TME_M68K_STATS 4149: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4150: #endif /* _TME_M68K_STATS */ 4151: 1.1.1.4 root 4152: /* busy this TLB entry: */ 4153: tme_m68k_tlb_busy(tlb); 4154: 4155: /* if we aren't restarting, and this address is properly aligned, 4156: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4157: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4158: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4159: && tme_m68k_tlb_is_valid(tlb) ! 4160: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4161: && (tlb->tme_m68k_tlb_function_codes_mask ! 4162: & TME_BIT(function_code)) ! 4163: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4164: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4165: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4166: 1.1.1.4 root 4167: /* make the emulator memory pointer: */ 4168: mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4169: 4170: /* do the 16-bit bus read: */ 4171: mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4172: 4173: /* put the value read, in host byte order: */ 4174: ic->tme_m68k_ireg_memx16 = tme_betoh_u16(mem_value); 4175: 4176: /* step the transfer count: */ 1.1 root 4177: TME_M68K_SEQUENCE_TRANSFER_STEP; 4178: } 4179: 4180: /* otherwise, do the bus cycles the slow way: */ 4181: else { 4182: tme_m68k_read16(ic, tlb, 4183: &ic->_tme_m68k_ea_function_code, 4184: &ic->_tme_m68k_ea_address, 4185: &ic->tme_m68k_ireg_memx16, 4186: TME_M68K_BUS_CYCLE_NORMAL); 4187: } 4188: 1.1.1.4 root 4189: /* unbusy this TLB entry: */ 4190: tme_m68k_tlb_unbusy(tlb); 4191: 1.1 root 4192: /* log the value read: */ 4193: tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx16, TME_BUS_CYCLE_READ); 4194: tme_m68k_log(ic, 1000, TME_OK, 4195: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4196: _("read_memx16 %d:0x%08x: 0x%04x"), 1.1 root 4197: ic->_tme_m68k_ea_function_code, 4198: ic->_tme_m68k_ea_address, 4199: ic->tme_m68k_ireg_memx16)); 4200: } 4201: 4202: /* this reads a 16-bit mem value: */ 4203: void 4204: tme_m68k_read_mem16(struct tme_m68k *ic, int ireg) 4205: { 1.1.1.5 ! root 4206: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4207: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4208: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4209: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4210: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4211: tme_uint16_t mem_value; 4212: const tme_shared tme_uint16_t *mem; 1.1 root 4213: 1.1.1.3 root 4214: #ifdef _TME_M68K_STATS 4215: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4216: #endif /* _TME_M68K_STATS */ 4217: 1.1.1.4 root 4218: /* busy this TLB entry: */ 4219: tme_m68k_tlb_busy(tlb); 4220: 4221: /* if we aren't restarting, and this address is properly aligned, 4222: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4223: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4224: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4225: && tme_m68k_tlb_is_valid(tlb) ! 4226: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4227: && (tlb->tme_m68k_tlb_function_codes_mask ! 4228: & TME_BIT(function_code)) ! 4229: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4230: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4231: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4232: 1.1.1.4 root 4233: /* make the emulator memory pointer: */ 4234: mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4235: 4236: /* do the 16-bit bus read: */ 4237: mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4238: 4239: /* put the value read, in host byte order: */ 4240: ic->tme_m68k_ireg_uint16(ireg) = tme_betoh_u16(mem_value); 4241: 4242: /* step the transfer count: */ 1.1 root 4243: TME_M68K_SEQUENCE_TRANSFER_STEP; 4244: } 4245: 4246: /* otherwise, do the bus cycles the slow way: */ 4247: else { 4248: tme_m68k_read16(ic, tlb, 4249: &ic->_tme_m68k_ea_function_code, 4250: &ic->_tme_m68k_ea_address, 4251: &ic->tme_m68k_ireg_uint16(ireg), 4252: TME_M68K_BUS_CYCLE_NORMAL); 4253: } 4254: 1.1.1.4 root 4255: /* unbusy this TLB entry: */ 4256: tme_m68k_tlb_unbusy(tlb); 4257: 1.1 root 4258: /* log the value read: */ 4259: tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint16(ireg), TME_BUS_CYCLE_READ); 4260: tme_m68k_log(ic, 1000, TME_OK, 4261: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4262: _("read_mem16 %d:0x%08x: 0x%04x"), 1.1 root 4263: ic->_tme_m68k_ea_function_code, 4264: ic->_tme_m68k_ea_address, 4265: ic->tme_m68k_ireg_uint16(ireg))); 4266: } 4267: 4268: /* this reads a 16-bit inst value: */ 4269: tme_uint16_t 4270: tme_m68k_fetch16(struct tme_m68k *ic, tme_uint32_t pc) 4271: { 1.1.1.5 ! root 4272: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4273: unsigned int function_code = TME_M68K_FUNCTION_CODE_PROGRAM(ic); 4274: tme_uint32_t linear_address_first = pc; 4275: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4276: struct tme_m68k_tlb *tlb = &ic->_tme_m68k_itlb; 1.1.1.4 root 4277: tme_uint16_t mem_value; 4278: const tme_shared tme_uint16_t *mem; 4279: unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next; 1.1 root 4280: 1.1.1.3 root 4281: #ifdef _TME_M68K_STATS 4282: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4283: #endif /* _TME_M68K_STATS */ 4284: 1.1.1.4 root 4285: /* busy this TLB entry: */ 4286: tme_m68k_tlb_busy(tlb); 1.1 root 4287: 1.1.1.4 root 4288: /* if this fetch was done by the fast executor: */ 4289: if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) { 1.1 root 4290: 1.1.1.4 root 4291: /* the entire fetch must be in the instruction buffer, and 4292: we must be restarting: */ 4293: assert ((fetch_slow_next + sizeof(tme_uint16_t)) 4294: <= ic->_tme_m68k_insn_fetch_slow_count_fast); 4295: assert (TME_M68K_SEQUENCE_RESTARTING); 4296: mem_value = tme_memory_read16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t)); 4297: } 4298: 4299: /* otherwise, this fetch was not done by the fast executor: */ 4300: else { 4301: 4302: /* if we're restarting, but the offset in the instruction buffer 4303: to fetch into is at the instruction buffer total, this must be 4304: a fake fault caused by the fast executor. we confirm this by 4305: checking that this transfer "caused" the fault, and that this 4306: transfer will be the first slow one after any fast fetches. 4307: in this case, we can cancel the restart for now: */ 4308: if (TME_M68K_SEQUENCE_RESTARTING 4309: && (fetch_slow_next 4310: == ic->_tme_m68k_insn_fetch_slow_count_total)) { 4311: assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next 4312: == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted) 4313: && (fetch_slow_next 4314: == ic->_tme_m68k_insn_fetch_slow_count_fast)); 4315: ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--; 4316: } 4317: 4318: /* if we're not restarting: */ 4319: if (!TME_M68K_SEQUENCE_RESTARTING) { 4320: 4321: /* we advance the instruction buffer total *before* we do 4322: what may be a slow fetch, because we may transfer a few 4323: bytes and then fault. without this, those few bytes 4324: would not get saved in the exception stack frame and 4325: restored later before the continuation of the fetch: */ 4326: ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint16_t); 4327: } 4328: 4329: /* make sure that if this is a new transfer or if this 4330: transfer faulted, that we're fetching for the current 4331: last positions in the instruction buffer: */ 4332: assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next 4333: < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted) 4334: || ((fetch_slow_next + sizeof(tme_uint16_t)) 4335: == ic->_tme_m68k_insn_fetch_slow_count_total)); 4336: 4337: /* if we aren't restarting, and this address is properly aligned, 4338: and this TLB entry covers the operand and allows fast reads: */ 4339: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 4340: && ((sizeof(tme_uint16_t) - 1) & linear_address_first) == 0 1.1.1.5 ! root 4341: && tme_m68k_tlb_is_valid(tlb) ! 4342: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4343: && (tlb->tme_m68k_tlb_function_codes_mask ! 4344: & TME_BIT(function_code)) ! 4345: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4346: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4347: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1.1.4 root 4348: 4349: /* make the emulator memory pointer: */ 4350: mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4351: 4352: /* do the 16-bit bus read: */ 4353: mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint16_t), sizeof(tme_uint32_t)); 4354: 4355: /* put the value read, in host byte order: */ 4356: mem_value = tme_betoh_u16(mem_value); 4357: tme_memory_write16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), mem_value, sizeof(tme_uint16_t)); 4358: 4359: /* step the transfer count: */ 4360: TME_M68K_SEQUENCE_TRANSFER_STEP; 4361: } 4362: 4363: /* otherwise, do the bus cycles the slow way: */ 4364: else { 4365: tme_m68k_read16(ic, tlb, 4366: &function_code, 4367: &pc, 4368: ((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), 4369: TME_M68K_BUS_CYCLE_FETCH); 4370: mem_value = tme_memory_read16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t)); 4371: } 1.1 root 4372: } 4373: 1.1.1.4 root 4374: /* unbusy this TLB entry: */ 4375: tme_m68k_tlb_unbusy(tlb); 4376: 1.1 root 4377: /* log the value read: */ 1.1.1.4 root 4378: tme_m68k_verify_mem16(ic, function_code, pc, *((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), TME_BUS_CYCLE_READ); 1.1 root 4379: tme_m68k_log(ic, 1000, TME_OK, 4380: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4381: _("fetch16 %d:0x%08x: 0x%04x"), 1.1 root 4382: function_code, 4383: pc, 1.1.1.4 root 4384: *((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)))); 4385: 4386: /* advance the offset in the instruction buffer for the next slow fetch: */ 4387: fetch_slow_next += sizeof(tme_uint16_t); 4388: ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next; 4389: 4390: /* return the fetched value: */ 4391: return(mem_value); 1.1 root 4392: } 4393: 4394: /* this reads a 16-bit stack value: */ 4395: void 4396: tme_m68k_pop16(struct tme_m68k *ic, tme_uint16_t *_value) 4397: { 1.1.1.5 ! root 4398: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4399: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 4400: tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7; 4401: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4402: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4403: tme_uint16_t mem_value; 4404: const tme_shared tme_uint16_t *mem; 1.1 root 4405: 1.1.1.3 root 4406: #ifdef _TME_M68K_STATS 4407: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4408: #endif /* _TME_M68K_STATS */ 4409: 1.1.1.4 root 4410: /* busy this TLB entry: */ 4411: tme_m68k_tlb_busy(tlb); 4412: 4413: /* if we aren't restarting, and this address is properly aligned, 4414: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4415: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4416: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4417: && tme_m68k_tlb_is_valid(tlb) ! 4418: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4419: && (tlb->tme_m68k_tlb_function_codes_mask ! 4420: & TME_BIT(function_code)) ! 4421: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4422: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4423: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4424: 1.1.1.4 root 4425: /* make the emulator memory pointer: */ 4426: mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4427: 4428: /* do the 16-bit bus read: */ 4429: mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4430: 4431: /* put the value read, in host byte order: */ 4432: *_value = tme_betoh_u16(mem_value); 4433: 4434: /* step the transfer count: */ 1.1 root 4435: TME_M68K_SEQUENCE_TRANSFER_STEP; 4436: } 4437: 4438: /* otherwise, do the bus cycles the slow way: */ 4439: else { 4440: tme_m68k_read16(ic, tlb, 4441: &function_code, 4442: &ic->tme_m68k_ireg_a7, 4443: _value, 4444: TME_M68K_BUS_CYCLE_NORMAL); 4445: } 4446: 1.1.1.4 root 4447: /* unbusy this TLB entry: */ 4448: tme_m68k_tlb_unbusy(tlb); 4449: 1.1 root 4450: /* log the value read: */ 4451: tme_m68k_verify_mem16(ic, function_code, ic->tme_m68k_ireg_a7, *_value, TME_BUS_CYCLE_READ); 4452: tme_m68k_log(ic, 1000, TME_OK, 4453: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4454: _("pop16 %d:0x%08x: 0x%04x"), 1.1 root 4455: function_code, 4456: ic->tme_m68k_ireg_a7, 4457: *_value)); 4458: if (!TME_M68K_SEQUENCE_RESTARTING) { 4459: ic->tme_m68k_ireg_a7 += sizeof(tme_uint16_t); 4460: } 4461: } 4462: 4463: /* this writes a 16-bit memx value: */ 4464: void 4465: tme_m68k_write_memx16(struct tme_m68k *ic) 4466: { 1.1.1.5 ! root 4467: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4468: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4469: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4470: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4471: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4472: tme_uint16_t mem_value; 4473: tme_shared tme_uint16_t *mem; 1.1 root 4474: 1.1.1.3 root 4475: #ifdef _TME_M68K_STATS 4476: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4477: #endif /* _TME_M68K_STATS */ 4478: 1.1 root 4479: /* log the value written: */ 4480: tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx16, TME_BUS_CYCLE_WRITE); 4481: tme_m68k_log(ic, 1000, TME_OK, 4482: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4483: _("write_memx16 %d:0x%08x: 0x%04x"), 1.1 root 4484: ic->_tme_m68k_ea_function_code, 4485: ic->_tme_m68k_ea_address, 4486: ic->tme_m68k_ireg_memx16)); 4487: 1.1.1.4 root 4488: /* busy this TLB entry: */ 4489: tme_m68k_tlb_busy(tlb); 4490: 4491: /* if we aren't restarting, and this address is properly aligned, 4492: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 4493: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4494: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4495: && tme_m68k_tlb_is_valid(tlb) ! 4496: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4497: && (tlb->tme_m68k_tlb_function_codes_mask ! 4498: & TME_BIT(function_code)) ! 4499: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4500: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4501: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4502: 1.1.1.4 root 4503: /* make the emulator memory pointer: */ 4504: mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 4505: 4506: /* get the value to write, in big-endian byte order: */ 4507: mem_value = tme_htobe_u16(ic->tme_m68k_ireg_memx16); 4508: 4509: /* do the 16-bit bus write: */ 4510: tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4511: 4512: /* step the transfer count: */ 1.1 root 4513: TME_M68K_SEQUENCE_TRANSFER_STEP; 4514: } 4515: 4516: /* otherwise, do the bus cycles the slow way: */ 4517: else { 4518: tme_m68k_write16(ic, tlb, 4519: &ic->_tme_m68k_ea_function_code, 4520: &ic->_tme_m68k_ea_address, 4521: &ic->tme_m68k_ireg_memx16, 4522: TME_M68K_BUS_CYCLE_NORMAL); 4523: } 1.1.1.4 root 4524: 4525: /* unbusy this TLB entry: */ 4526: tme_m68k_tlb_unbusy(tlb); 1.1 root 4527: } 4528: 4529: /* this writes a 16-bit mem value: */ 4530: void 4531: tme_m68k_write_mem16(struct tme_m68k *ic, int ireg) 4532: { 1.1.1.5 ! root 4533: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4534: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4535: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4536: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4537: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4538: tme_uint16_t mem_value; 4539: tme_shared tme_uint16_t *mem; 1.1 root 4540: 1.1.1.3 root 4541: #ifdef _TME_M68K_STATS 4542: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4543: #endif /* _TME_M68K_STATS */ 4544: 1.1 root 4545: /* log the value written: */ 4546: tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint16(ireg), TME_BUS_CYCLE_WRITE); 4547: tme_m68k_log(ic, 1000, TME_OK, 4548: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4549: _("write_mem16 %d:0x%08x: 0x%04x"), 1.1 root 4550: ic->_tme_m68k_ea_function_code, 4551: ic->_tme_m68k_ea_address, 4552: ic->tme_m68k_ireg_uint16(ireg))); 4553: 1.1.1.4 root 4554: /* busy this TLB entry: */ 4555: tme_m68k_tlb_busy(tlb); 4556: 4557: /* if we aren't restarting, and this address is properly aligned, 4558: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 4559: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4560: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4561: && tme_m68k_tlb_is_valid(tlb) ! 4562: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4563: && (tlb->tme_m68k_tlb_function_codes_mask ! 4564: & TME_BIT(function_code)) ! 4565: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4566: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4567: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4568: 1.1.1.4 root 4569: /* make the emulator memory pointer: */ 4570: mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 4571: 4572: /* get the value to write, in big-endian byte order: */ 4573: mem_value = tme_htobe_u16(ic->tme_m68k_ireg_uint16(ireg)); 4574: 4575: /* do the 16-bit bus write: */ 4576: tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4577: 4578: /* step the transfer count: */ 1.1 root 4579: TME_M68K_SEQUENCE_TRANSFER_STEP; 4580: } 4581: 4582: /* otherwise, do the bus cycles the slow way: */ 4583: else { 4584: tme_m68k_write16(ic, tlb, 4585: &ic->_tme_m68k_ea_function_code, 4586: &ic->_tme_m68k_ea_address, 4587: &ic->tme_m68k_ireg_uint16(ireg), 4588: TME_M68K_BUS_CYCLE_NORMAL); 4589: } 1.1.1.4 root 4590: 4591: /* unbusy this TLB entry: */ 4592: tme_m68k_tlb_unbusy(tlb); 1.1 root 4593: } 4594: 4595: /* this writes a 16-bit stack value: */ 4596: void 4597: tme_m68k_push16(struct tme_m68k *ic, tme_uint16_t value) 4598: { 1.1.1.5 ! root 4599: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4600: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 4601: tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7 - sizeof(tme_uint16_t); 4602: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; 1.1.1.5 ! root 4603: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4604: tme_uint16_t mem_value; 4605: tme_shared tme_uint16_t *mem; 1.1 root 4606: 1.1.1.3 root 4607: #ifdef _TME_M68K_STATS 4608: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4609: #endif /* _TME_M68K_STATS */ 4610: 1.1 root 4611: /* log the value written: */ 4612: tme_m68k_verify_mem16(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE); 4613: tme_m68k_log(ic, 1000, TME_OK, 4614: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4615: _("push16 %d:0x%08x: 0x%04x"), 1.1 root 4616: function_code, 4617: linear_address_first, 4618: value)); 4619: 1.1.1.4 root 4620: /* busy this TLB entry: */ 4621: tme_m68k_tlb_busy(tlb); 4622: 4623: /* if we aren't restarting, and this address is properly aligned, 4624: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 4625: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4626: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4627: && tme_m68k_tlb_is_valid(tlb) ! 4628: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4629: && (tlb->tme_m68k_tlb_function_codes_mask ! 4630: & TME_BIT(function_code)) ! 4631: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4632: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4633: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4634: 1.1.1.4 root 4635: /* make the emulator memory pointer: */ 4636: mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 4637: 4638: /* get the value to write, in big-endian byte order: */ 4639: mem_value = tme_htobe_u16(value); 4640: 4641: /* do the 16-bit bus write: */ 4642: tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4643: 4644: /* step the transfer count: */ 1.1 root 4645: TME_M68K_SEQUENCE_TRANSFER_STEP; 4646: } 4647: 4648: /* otherwise, do the bus cycles the slow way: */ 4649: else { 4650: tme_m68k_write16(ic, tlb, 4651: &function_code, 4652: &linear_address_first, 4653: &value, 4654: TME_M68K_BUS_CYCLE_NORMAL); 4655: } 1.1.1.4 root 4656: 4657: /* unbusy this TLB entry: */ 4658: tme_m68k_tlb_unbusy(tlb); 1.1 root 4659: if (!TME_M68K_SEQUENCE_RESTARTING) { 4660: ic->tme_m68k_ireg_a7 -= sizeof(tme_uint16_t); 4661: } 4662: } 4663: 4664: /* this reads a 32-bit memx value: */ 4665: void 4666: tme_m68k_read_memx32(struct tme_m68k *ic) 4667: { 1.1.1.5 ! root 4668: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4669: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4670: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4671: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 4672: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4673: tme_uint32_t mem_value; 4674: const tme_shared tme_uint32_t *mem; 1.1 root 4675: 1.1.1.3 root 4676: #ifdef _TME_M68K_STATS 4677: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4678: #endif /* _TME_M68K_STATS */ 4679: 1.1.1.4 root 4680: /* busy this TLB entry: */ 4681: tme_m68k_tlb_busy(tlb); 4682: 4683: /* if we aren't restarting, and this address is properly aligned, 4684: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4685: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4686: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4687: && tme_m68k_tlb_is_valid(tlb) ! 4688: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4689: && (tlb->tme_m68k_tlb_function_codes_mask ! 4690: & TME_BIT(function_code)) ! 4691: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4692: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4693: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4694: 1.1.1.4 root 4695: /* make the emulator memory pointer: */ 4696: mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4697: 4698: /* do the 32-bit bus read: */ 4699: mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4700: 4701: /* put the value read, in host byte order: */ 4702: ic->tme_m68k_ireg_memx32 = tme_betoh_u32(mem_value); 4703: 4704: /* step the transfer count: */ 1.1 root 4705: TME_M68K_SEQUENCE_TRANSFER_STEP; 4706: } 4707: 4708: /* otherwise, do the bus cycles the slow way: */ 4709: else { 4710: tme_m68k_read32(ic, tlb, 4711: &ic->_tme_m68k_ea_function_code, 4712: &ic->_tme_m68k_ea_address, 4713: &ic->tme_m68k_ireg_memx32, 4714: TME_M68K_BUS_CYCLE_NORMAL); 4715: } 4716: 1.1.1.4 root 4717: /* unbusy this TLB entry: */ 4718: tme_m68k_tlb_unbusy(tlb); 4719: 1.1 root 4720: /* log the value read: */ 4721: tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx32, TME_BUS_CYCLE_READ); 4722: tme_m68k_log(ic, 1000, TME_OK, 4723: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4724: _("read_memx32 %d:0x%08x: 0x%08x"), 1.1 root 4725: ic->_tme_m68k_ea_function_code, 4726: ic->_tme_m68k_ea_address, 4727: ic->tme_m68k_ireg_memx32)); 4728: } 4729: 4730: /* this reads a 32-bit mem value: */ 4731: void 4732: tme_m68k_read_mem32(struct tme_m68k *ic, int ireg) 4733: { 1.1.1.5 ! root 4734: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4735: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4736: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4737: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 4738: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4739: tme_uint32_t mem_value; 4740: const tme_shared tme_uint32_t *mem; 1.1 root 4741: 1.1.1.3 root 4742: #ifdef _TME_M68K_STATS 4743: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4744: #endif /* _TME_M68K_STATS */ 4745: 1.1.1.4 root 4746: /* busy this TLB entry: */ 4747: tme_m68k_tlb_busy(tlb); 4748: 4749: /* if we aren't restarting, and this address is properly aligned, 4750: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4751: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4752: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4753: && tme_m68k_tlb_is_valid(tlb) ! 4754: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4755: && (tlb->tme_m68k_tlb_function_codes_mask ! 4756: & TME_BIT(function_code)) ! 4757: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4758: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4759: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4760: 1.1.1.4 root 4761: /* make the emulator memory pointer: */ 4762: mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4763: 4764: /* do the 32-bit bus read: */ 4765: mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4766: 4767: /* put the value read, in host byte order: */ 4768: ic->tme_m68k_ireg_uint32(ireg) = tme_betoh_u32(mem_value); 4769: 4770: /* step the transfer count: */ 1.1 root 4771: TME_M68K_SEQUENCE_TRANSFER_STEP; 4772: } 4773: 4774: /* otherwise, do the bus cycles the slow way: */ 4775: else { 4776: tme_m68k_read32(ic, tlb, 4777: &ic->_tme_m68k_ea_function_code, 4778: &ic->_tme_m68k_ea_address, 4779: &ic->tme_m68k_ireg_uint32(ireg), 4780: TME_M68K_BUS_CYCLE_NORMAL); 4781: } 4782: 1.1.1.4 root 4783: /* unbusy this TLB entry: */ 4784: tme_m68k_tlb_unbusy(tlb); 4785: 1.1 root 4786: /* log the value read: */ 4787: tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint32(ireg), TME_BUS_CYCLE_READ); 4788: tme_m68k_log(ic, 1000, TME_OK, 4789: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4790: _("read_mem32 %d:0x%08x: 0x%08x"), 1.1 root 4791: ic->_tme_m68k_ea_function_code, 4792: ic->_tme_m68k_ea_address, 4793: ic->tme_m68k_ireg_uint32(ireg))); 4794: } 4795: 4796: /* this reads a 32-bit inst value: */ 4797: tme_uint32_t 4798: tme_m68k_fetch32(struct tme_m68k *ic, tme_uint32_t pc) 4799: { 1.1.1.5 ! root 4800: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4801: unsigned int function_code = TME_M68K_FUNCTION_CODE_PROGRAM(ic); 4802: tme_uint32_t linear_address_first = pc; 4803: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 4804: struct tme_m68k_tlb *tlb = &ic->_tme_m68k_itlb; 1.1.1.4 root 4805: tme_uint32_t mem_value; 4806: const tme_shared tme_uint32_t *mem; 4807: unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next; 1.1 root 4808: 1.1.1.3 root 4809: #ifdef _TME_M68K_STATS 4810: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4811: #endif /* _TME_M68K_STATS */ 4812: 1.1.1.4 root 4813: /* busy this TLB entry: */ 4814: tme_m68k_tlb_busy(tlb); 1.1 root 4815: 1.1.1.4 root 4816: /* if this fetch was done by the fast executor: */ 4817: if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) { 4818: 4819: /* the entire fetch must be in the instruction buffer, and 4820: we must be restarting: */ 4821: assert ((fetch_slow_next + sizeof(tme_uint32_t)) 4822: <= ic->_tme_m68k_insn_fetch_slow_count_fast); 4823: assert (TME_M68K_SEQUENCE_RESTARTING); 4824: mem_value = tme_memory_read32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t)); 4825: } 4826: 4827: /* otherwise, this fetch was not done by the fast executor: */ 4828: else { 4829: 4830: /* if we're restarting, but the offset in the instruction buffer 4831: to fetch into is at the instruction buffer total, this must be 4832: a fake fault caused by the fast executor. we confirm this by 4833: checking that this transfer "caused" the fault, and that this 4834: transfer will be the first slow one after any fast fetches. 4835: in this case, we can cancel the restart for now: */ 4836: if (TME_M68K_SEQUENCE_RESTARTING 4837: && (fetch_slow_next 4838: == ic->_tme_m68k_insn_fetch_slow_count_total)) { 4839: assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next 4840: == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted) 4841: && (fetch_slow_next 4842: == ic->_tme_m68k_insn_fetch_slow_count_fast)); 4843: ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--; 1.1 root 4844: } 1.1.1.4 root 4845: 4846: /* if we're not restarting: */ 4847: if (!TME_M68K_SEQUENCE_RESTARTING) { 4848: 4849: /* we advance the instruction buffer total *before* we do 4850: what may be a slow fetch, because we may transfer a few 4851: bytes and then fault. without this, those few bytes 4852: would not get saved in the exception stack frame and 4853: restored later before the continuation of the fetch: */ 4854: ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint32_t); 4855: } 4856: 4857: /* make sure that if this is a new transfer or if this 4858: transfer faulted, that we're fetching for the current 4859: last positions in the instruction buffer: */ 4860: assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next 4861: < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted) 4862: || ((fetch_slow_next + sizeof(tme_uint32_t)) 4863: == ic->_tme_m68k_insn_fetch_slow_count_total)); 4864: 4865: /* if we aren't restarting, and this address is properly aligned, 4866: and this TLB entry covers the operand and allows fast reads: */ 4867: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 4868: && ((sizeof(tme_uint16_t) - 1) & linear_address_first) == 0 1.1.1.5 ! root 4869: && tme_m68k_tlb_is_valid(tlb) ! 4870: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4871: && (tlb->tme_m68k_tlb_function_codes_mask ! 4872: & TME_BIT(function_code)) ! 4873: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4874: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4875: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1.1.4 root 4876: 4877: /* make the emulator memory pointer: */ 4878: mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4879: 4880: /* do the 32-bit bus read: */ 4881: mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint16_t), sizeof(tme_uint32_t)); 4882: 4883: /* put the value read, in host byte order: */ 4884: mem_value = tme_betoh_u32(mem_value); 4885: tme_memory_write32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), mem_value, sizeof(tme_uint16_t)); 4886: 4887: /* step the transfer count: */ 4888: TME_M68K_SEQUENCE_TRANSFER_STEP; 1.1 root 4889: } 1.1.1.4 root 4890: 4891: /* otherwise, do the bus cycles the slow way: */ 1.1 root 4892: else { 1.1.1.4 root 4893: tme_m68k_read32(ic, tlb, 4894: &function_code, 4895: &pc, 4896: ((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), 4897: TME_M68K_BUS_CYCLE_FETCH); 4898: mem_value = tme_memory_read32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t)); 1.1 root 4899: } 4900: } 4901: 1.1.1.4 root 4902: /* unbusy this TLB entry: */ 4903: tme_m68k_tlb_unbusy(tlb); 1.1 root 4904: 4905: /* log the value read: */ 1.1.1.4 root 4906: tme_m68k_verify_mem32(ic, function_code, pc, *((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), TME_BUS_CYCLE_READ); 1.1 root 4907: tme_m68k_log(ic, 1000, TME_OK, 4908: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4909: _("fetch32 %d:0x%08x: 0x%08x"), 1.1 root 4910: function_code, 4911: pc, 1.1.1.4 root 4912: *((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)))); 4913: 4914: /* advance the offset in the instruction buffer for the next slow fetch: */ 4915: fetch_slow_next += sizeof(tme_uint32_t); 4916: ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next; 4917: 4918: /* return the fetched value: */ 4919: return(mem_value); 1.1 root 4920: } 4921: 4922: /* this reads a 32-bit stack value: */ 4923: void 4924: tme_m68k_pop32(struct tme_m68k *ic, tme_uint32_t *_value) 4925: { 1.1.1.5 ! root 4926: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4927: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 4928: tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7; 4929: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 4930: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 4931: tme_uint32_t mem_value; 4932: const tme_shared tme_uint32_t *mem; 1.1 root 4933: 1.1.1.3 root 4934: #ifdef _TME_M68K_STATS 4935: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 4936: #endif /* _TME_M68K_STATS */ 4937: 1.1.1.4 root 4938: /* busy this TLB entry: */ 4939: tme_m68k_tlb_busy(tlb); 4940: 4941: /* if we aren't restarting, and this address is properly aligned, 4942: and this TLB entry covers the operand and allows fast reads: */ 1.1 root 4943: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 4944: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 4945: && tme_m68k_tlb_is_valid(tlb) ! 4946: && tlb->tme_m68k_tlb_bus_context == bus_context ! 4947: && (tlb->tme_m68k_tlb_function_codes_mask ! 4948: & TME_BIT(function_code)) ! 4949: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 4950: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 4951: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 4952: 1.1.1.4 root 4953: /* make the emulator memory pointer: */ 4954: mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first); 4955: 4956: /* do the 32-bit bus read: */ 4957: mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 4958: 4959: /* put the value read, in host byte order: */ 4960: *_value = tme_betoh_u32(mem_value); 4961: 4962: /* step the transfer count: */ 1.1 root 4963: TME_M68K_SEQUENCE_TRANSFER_STEP; 4964: } 4965: 4966: /* otherwise, do the bus cycles the slow way: */ 4967: else { 4968: tme_m68k_read32(ic, tlb, 4969: &function_code, 4970: &ic->tme_m68k_ireg_a7, 4971: _value, 4972: TME_M68K_BUS_CYCLE_NORMAL); 4973: } 4974: 1.1.1.4 root 4975: /* unbusy this TLB entry: */ 4976: tme_m68k_tlb_unbusy(tlb); 4977: 1.1 root 4978: /* log the value read: */ 4979: tme_m68k_verify_mem32(ic, function_code, ic->tme_m68k_ireg_a7, *_value, TME_BUS_CYCLE_READ); 4980: tme_m68k_log(ic, 1000, TME_OK, 4981: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 4982: _("pop32 %d:0x%08x: 0x%08x"), 1.1 root 4983: function_code, 4984: ic->tme_m68k_ireg_a7, 4985: *_value)); 4986: if (!TME_M68K_SEQUENCE_RESTARTING) { 4987: ic->tme_m68k_ireg_a7 += sizeof(tme_uint32_t); 4988: } 4989: } 4990: 4991: /* this writes a 32-bit memx value: */ 4992: void 4993: tme_m68k_write_memx32(struct tme_m68k *ic) 4994: { 1.1.1.5 ! root 4995: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 4996: unsigned int function_code = ic->_tme_m68k_ea_function_code; 4997: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 4998: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 4999: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 5000: tme_uint32_t mem_value; 5001: tme_shared tme_uint32_t *mem; 1.1 root 5002: 1.1.1.3 root 5003: #ifdef _TME_M68K_STATS 5004: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 5005: #endif /* _TME_M68K_STATS */ 5006: 1.1 root 5007: /* log the value written: */ 5008: tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx32, TME_BUS_CYCLE_WRITE); 5009: tme_m68k_log(ic, 1000, TME_OK, 5010: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 5011: _("write_memx32 %d:0x%08x: 0x%08x"), 1.1 root 5012: ic->_tme_m68k_ea_function_code, 5013: ic->_tme_m68k_ea_address, 5014: ic->tme_m68k_ireg_memx32)); 5015: 1.1.1.4 root 5016: /* busy this TLB entry: */ 5017: tme_m68k_tlb_busy(tlb); 5018: 5019: /* if we aren't restarting, and this address is properly aligned, 5020: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 5021: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 5022: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 5023: && tme_m68k_tlb_is_valid(tlb) ! 5024: && tlb->tme_m68k_tlb_bus_context == bus_context ! 5025: && (tlb->tme_m68k_tlb_function_codes_mask ! 5026: & TME_BIT(function_code)) ! 5027: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 5028: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 5029: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 5030: 1.1.1.4 root 5031: /* make the emulator memory pointer: */ 5032: mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 5033: 5034: /* get the value to write, in big-endian byte order: */ 5035: mem_value = tme_htobe_u32(ic->tme_m68k_ireg_memx32); 5036: 5037: /* do the 32-bit bus write: */ 5038: tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 5039: 5040: /* step the transfer count: */ 1.1 root 5041: TME_M68K_SEQUENCE_TRANSFER_STEP; 5042: } 5043: 5044: /* otherwise, do the bus cycles the slow way: */ 5045: else { 5046: tme_m68k_write32(ic, tlb, 5047: &ic->_tme_m68k_ea_function_code, 5048: &ic->_tme_m68k_ea_address, 5049: &ic->tme_m68k_ireg_memx32, 5050: TME_M68K_BUS_CYCLE_NORMAL); 5051: } 1.1.1.4 root 5052: 5053: /* unbusy this TLB entry: */ 5054: tme_m68k_tlb_unbusy(tlb); 1.1 root 5055: } 5056: 5057: /* this writes a 32-bit mem value: */ 5058: void 5059: tme_m68k_write_mem32(struct tme_m68k *ic, int ireg) 5060: { 1.1.1.5 ! root 5061: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 5062: unsigned int function_code = ic->_tme_m68k_ea_function_code; 5063: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 5064: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 5065: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 5066: tme_uint32_t mem_value; 5067: tme_shared tme_uint32_t *mem; 1.1 root 5068: 1.1.1.3 root 5069: #ifdef _TME_M68K_STATS 5070: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 5071: #endif /* _TME_M68K_STATS */ 5072: 1.1 root 5073: /* log the value written: */ 5074: tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint32(ireg), TME_BUS_CYCLE_WRITE); 5075: tme_m68k_log(ic, 1000, TME_OK, 5076: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 5077: _("write_mem32 %d:0x%08x: 0x%08x"), 1.1 root 5078: ic->_tme_m68k_ea_function_code, 5079: ic->_tme_m68k_ea_address, 5080: ic->tme_m68k_ireg_uint32(ireg))); 5081: 1.1.1.4 root 5082: /* busy this TLB entry: */ 5083: tme_m68k_tlb_busy(tlb); 5084: 5085: /* if we aren't restarting, and this address is properly aligned, 5086: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 5087: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 5088: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 5089: && tme_m68k_tlb_is_valid(tlb) ! 5090: && tlb->tme_m68k_tlb_bus_context == bus_context ! 5091: && (tlb->tme_m68k_tlb_function_codes_mask ! 5092: & TME_BIT(function_code)) ! 5093: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 5094: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 5095: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 5096: 1.1.1.4 root 5097: /* make the emulator memory pointer: */ 5098: mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 5099: 5100: /* get the value to write, in big-endian byte order: */ 5101: mem_value = tme_htobe_u32(ic->tme_m68k_ireg_uint32(ireg)); 5102: 5103: /* do the 32-bit bus write: */ 5104: tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 5105: 5106: /* step the transfer count: */ 1.1 root 5107: TME_M68K_SEQUENCE_TRANSFER_STEP; 5108: } 5109: 5110: /* otherwise, do the bus cycles the slow way: */ 5111: else { 5112: tme_m68k_write32(ic, tlb, 5113: &ic->_tme_m68k_ea_function_code, 5114: &ic->_tme_m68k_ea_address, 5115: &ic->tme_m68k_ireg_uint32(ireg), 5116: TME_M68K_BUS_CYCLE_NORMAL); 5117: } 1.1.1.4 root 5118: 5119: /* unbusy this TLB entry: */ 5120: tme_m68k_tlb_unbusy(tlb); 1.1 root 5121: } 5122: 5123: /* this writes a 32-bit stack value: */ 5124: void 5125: tme_m68k_push32(struct tme_m68k *ic, tme_uint32_t value) 5126: { 1.1.1.5 ! root 5127: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 5128: unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 5129: tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7 - sizeof(tme_uint32_t); 5130: tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; 1.1.1.5 ! root 5131: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1.1.4 root 5132: tme_uint32_t mem_value; 5133: tme_shared tme_uint32_t *mem; 1.1 root 5134: 1.1.1.3 root 5135: #ifdef _TME_M68K_STATS 5136: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 5137: #endif /* _TME_M68K_STATS */ 5138: 1.1 root 5139: /* log the value written: */ 5140: tme_m68k_verify_mem32(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE); 5141: tme_m68k_log(ic, 1000, TME_OK, 5142: (TME_M68K_LOG_HANDLE(ic), 1.1.1.5 ! root 5143: _("push32 %d:0x%08x: 0x%08x"), 1.1 root 5144: function_code, 5145: linear_address_first, 5146: value)); 5147: 1.1.1.4 root 5148: /* busy this TLB entry: */ 5149: tme_m68k_tlb_busy(tlb); 5150: 5151: /* if we aren't restarting, and this address is properly aligned, 5152: and this TLB entry covers the operand and allows fast writes: */ 1.1 root 5153: if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING 1.1.1.4 root 5154: && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0 1.1.1.5 ! root 5155: && tme_m68k_tlb_is_valid(tlb) ! 5156: && tlb->tme_m68k_tlb_bus_context == bus_context ! 5157: && (tlb->tme_m68k_tlb_function_codes_mask ! 5158: & TME_BIT(function_code)) ! 5159: && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 5160: && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last ! 5161: && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 5162: 1.1.1.4 root 5163: /* make the emulator memory pointer: */ 5164: mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first); 5165: 5166: /* get the value to write, in big-endian byte order: */ 5167: mem_value = tme_htobe_u32(value); 5168: 5169: /* do the 32-bit bus write: */ 5170: tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t)); 5171: 5172: /* step the transfer count: */ 1.1 root 5173: TME_M68K_SEQUENCE_TRANSFER_STEP; 5174: } 5175: 5176: /* otherwise, do the bus cycles the slow way: */ 5177: else { 5178: tme_m68k_write32(ic, tlb, 5179: &function_code, 5180: &linear_address_first, 5181: &value, 5182: TME_M68K_BUS_CYCLE_NORMAL); 5183: } 1.1.1.4 root 5184: 5185: /* unbusy this TLB entry: */ 5186: tme_m68k_tlb_unbusy(tlb); 1.1 root 5187: if (!TME_M68K_SEQUENCE_RESTARTING) { 5188: ic->tme_m68k_ireg_a7 -= sizeof(tme_uint32_t); 5189: } 5190: } 5191: 5192: /* this reads a any-bit mem value: */ 5193: void 5194: tme_m68k_read_mem(struct tme_m68k *ic, tme_uint8_t *buffer, unsigned int count) 5195: { 1.1.1.5 ! root 5196: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 5197: unsigned int function_code = ic->_tme_m68k_ea_function_code; 5198: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 5199: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1 root 5200: 1.1.1.3 root 5201: #ifdef _TME_M68K_STATS 5202: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 5203: #endif /* _TME_M68K_STATS */ 5204: 1.1.1.4 root 5205: /* busy this TLB entry: */ 5206: tme_m68k_tlb_busy(tlb); 1.1 root 5207: 1.1.1.4 root 5208: /* call the full read function: */ 5209: tme_m68k_read(ic, tlb, &ic->_tme_m68k_ea_function_code, &ic->_tme_m68k_ea_address, buffer, count, TME_M68K_BUS_CYCLE_RAW); 1.1 root 5210: 1.1.1.4 root 5211: /* unbusy this TLB entry: */ 5212: tme_m68k_tlb_unbusy(tlb); 1.1 root 5213: 5214: /* log the value read: */ 5215: tme_m68k_verify_mem_any(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, buffer, count, TME_BUS_CYCLE_READ); 5216: tme_m68k_log_start(ic, 1000, TME_OK) { 5217: unsigned int byte_i; 5218: tme_log_part(TME_M68K_LOG_HANDLE(ic), 5219: _("read_mem %d:0x%08x count %d:"), 5220: ic->_tme_m68k_ea_function_code, 5221: ic->_tme_m68k_ea_address, 5222: count); 5223: for (byte_i = 0; byte_i < count ; byte_i++) { 5224: tme_log_part(TME_M68K_LOG_HANDLE(ic), " 0x%02x", (buffer)[byte_i]); 5225: } 5226: } tme_m68k_log_finish(ic); 5227: } 5228: 5229: /* this reads a region of address space using actual bus cycles: */ 5230: void 5231: tme_m68k_read(struct tme_m68k *ic, 5232: struct tme_m68k_tlb *tlb, 5233: unsigned int *_function_code, 5234: tme_uint32_t *_linear_address, 5235: tme_uint8_t *reg, 5236: unsigned int reg_size, 5237: unsigned int flags) 5238: { 5239: unsigned int function_code; 5240: tme_uint32_t linear_address; 5241: tme_bus_addr_t physical_address; 5242: int shift; 5243: struct tme_bus_cycle cycle; 5244: unsigned int transferred, resid, cycle_size; 5245: int exception; 5246: int err; 5247: tme_uint8_t *reg_p; 5248: unsigned int buffer_i; 1.1.1.4 root 5249: tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2]; 5250: const tme_shared tme_uint8_t *mem; 1.1 root 5251: 5252: /* if we're not restarting, everything is fresh: */ 5253: if (!TME_M68K_SEQUENCE_RESTARTING) { 5254: function_code = *_function_code; 5255: linear_address = *_linear_address; 5256: transferred = 0; 5257: } 5258: 5259: /* otherwise, if this is the transfer that faulted, restore 5260: our state to the cycle that faulted, then take into account 5261: any data provided by a software rerun of the faulted cycle: */ 5262: else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted 5263: == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) { 5264: function_code = *_function_code = ic->_tme_m68k_group0_function_code; 5265: linear_address = ic->_tme_m68k_group0_address; 5266: transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after; 5267: if (transferred >= reg_size) abort(); 5268: *_linear_address = linear_address - transferred; 5269: resid = reg_size - transferred; 5270: if (ic->_tme_m68k_group0_buffer_read_size > resid) abort(); 5271: if (ic->_tme_m68k_group0_buffer_read_softrr > resid) abort(); 5272: if (ic->_tme_m68k_group0_buffer_read_softrr > 0) { 5273: #ifdef WORDS_BIGENDIAN 5274: memcpy(reg + transferred, 5275: ic->_tme_m68k_group0_buffer_read, 5276: ic->_tme_m68k_group0_buffer_read_size); 5277: #else /* !WORDS_BIGENDIAN */ 5278: reg_p = (reg + reg_size - 1) - transferred; 5279: for (buffer_i = 0; 5280: buffer_i < ic->_tme_m68k_group0_buffer_read_size; 5281: buffer_i++) { 5282: *(reg_p--) = ic->_tme_m68k_group0_buffer_read[buffer_i]; 5283: } 5284: #endif /* !WORDS_BIGENDIAN */ 5285: } 5286: transferred += ic->_tme_m68k_group0_buffer_read_softrr; 5287: } 5288: 5289: /* otherwise, a later transfer has faulted. just step the 5290: transfer number and return: */ 5291: else { 5292: TME_M68K_SEQUENCE_TRANSFER_STEP; 5293: return; 5294: } 5295: 5296: /* do as many bus cycles as needed to complete the transfer: */ 5297: exception = TME_M68K_EXCEPTION_NONE; 5298: cycle_size = 0; 5299: for(; transferred < reg_size; ) { 5300: resid = reg_size - transferred; 5301: 5302: /* start the bus cycle structure: */ 5303: cycle.tme_bus_cycle_type = TME_BUS_CYCLE_READ; 5304: if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG 5305: || (flags & TME_M68K_BUS_CYCLE_RAW)) { 5306: cycle.tme_bus_cycle_buffer = reg + transferred; 5307: cycle.tme_bus_cycle_buffer_increment = 1; 5308: } 5309: else { 5310: cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred); 5311: cycle.tme_bus_cycle_buffer_increment = -1; 5312: } 5313: 5314: /* if we're emulating a CPU with a 16-bit bus interface: */ 5315: if (ic->_tme_m68k_bus_16bit) { 5316: 5317: /* if we're trying to transfer a non-power-of-two 5318: number of bytes, either the CPU is broken (no 5319: instructions ever transfer a non-power-of-two 5320: number of bytes), or this function allowed an 5321: unaligned transfer: */ 5322: assert((resid & (resid - 1)) == 0 5323: || (flags & TME_M68K_BUS_CYCLE_RAW)); 5324: 5325: /* only byte transfers can be unaligned: */ 5326: if (resid > sizeof(tme_uint8_t) 5327: && (linear_address & 1)) { 1.1.1.3 root 5328: exception = TME_M68K_EXCEPTION_AERR; 1.1 root 5329: break; 5330: } 5331: 5332: /* set the bus-size specific parts of the bus cycle structure: */ 5333: cycle_size = TME_MIN(resid, sizeof(tme_uint16_t)); 5334: cycle.tme_bus_cycle_size = cycle_size; 5335: cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2); 5336: cycle.tme_bus_cycle_lane_routing = 5337: &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)]; 5338: } 5339: 5340: /* otherwise we're emulating a CPU with a 32-bit bus interface: */ 5341: else { 5342: 5343: /* an instruction fetch must be aligned: */ 5344: if (flags & TME_M68K_BUS_CYCLE_FETCH) { 5345: if (linear_address & 1) { 1.1.1.3 root 5346: exception = TME_M68K_EXCEPTION_AERR; 1.1 root 5347: break; 5348: } 5349: assert(!(resid & 1)); 5350: } 5351: 5352: /* set the bus-size specific parts of the bus cycle structure: */ 5353: cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1))); 5354: cycle.tme_bus_cycle_size = cycle_size; 5355: cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2); 5356: cycle.tme_bus_cycle_lane_routing = 5357: &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)]; 5358: } 5359: 1.1.1.4 root 5360: /* loop while this TLB entry is invalid or does not apply: */ 1.1.1.5 ! root 5361: for (; __tme_predict_false(tme_m68k_tlb_is_invalid(tlb) ! 5362: || tlb->tme_m68k_tlb_bus_context != ic->_tme_m68k_bus_context 1.1.1.4 root 5363: || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0 1.1.1.5 ! root 5364: || linear_address < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 5365: || linear_address > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last 1.1.1.4 root 5366: || (tlb->tme_m68k_tlb_emulator_off_read == TME_EMULATOR_OFF_UNDEF 5367: && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_READ) == 0)); ) { 5368: 5369: /* this must not be part of a read/modify/write cycle: */ 5370: assert(!(flags & TME_M68K_BUS_CYCLE_RMW)); 5371: 5372: /* fill this TLB entry: */ 1.1 root 5373: tme_m68k_tlb_fill(ic, tlb, 5374: function_code, 5375: linear_address, 5376: TME_BUS_CYCLE_READ); 5377: } 5378: 1.1.1.4 root 5379: /* if this TLB entry allows for fast reads: */ 5380: mem = tlb->tme_m68k_tlb_emulator_off_read; 5381: if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 5382: 1.1.1.4 root 5383: /* make the emulator memory pointer: */ 5384: mem += linear_address; 5385: 5386: /* limit the cycle size to addresses covered by the TLB entry: */ 5387: if (__tme_predict_false((cycle_size - 1) 1.1.1.5 ! root 5388: > (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address))) { ! 5389: cycle_size = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address) + 1; 1.1 root 5390: } 5391: 1.1.1.4 root 5392: /* if this is a little-endian host, and this isn't a raw read: */ 5393: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 5394: && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) { 5395: 5396: /* use the intermediate buffer for the read: */ 5397: cycle.tme_bus_cycle_buffer = ®_buffer[0]; 1.1 root 5398: } 1.1.1.4 root 5399: 5400: /* do the bus read: */ 5401: tme_memory_bus_read_buffer(mem, 5402: cycle.tme_bus_cycle_buffer, 5403: cycle_size, 5404: tlb->tme_m68k_tlb_bus_rwlock, 5405: sizeof(tme_uint8_t), 5406: sizeof(tme_uint32_t)); 5407: 5408: /* if this is a little-endian host, and this isn't a raw read: */ 5409: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 5410: && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) { 5411: 5412: /* byteswap the read data in the intermediate buffer: */ 5413: reg_p = reg + reg_size - (1 + transferred); 5414: buffer_i = 0; 5415: do { 5416: *(reg_p--) = reg_buffer[buffer_i]; 5417: } while (++buffer_i != cycle_size); 5418: } 5419: 5420: /* update: */ 5421: linear_address += cycle_size; 5422: transferred += cycle_size; 5423: continue; 5424: } 5425: 5426: /* otherwise, this TLB entry does not allow for fast reads: */ 5427: 5428: /* if this is a part of a read/modify/write cycle: */ 5429: if (flags & TME_M68K_BUS_CYCLE_RMW) { 5430: 5431: /* if this is the first cycle in this read, 5432: we will establish the new lock, otherwise 5433: we will continue using the existing lock: */ 5434: cycle.tme_bus_cycle_type 5435: |= (TME_BUS_CYCLE_LOCK 5436: | (transferred == 0 ? 0 : TME_BUS_CYCLE_UNLOCK)); 1.1 root 5437: } 5438: 5439: /* form the physical address for the bus cycle handler: */ 5440: physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address; 5441: shift = tlb->tme_m68k_tlb_addr_shift; 5442: if (shift < 0) { 5443: physical_address <<= (0 - shift); 5444: } 5445: else if (shift > 0) { 5446: physical_address >>= shift; 5447: } 5448: cycle.tme_bus_cycle_address = physical_address; 5449: 5450: /* run the bus cycle: */ 1.1.1.4 root 5451: tme_m68k_tlb_unbusy(tlb); 5452: tme_m68k_callout_unlock(ic); 1.1 root 5453: err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle) 5454: (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle); 1.1.1.4 root 5455: tme_m68k_callout_relock(ic); 5456: tme_m68k_tlb_busy(tlb); 1.1 root 5457: 1.1.1.4 root 5458: /* if the TLB entry was invalidated before the read: */ 5459: if (err == EBADF 1.1.1.5 ! root 5460: && tme_m68k_tlb_is_invalid(tlb)) { 1.1.1.4 root 5461: cycle.tme_bus_cycle_size = 0; 1.1 root 5462: } 5463: 1.1.1.3 root 5464: /* otherwise, if we didn't get a bus error, but some 5465: synchronous event has happened: */ 5466: else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) { 5467: 5468: /* after the currently executing instruction finishes, check 5469: for external resets, halts, or interrupts: */ 5470: ic->_tme_m68k_instruction_burst_remaining = 0; 5471: } 5472: 1.1 root 5473: /* otherwise, any other error might be a bus error: */ 5474: else if (err != TME_OK) { 5475: err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err); 5476: if (err != TME_OK) { 1.1.1.3 root 5477: exception = TME_M68K_EXCEPTION_BERR; 1.1 root 5478: break; 5479: } 5480: } 5481: 5482: /* update: */ 5483: linear_address += cycle.tme_bus_cycle_size; 5484: transferred += cycle.tme_bus_cycle_size; 5485: } 5486: 1.1.1.4 root 5487: /* NB: there is no need to explicitly unlock 5488: a device. if a locked bus cycle to a device 5489: faults, the lock must be automatically unlocked: */ 1.1 root 5490: 5491: /* if we faulted, stash the information the fault stacker 5492: will need and start exception processing: */ 5493: if (exception != TME_M68K_EXCEPTION_NONE) { 5494: ic->_tme_m68k_group0_flags = flags | TME_M68K_BUS_CYCLE_READ; 5495: ic->_tme_m68k_group0_function_code = function_code; 5496: ic->_tme_m68k_group0_address = linear_address; 5497: ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence; 5498: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred; 5499: ic->_tme_m68k_group0_buffer_read_size = cycle_size; 5500: if (ic->_tme_m68k_group0_hook != NULL) { 5501: (*ic->_tme_m68k_group0_hook)(ic); 5502: } 5503: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = 5504: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next; 1.1.1.4 root 5505: tme_m68k_tlb_unbusy(tlb); 1.1 root 5506: tme_m68k_exception(ic, exception); 5507: } 5508: 5509: /* otherwise, this transfer has now completed: */ 5510: TME_M68K_SEQUENCE_TRANSFER_STEP; 5511: } 5512: 5513: /* this writes a any-bit mem value: */ 5514: void 5515: tme_m68k_write_mem(struct tme_m68k *ic, tme_uint8_t *buffer, unsigned int count) 5516: { 1.1.1.5 ! root 5517: tme_bus_context_t bus_context = ic->_tme_m68k_bus_context; 1.1 root 5518: unsigned int function_code = ic->_tme_m68k_ea_function_code; 5519: tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address; 1.1.1.5 ! root 5520: struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first); 1.1 root 5521: 1.1.1.3 root 5522: #ifdef _TME_M68K_STATS 5523: ic->tme_m68k_stats.tme_m68k_stats_memory_total++; 5524: #endif /* _TME_M68K_STATS */ 5525: 1.1 root 5526: /* log the value written: */ 5527: tme_m68k_verify_mem_any(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, buffer, count, TME_BUS_CYCLE_WRITE); 5528: tme_m68k_log_start(ic, 1000, TME_OK) { 5529: unsigned int byte_i; 5530: tme_log_part(TME_M68K_LOG_HANDLE(ic), 5531: _("write_mem %d:0x%08x count %d:"), 5532: ic->_tme_m68k_ea_function_code, 5533: ic->_tme_m68k_ea_address, 5534: count); 5535: for (byte_i = 0; byte_i < count ; byte_i++) { 5536: tme_log_part(TME_M68K_LOG_HANDLE(ic), " 0x%02x", (buffer)[byte_i]); 5537: } 5538: } tme_m68k_log_finish(ic); 5539: 1.1.1.4 root 5540: /* busy this TLB entry: */ 5541: tme_m68k_tlb_busy(tlb); 1.1 root 5542: 1.1.1.4 root 5543: /* call the full write function: */ 5544: tme_m68k_write(ic, tlb, &ic->_tme_m68k_ea_function_code, &ic->_tme_m68k_ea_address, buffer, count, TME_M68K_BUS_CYCLE_RAW); 1.1 root 5545: 1.1.1.4 root 5546: /* unbusy this TLB entry: */ 5547: tme_m68k_tlb_unbusy(tlb); 1.1 root 5548: } 5549: 5550: /* this writes a region of address space using actual bus cycles: */ 5551: void 5552: tme_m68k_write(struct tme_m68k *ic, 5553: struct tme_m68k_tlb *tlb, 5554: unsigned int *_function_code, 5555: tme_uint32_t *_linear_address, 5556: tme_uint8_t *reg, 5557: unsigned int reg_size, 5558: unsigned int flags) 5559: { 5560: unsigned int function_code; 5561: tme_uint32_t linear_address; 5562: tme_bus_addr_t physical_address; 5563: int shift; 5564: struct tme_bus_cycle cycle; 5565: unsigned int transferred, resid, cycle_size; 5566: int exception; 5567: int err; 5568: tme_uint8_t *reg_p; 5569: unsigned int buffer_i; 1.1.1.4 root 5570: tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2]; 5571: tme_shared tme_uint8_t *mem; 1.1 root 5572: 5573: /* if we're not restarting, everything is fresh: */ 5574: if (!TME_M68K_SEQUENCE_RESTARTING) { 5575: function_code = *_function_code; 5576: linear_address = *_linear_address; 5577: transferred = 0; 5578: } 5579: 5580: /* otherwise, if this is the transfer that faulted, restore 5581: our state to the cycle that faulted, then take into account 5582: any data provided by a software rerun of the faulted cycle: */ 5583: else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted 5584: == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) { 5585: function_code = *_function_code = ic->_tme_m68k_group0_function_code; 5586: linear_address = ic->_tme_m68k_group0_address; 5587: transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after; 5588: if (transferred >= reg_size) abort(); 5589: *_linear_address = linear_address - transferred; 5590: resid = reg_size - transferred; 5591: if (ic->_tme_m68k_group0_buffer_write_size > resid) abort(); 5592: if (ic->_tme_m68k_group0_buffer_write_softrr > resid) abort(); 5593: if (ic->_tme_m68k_group0_buffer_write_softrr == 0) { 5594: #ifdef WORDS_BIGENDIAN 5595: memcpy(reg + transferred, 5596: ic->_tme_m68k_group0_buffer_write, 5597: ic->_tme_m68k_group0_buffer_write_size); 5598: #else /* !WORDS_BIGENDIAN */ 5599: reg_p = (reg + reg_size - 1) - transferred; 5600: for (buffer_i = 0; 5601: buffer_i < ic->_tme_m68k_group0_buffer_write_size; 5602: buffer_i++) { 5603: *(reg_p--) = ic->_tme_m68k_group0_buffer_write[buffer_i]; 5604: } 5605: #endif /* !WORDS_BIGENDIAN */ 5606: } 5607: transferred += ic->_tme_m68k_group0_buffer_write_softrr; 5608: } 5609: 5610: /* otherwise, a later transfer has faulted. just step the 5611: transfer number and return: */ 5612: else { 5613: TME_M68K_SEQUENCE_TRANSFER_STEP; 5614: return; 5615: } 5616: 5617: /* do as many bus cycles as needed to complete the transfer: */ 5618: exception = TME_M68K_EXCEPTION_NONE; 5619: cycle_size = 0; 5620: for(; transferred < reg_size; ) { 5621: resid = reg_size - transferred; 5622: 5623: /* start the bus cycle structure: */ 5624: cycle.tme_bus_cycle_type = TME_BUS_CYCLE_WRITE; 5625: if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG 5626: || (flags & TME_M68K_BUS_CYCLE_RAW)) { 5627: cycle.tme_bus_cycle_buffer = reg + transferred; 5628: cycle.tme_bus_cycle_buffer_increment = 1; 5629: } 5630: else { 5631: cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred); 5632: cycle.tme_bus_cycle_buffer_increment = -1; 5633: } 5634: 5635: /* if we're emulating a CPU with a 16-bit bus interface: */ 5636: if (ic->_tme_m68k_bus_16bit) { 5637: 5638: /* if we're trying to transfer a non-power-of-two 5639: number of bytes, either the CPU is broken (no 5640: instructions ever transfer a non-power-of-two 5641: number of bytes), or this function allowed an 5642: unaligned transfer: */ 5643: assert((resid & (resid - 1)) == 0 5644: || (flags & TME_M68K_BUS_CYCLE_RAW)); 5645: 5646: /* only byte transfers can be unaligned: */ 5647: if (resid > sizeof(tme_uint8_t) 5648: && (linear_address & 1)) { 1.1.1.3 root 5649: exception = TME_M68K_EXCEPTION_AERR; 1.1 root 5650: break; 5651: } 5652: 5653: /* set the bus-size specific parts of the bus cycle structure: */ 5654: cycle_size = TME_MIN(resid, sizeof(tme_uint16_t)); 5655: cycle.tme_bus_cycle_size = cycle_size; 5656: cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2); 5657: cycle.tme_bus_cycle_lane_routing = 5658: &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)]; 5659: } 5660: 5661: /* otherwise we're emulating a CPU with a 32-bit bus interface: */ 5662: else { 5663: 5664: /* set the bus-size specific parts of the bus cycle structure: */ 5665: cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1))); 5666: cycle.tme_bus_cycle_size = cycle_size; 5667: cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2); 5668: cycle.tme_bus_cycle_lane_routing = 5669: &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)]; 5670: } 5671: 1.1.1.4 root 5672: /* loop while this TLB entry is invalid or does not apply: */ 1.1.1.5 ! root 5673: for (; __tme_predict_false(tme_m68k_tlb_is_invalid(tlb) ! 5674: || tlb->tme_m68k_tlb_bus_context != ic->_tme_m68k_bus_context 1.1.1.4 root 5675: || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0 1.1.1.5 ! root 5676: || linear_address < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first ! 5677: || linear_address > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last 1.1.1.4 root 5678: || (tlb->tme_m68k_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF 5679: && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_WRITE) == 0)); ) { 5680: 5681: /* this must not be part of a read/modify/write cycle: */ 5682: assert(!(flags & TME_M68K_BUS_CYCLE_RMW)); 5683: 5684: /* fill this TLB entry: */ 1.1 root 5685: tme_m68k_tlb_fill(ic, tlb, 5686: function_code, 5687: linear_address, 5688: TME_BUS_CYCLE_WRITE); 5689: } 5690: 1.1.1.4 root 5691: /* if this TLB entry allows for fast writes: */ 5692: mem = tlb->tme_m68k_tlb_emulator_off_write; 5693: if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) { 1.1 root 5694: 1.1.1.4 root 5695: /* make the emulator memory pointer: */ 5696: mem += linear_address; 5697: 5698: /* limit the cycle size to addresses covered by the TLB entry: */ 5699: if (__tme_predict_false((cycle_size - 1) 1.1.1.5 ! root 5700: > (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address))) { ! 5701: cycle_size = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address) + 1; 1.1 root 5702: } 5703: 1.1.1.4 root 5704: /* if this is a little-endian host, and this isn't a raw write: */ 5705: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE 5706: && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) { 5707: 5708: /* byteswap the data to write in the intermediate buffer: */ 5709: reg_p = cycle.tme_bus_cycle_buffer; 5710: buffer_i = 0; 5711: do { 5712: reg_buffer[buffer_i] = *(reg_p--); 5713: } while (++buffer_i != cycle_size); 5714: 5715: /* use the intermediate buffer for the write: */ 5716: cycle.tme_bus_cycle_buffer = ®_buffer[0]; 1.1 root 5717: } 1.1.1.4 root 5718: 5719: /* do the bus write: */ 5720: tme_memory_bus_write_buffer(mem, 5721: cycle.tme_bus_cycle_buffer, 5722: cycle_size, 5723: tlb->tme_m68k_tlb_bus_rwlock, 5724: sizeof(tme_uint8_t), 5725: sizeof(tme_uint32_t)); 5726: 5727: /* update: */ 5728: linear_address += cycle_size; 5729: transferred += cycle_size; 5730: continue; 5731: } 5732: 5733: /* otherwise, this TLB entry does not allow for fast writes: */ 5734: 5735: /* if this is a part of a read/modify/write cycle: */ 5736: if (flags & TME_M68K_BUS_CYCLE_RMW) { 5737: 5738: /* we will continue using the existing lock. 5739: the device will automatically unlock after 5740: the last cycle of this write: */ 5741: cycle.tme_bus_cycle_type 5742: |= (TME_BUS_CYCLE_LOCK 5743: | (TME_BUS_CYCLE_UNLOCK)); 1.1 root 5744: } 5745: 5746: /* form the physical address for the bus cycle handler: */ 5747: physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address; 5748: shift = tlb->tme_m68k_tlb_addr_shift; 5749: if (shift < 0) { 5750: physical_address <<= (0 - shift); 5751: } 5752: else if (shift > 0) { 5753: physical_address >>= shift; 5754: } 5755: cycle.tme_bus_cycle_address = physical_address; 5756: 5757: /* run the bus cycle: */ 1.1.1.4 root 5758: tme_m68k_tlb_unbusy(tlb); 5759: tme_m68k_callout_unlock(ic); 1.1 root 5760: err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle) 5761: (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle); 1.1.1.4 root 5762: tme_m68k_callout_relock(ic); 5763: tme_m68k_tlb_busy(tlb); 1.1 root 5764: 1.1.1.4 root 5765: /* if the TLB entry was invalidated before the write: */ 5766: if (err == EBADF 1.1.1.5 ! root 5767: && tme_m68k_tlb_is_invalid(tlb)) { 1.1.1.4 root 5768: cycle.tme_bus_cycle_size = 0; 1.1 root 5769: } 5770: 1.1.1.3 root 5771: /* otherwise, if we didn't get a bus error, but some 5772: synchronous event has happened: */ 5773: else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) { 5774: 5775: /* after the currently executing instruction finishes, check 5776: for external resets, halts, or interrupts: */ 5777: ic->_tme_m68k_instruction_burst_remaining = 0; 5778: } 5779: 1.1 root 5780: /* otherwise, any other error might be a bus error: */ 5781: else if (err != TME_OK) { 5782: err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err); 5783: if (err != TME_OK) { 1.1.1.3 root 5784: exception = TME_M68K_EXCEPTION_BERR; 1.1 root 5785: break; 5786: } 5787: } 5788: 5789: /* update: */ 5790: linear_address += cycle.tme_bus_cycle_size; 5791: transferred += cycle.tme_bus_cycle_size; 5792: } 5793: 1.1.1.4 root 5794: /* NB: there is no need to explicitly unlock 5795: a device. if a locked bus cycle to a device 5796: faults, the lock must be automatically unlocked: */ 1.1 root 5797: 5798: /* if we faulted, stash the information the fault stacker 5799: will need and start exception processing: */ 5800: if (exception != TME_M68K_EXCEPTION_NONE) { 5801: ic->_tme_m68k_group0_flags = flags; 5802: ic->_tme_m68k_group0_function_code = function_code; 5803: ic->_tme_m68k_group0_address = linear_address; 5804: ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence; 5805: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred; 5806: ic->_tme_m68k_group0_buffer_write_size = cycle_size; 5807: #ifdef WORDS_BIGENDIAN 5808: memcpy(ic->_tme_m68k_group0_buffer_write, 5809: reg + transferred, 5810: ic->_tme_m68k_group0_buffer_write_size); 5811: #else /* !WORDS_BIGENDIAN */ 5812: reg_p = (reg + reg_size - 1) - transferred; 5813: for (buffer_i = 0; 5814: buffer_i < ic->_tme_m68k_group0_buffer_write_size; 5815: buffer_i++) { 5816: ic->_tme_m68k_group0_buffer_write[buffer_i] = *(reg_p--); 5817: } 5818: #endif /* !WORDS_BIGENDIAN */ 5819: if (ic->_tme_m68k_group0_hook != NULL) { 5820: (*ic->_tme_m68k_group0_hook)(ic); 5821: } 5822: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = 5823: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next; 1.1.1.4 root 5824: tme_m68k_tlb_unbusy(tlb); 1.1 root 5825: tme_m68k_exception(ic, exception); 5826: } 5827: 5828: /* otherwise, this transfer has now completed: */ 5829: TME_M68K_SEQUENCE_TRANSFER_STEP; 5830: } 5831: 5832: TME_M68K_INSN(tme_m68k_abcd) 5833: { 5834: tme_uint8_t dst, dst_msd, dst_lsd; 5835: tme_uint8_t src, src_msd, src_lsd; 5836: tme_uint8_t res, res_msd, res_lsd; 5837: tme_uint8_t flags; 5838: int memory; 5839: int rx, ry, function_code; 5840: 5841: /* load the operands: */ 5842: rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 5843: ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 5844: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0; 5845: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 5846: if (memory) { 1.1.1.4 root 5847: TME_M68K_INSN_CANFAULT; 1.1 root 5848: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 5849: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3); 1.1 root 5850: ic->_tme_m68k_ea_function_code = function_code; 5851: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx); 5852: } 5853: tme_m68k_read_memx8(ic); 5854: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 5855: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3); 1.1 root 5856: ic->_tme_m68k_ea_function_code = function_code; 5857: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry); 5858: } 5859: tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32); 5860: src = ic->tme_m68k_ireg_memx8; 5861: dst = ic->tme_m68k_ireg_memy8; 5862: } 5863: else { 5864: src = ic->tme_m68k_ireg_uint8(rx << 2); 5865: dst = ic->tme_m68k_ireg_uint8(ry << 2); 5866: } 5867: dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4); 5868: dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4); 5869: src_lsd = TME_FIELD_EXTRACTU(src, 0, 4); 5870: src_msd = TME_FIELD_EXTRACTU(src, 4, 4); 5871: 5872: /* perform the operation: */ 5873: res_lsd = dst_lsd + src_lsd + ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0); 5874: res_msd = dst_msd + src_msd; 5875: flags = 0; 5876: if (res_lsd > 9) { 5877: res_lsd -= 10; 5878: res_msd += 1; 5879: } 5880: if (res_msd > 9) { 5881: res_msd -= 10; 5882: flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 5883: } 5884: res = (res_msd << 4) + (res_lsd & 0xf); 5885: if (res == 0) flags |= TME_M68K_FLAG_N; 5886: 5887: /* store the result and set the flags: */ 5888: if (memory) { 5889: if (!TME_M68K_SEQUENCE_RESTARTING) { 5890: ic->tme_m68k_ireg_memx8 = res; 5891: ic->_tme_m68k_ea_function_code = function_code; 5892: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry); 5893: ic->tme_m68k_ireg_ccr = flags; 5894: } 5895: tme_m68k_write_memx8(ic); 5896: } 5897: else { 5898: ic->tme_m68k_ireg_uint8(ry << 2) = res; 5899: ic->tme_m68k_ireg_ccr = flags; 5900: } 5901: 5902: TME_M68K_INSN_OK; 5903: } 5904: 5905: TME_M68K_INSN(tme_m68k_sbcd) 5906: { 5907: tme_uint8_t dst, dst_msd, dst_lsd; 5908: tme_uint8_t src, src_msd, src_lsd; 5909: tme_uint8_t res, res_msd, res_lsd; 5910: tme_uint8_t flags; 5911: int memory; 5912: int rx, ry, function_code; 5913: 5914: /* load the operands: */ 5915: rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); 5916: ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3); 5917: memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0; 5918: function_code = TME_M68K_FUNCTION_CODE_DATA(ic); 5919: if (memory) { 1.1.1.4 root 5920: TME_M68K_INSN_CANFAULT; 1.1 root 5921: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 5922: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3); 1.1 root 5923: ic->_tme_m68k_ea_function_code = function_code; 5924: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx); 5925: } 5926: tme_m68k_read_memx8(ic); 5927: if (!TME_M68K_SEQUENCE_RESTARTING) { 1.1.1.4 root 5928: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3); 1.1 root 5929: ic->_tme_m68k_ea_function_code = function_code; 5930: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry); 5931: } 5932: tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32); 5933: src = ic->tme_m68k_ireg_memx8; 5934: dst = ic->tme_m68k_ireg_memy8; 5935: } 5936: else { 5937: src = ic->tme_m68k_ireg_uint8(rx << 2); 5938: dst = ic->tme_m68k_ireg_uint8(ry << 2); 5939: } 5940: dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4); 5941: dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4); 5942: src_lsd = TME_FIELD_EXTRACTU(src, 0, 4); 5943: src_msd = TME_FIELD_EXTRACTU(src, 4, 4); 5944: 5945: /* perform the operation: */ 5946: res_lsd = dst_lsd - src_lsd - ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0); 5947: res_msd = dst_msd - src_msd; 5948: flags = 0; 5949: if (res_lsd > 9) { 5950: res_lsd += 10; 5951: res_msd -= 1; 5952: } 5953: if (res_msd > 9) { 5954: res_msd += 10; 5955: flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 5956: } 5957: res = (res_msd << 4) + (res_lsd & 0xf); 5958: if (res == 0) flags |= TME_M68K_FLAG_N; 5959: 5960: /* store the result and set the flags: */ 5961: if (memory) { 5962: if (!TME_M68K_SEQUENCE_RESTARTING) { 5963: ic->tme_m68k_ireg_memx8 = res; 5964: ic->_tme_m68k_ea_function_code = function_code; 5965: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry); 5966: ic->tme_m68k_ireg_ccr = flags; 5967: } 5968: tme_m68k_write_memx8(ic); 5969: } 5970: else { 5971: ic->tme_m68k_ireg_uint8(ry << 2) = res; 5972: ic->tme_m68k_ireg_ccr = flags; 5973: } 5974: 5975: TME_M68K_INSN_OK; 5976: } 5977: 5978: TME_M68K_INSN(tme_m68k_nbcd) 5979: { 5980: tme_uint8_t dst, dst_msd, dst_lsd; 5981: tme_uint8_t src, src_msd, src_lsd; 5982: tme_uint8_t res, res_msd, res_lsd; 5983: tme_uint8_t flags; 5984: 5985: dst = 0x00; 5986: src = TME_M68K_INSN_OP1(tme_uint8_t); 5987: dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4); 5988: dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4); 5989: src_lsd = TME_FIELD_EXTRACTU(src, 0, 4); 5990: src_msd = TME_FIELD_EXTRACTU(src, 4, 4); 5991: 5992: /* perform the operation: */ 5993: res_lsd = dst_lsd - src_lsd - ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0); 5994: res_msd = dst_msd - src_msd; 5995: flags = 0; 5996: if (res_lsd > 9) { 5997: res_lsd += 10; 5998: res_msd -= 1; 5999: } 6000: if (res_msd > 9) { 6001: res_msd += 10; 6002: flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X; 6003: } 6004: res = (res_msd << 4) + (res_lsd & 0xf); 6005: if (res == 0) flags |= TME_M68K_FLAG_N; 6006: 6007: /* store the result and set the flags: */ 6008: TME_M68K_INSN_OP1(tme_uint8_t) = res; 6009: ic->tme_m68k_ireg_ccr = flags; 6010: 6011: TME_M68K_INSN_OK; 6012: } 6013: 6014: TME_M68K_INSN(tme_m68k_ori_ccr) 6015: { 6016: tme_uint8_t reg; 6017: reg = ic->tme_m68k_ireg_ccr | (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR); 6018: ic->tme_m68k_ireg_ccr = reg; 6019: TME_M68K_INSN_OK; 6020: } 6021: 6022: TME_M68K_INSN(tme_m68k_andi_ccr) 6023: { 6024: tme_uint8_t reg; 6025: reg = ic->tme_m68k_ireg_ccr & (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR); 6026: ic->tme_m68k_ireg_ccr = reg; 6027: TME_M68K_INSN_OK; 6028: } 6029: 6030: TME_M68K_INSN(tme_m68k_eori_ccr) 6031: { 6032: tme_uint8_t reg; 6033: reg = ic->tme_m68k_ireg_ccr ^ (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR); 6034: ic->tme_m68k_ireg_ccr = reg; 6035: TME_M68K_INSN_OK; 6036: } 6037: 6038: TME_M68K_INSN(tme_m68k_move_to_ccr) 6039: { 6040: tme_uint8_t reg; 6041: reg = (TME_M68K_INSN_OP1(tme_uint16_t) & TME_M68K_FLAG_CCR); 6042: ic->tme_m68k_ireg_ccr = reg; 6043: TME_M68K_INSN_OK; 6044: } 6045: 6046: TME_M68K_INSN(tme_m68k_ori_sr) 6047: { 6048: tme_uint16_t reg; 6049: reg = ic->tme_m68k_ireg_sr | (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR); 6050: TME_M68K_INSN_PRIV; 6051: TME_M68K_INSN_CHANGE_SR(reg); 6052: TME_M68K_INSN_OK; 6053: } 6054: 6055: TME_M68K_INSN(tme_m68k_andi_sr) 6056: { 6057: tme_uint16_t reg; 6058: reg = ic->tme_m68k_ireg_sr & (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR); 6059: TME_M68K_INSN_PRIV; 6060: TME_M68K_INSN_CHANGE_SR(reg); 6061: TME_M68K_INSN_OK; 6062: } 6063: 6064: TME_M68K_INSN(tme_m68k_eori_sr) 6065: { 6066: tme_uint16_t reg; 6067: reg = ic->tme_m68k_ireg_sr ^ (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR); 6068: TME_M68K_INSN_PRIV; 6069: TME_M68K_INSN_CHANGE_SR(reg); 6070: TME_M68K_INSN_OK; 6071: } 6072: 6073: TME_M68K_INSN(tme_m68k_move_to_sr) 6074: { 6075: tme_uint16_t reg; 6076: reg = (TME_M68K_INSN_OP1(tme_uint16_t) & TME_M68K_FLAG_SR); 6077: TME_M68K_INSN_PRIV; 6078: TME_M68K_INSN_CHANGE_SR(reg); 6079: TME_M68K_INSN_OK; 6080: } 6081: 6082: TME_M68K_INSN(tme_m68k_mulu) 6083: { 6084: int ireg_dl; 6085: tme_uint32_t res; 6086: tme_uint8_t flags; 6087: 6088: /* get the register containing the factor: */ 6089: ireg_dl = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t); 6090: 6091: /* perform the multiplication: */ 6092: res = (((tme_uint32_t) ic->tme_m68k_ireg_uint16(ireg_dl << 1)) 6093: * TME_M68K_INSN_OP1(tme_uint16_t)); 6094: 6095: /* store the result: */ 6096: ic->tme_m68k_ireg_uint32(ireg_dl) = (tme_uint32_t) res; 6097: 6098: /* set the flags: */ 6099: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 6100: if (((tme_int32_t) res) < 0) flags |= TME_M68K_FLAG_N; 6101: if (res == 0) flags |= TME_M68K_FLAG_Z; 6102: ic->tme_m68k_ireg_ccr = flags; 6103: 6104: TME_M68K_INSN_OK; 6105: } 6106: 6107: TME_M68K_INSN(tme_m68k_divu) 6108: { 6109: int ireg_dq; 6110: tme_uint32_t dividend, quotient; 6111: tme_uint16_t divisor, remainder; 6112: tme_uint8_t flags; 6113: 6114: /* get the register(s): */ 6115: ireg_dq = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t); 6116: 6117: /* form the dividend and the divisor: */ 6118: dividend = (tme_uint32_t) ic->tme_m68k_ireg_uint32(ireg_dq); 6119: divisor = TME_M68K_INSN_OP1(tme_uint16_t); 6120: if (divisor == 0) { 1.1.1.3 root 6121: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 6122: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 6123: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); 1.1 root 6124: } 6125: 6126: /* do the division: */ 6127: quotient = dividend / divisor; 6128: remainder = dividend % divisor; 6129: 6130: /* set the flags and return the quotient and remainder: */ 6131: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 6132: if (quotient > 0xffff) { 6133: flags |= TME_M68K_FLAG_V; 6134: } 6135: else { 6136: if (((tme_int16_t) quotient) < 0) flags |= TME_M68K_FLAG_N; 6137: if (quotient == 0) flags |= TME_M68K_FLAG_Z; 6138: ic->tme_m68k_ireg_uint16(ireg_dq << 1) = (tme_uint16_t) quotient; 6139: ic->tme_m68k_ireg_uint16((ireg_dq << 1) + 1) = remainder; 6140: } 6141: ic->tme_m68k_ireg_ccr = flags; 6142: 6143: TME_M68K_INSN_OK; 6144: } 6145: 6146: TME_M68K_INSN(tme_m68k_mulul) 6147: { 1.1.1.2 root 6148: #ifndef TME_HAVE_INT64_T 1.1 root 6149: abort(); 1.1.1.2 root 6150: #else /* TME_HAVE_INT64_T */ 1.1 root 6151: unsigned int flag_v; 6152: int ireg_dh; 6153: int ireg_dl; 6154: tme_uint64_t res; 6155: tme_uint8_t flags; 6156: 6157: /* get the register containing the factor: */ 6158: ireg_dl = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3); 6159: 6160: /* perform the multiplication: */ 6161: res = (((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dl)) 6162: * TME_M68K_INSN_OP1(tme_uint32_t)); 6163: 6164: /* store the result: */ 6165: ic->tme_m68k_ireg_uint32(ireg_dl) = (tme_uint32_t) res; 6166: flag_v = TME_M68K_FLAG_V; 6167: if (TME_M68K_INSN_SPECOP & TME_BIT(10)) { 6168: flag_v = 0; 6169: ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 6170: ic->tme_m68k_ireg_uint32(ireg_dh) = (tme_uint32_t) (res >> 32); 6171: } 6172: 6173: /* set the flags: */ 6174: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 6175: if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N; 6176: if (res == 0) flags |= TME_M68K_FLAG_Z; 1.1.1.2 root 6177: if (res > 0xffffffffUL) flags |= flag_v; 1.1 root 6178: ic->tme_m68k_ireg_ccr = flags; 6179: 6180: TME_M68K_INSN_OK; 1.1.1.2 root 6181: #endif /* TME_HAVE_INT64_T */ 1.1 root 6182: } 6183: 6184: TME_M68K_INSN(tme_m68k_divul) 6185: { 1.1.1.2 root 6186: #ifndef TME_HAVE_INT64_T 1.1 root 6187: abort(); 1.1.1.2 root 6188: #else /* TME_HAVE_INT64_T */ 1.1 root 6189: int ireg_dr; 6190: int ireg_dq; 6191: tme_uint64_t dividend, quotient; 6192: tme_uint32_t divisor, remainder; 6193: tme_uint8_t flags; 6194: 6195: /* get the register(s): */ 6196: ireg_dq = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3); 6197: ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 6198: 6199: /* form the dividend and the divisor: */ 6200: if (TME_M68K_INSN_SPECOP & TME_BIT(10)) { 6201: dividend = (tme_uint64_t) 6202: ((((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32) 6203: | ic->tme_m68k_ireg_uint32(ireg_dq)); 6204: } 6205: else 6206: dividend = (tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dq); 6207: divisor = TME_M68K_INSN_OP1(tme_uint32_t); 6208: if (divisor == 0) { 1.1.1.3 root 6209: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 6210: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 6211: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); 1.1 root 6212: } 6213: 6214: /* do the division: */ 6215: quotient = dividend / divisor; 6216: remainder = dividend % divisor; 6217: 6218: /* set the flags and return the quotient and remainder: */ 6219: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1.1.1.2 root 6220: if (quotient > 0xffffffffUL) { 1.1 root 6221: flags |= TME_M68K_FLAG_V; 6222: } 6223: else { 6224: if (((tme_int32_t) quotient) < 0) flags |= TME_M68K_FLAG_N; 6225: if (quotient == 0) flags |= TME_M68K_FLAG_Z; 6226: ic->tme_m68k_ireg_uint32(ireg_dq) = (tme_uint32_t) quotient; 6227: if (ireg_dr != ireg_dq) { 6228: ic->tme_m68k_ireg_uint32(ireg_dr) = remainder; 6229: } 6230: } 6231: ic->tme_m68k_ireg_ccr = flags; 6232: 6233: TME_M68K_INSN_OK; 1.1.1.2 root 6234: #endif /* TME_HAVE_INT64_T */ 1.1 root 6235: } 6236: 6237: TME_M68K_INSN(tme_m68k_muls) 6238: { 6239: int ireg_dl; 6240: tme_int32_t res; 6241: tme_uint8_t flags; 6242: 6243: /* get the register containing the factor: */ 6244: ireg_dl = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t); 6245: 6246: /* perform the multiplication: */ 6247: res = (((tme_int32_t) ic->tme_m68k_ireg_int16(ireg_dl << 1)) 6248: * TME_M68K_INSN_OP1(tme_int16_t)); 6249: 6250: /* store the result: */ 6251: ic->tme_m68k_ireg_int32(ireg_dl) = (tme_int32_t) res; 6252: 6253: /* set the flags: */ 6254: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 6255: if (((tme_int32_t) res) < 0) flags |= TME_M68K_FLAG_N; 6256: if (res == 0) flags |= TME_M68K_FLAG_Z; 6257: ic->tme_m68k_ireg_ccr = flags; 6258: 6259: TME_M68K_INSN_OK; 6260: } 6261: 6262: TME_M68K_INSN(tme_m68k_divs) 6263: { 6264: int ireg_dq; 6265: tme_int32_t dividend, quotient; 6266: tme_int16_t divisor, remainder; 6267: tme_uint8_t flags; 6268: 6269: /* get the register(s): */ 6270: ireg_dq = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t); 6271: 6272: /* form the dividend and the divisor: */ 6273: dividend = (tme_int32_t) ic->tme_m68k_ireg_int32(ireg_dq); 6274: divisor = TME_M68K_INSN_OP1(tme_int16_t); 6275: if (divisor == 0) { 1.1.1.3 root 6276: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 6277: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 6278: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); 1.1 root 6279: } 6280: 6281: /* do the division: */ 6282: quotient = dividend / divisor; 6283: remainder = dividend % divisor; 6284: 6285: /* set the flags and return the quotient and remainder: */ 6286: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1.1.1.2 root 6287: if (quotient > 0x7fff || quotient < -32768) { 1.1 root 6288: flags |= TME_M68K_FLAG_V; 6289: } 6290: else { 6291: if (((tme_int16_t) quotient) < 0) flags |= TME_M68K_FLAG_N; 6292: if (quotient == 0) flags |= TME_M68K_FLAG_Z; 6293: ic->tme_m68k_ireg_int16(ireg_dq << 1) = (tme_int16_t) quotient; 6294: ic->tme_m68k_ireg_int16((ireg_dq << 1) + 1) = remainder; 6295: } 6296: ic->tme_m68k_ireg_ccr = flags; 6297: 6298: TME_M68K_INSN_OK; 6299: } 6300: 6301: TME_M68K_INSN(tme_m68k_mulsl) 6302: { 1.1.1.2 root 6303: #ifndef TME_HAVE_INT64_T 1.1 root 6304: abort(); 1.1.1.2 root 6305: #else /* TME_HAVE_INT64_T */ 1.1 root 6306: unsigned int flag_v; 6307: int ireg_dh; 6308: int ireg_dl; 6309: tme_int64_t res; 6310: tme_uint8_t flags; 6311: 6312: /* get the register containing the factor: */ 6313: ireg_dl = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3); 6314: 6315: /* perform the multiplication: */ 6316: res = (((tme_int64_t) ic->tme_m68k_ireg_int32(ireg_dl)) 6317: * TME_M68K_INSN_OP1(tme_int32_t)); 6318: 6319: /* store the result: */ 6320: ic->tme_m68k_ireg_int32(ireg_dl) = (tme_int32_t) res; 6321: flag_v = TME_M68K_FLAG_V; 6322: if (TME_M68K_INSN_SPECOP & TME_BIT(10)) { 6323: flag_v = 0; 6324: ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 6325: ic->tme_m68k_ireg_int32(ireg_dh) = (tme_int32_t) (res >> 32); 6326: } 6327: 6328: /* set the flags: */ 6329: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 6330: if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N; 6331: if (res == 0) flags |= TME_M68K_FLAG_Z; 1.1.1.2 root 6332: if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)) flags |= flag_v; 1.1 root 6333: ic->tme_m68k_ireg_ccr = flags; 6334: 6335: TME_M68K_INSN_OK; 1.1.1.2 root 6336: #endif /* TME_HAVE_INT64_T */ 1.1 root 6337: } 6338: 6339: TME_M68K_INSN(tme_m68k_divsl) 6340: { 1.1.1.2 root 6341: #ifndef TME_HAVE_INT64_T 1.1 root 6342: abort(); 1.1.1.2 root 6343: #else /* TME_HAVE_INT64_T */ 1.1 root 6344: int ireg_dr; 6345: int ireg_dq; 6346: tme_int64_t dividend, quotient; 6347: tme_int32_t divisor, remainder; 6348: tme_uint8_t flags; 6349: 6350: /* get the register(s): */ 6351: ireg_dq = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3); 6352: ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3); 6353: 6354: /* form the dividend and the divisor: */ 6355: if (TME_M68K_INSN_SPECOP & TME_BIT(10)) { 6356: dividend = (tme_int64_t) 6357: ((((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32) 6358: | ic->tme_m68k_ireg_uint32(ireg_dq)); 6359: } 6360: else 6361: dividend = (tme_int64_t) ic->tme_m68k_ireg_int32(ireg_dq); 6362: divisor = TME_M68K_INSN_OP1(tme_int32_t); 6363: if (divisor == 0) { 1.1.1.3 root 6364: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 1.1 root 6365: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 1.1.1.3 root 6366: TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); 1.1 root 6367: } 6368: 6369: /* do the division: */ 6370: quotient = dividend / divisor; 6371: remainder = dividend % divisor; 6372: 6373: /* set the flags and return the quotient and remainder: */ 6374: flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; 1.1.1.2 root 6375: if (quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)) { 1.1 root 6376: flags |= TME_M68K_FLAG_V; 6377: } 6378: else { 6379: if (((tme_int32_t) quotient) < 0) flags |= TME_M68K_FLAG_N; 6380: if (quotient == 0) flags |= TME_M68K_FLAG_Z; 6381: ic->tme_m68k_ireg_int32(ireg_dq) = (tme_int32_t) quotient; 6382: if (ireg_dr != ireg_dq) { 6383: ic->tme_m68k_ireg_int32(ireg_dr) = remainder; 6384: } 6385: } 6386: ic->tme_m68k_ireg_ccr = flags; 6387: 6388: TME_M68K_INSN_OK; 1.1.1.2 root 6389: #endif /* TME_HAVE_INT64_T */ 1.1 root 6390: } 6391: /* automatically generated by m68k-misc-auto.sh, do not edit! */ 6392: 6393: /* the flags->conditions mapping: */ 6394: const tme_uint16_t _tme_m68k_conditions[32] = { 6395: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6396: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6397: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6398: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6399: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6400: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6401: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6402: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6403: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6404: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6405: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6406: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6407: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6408: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6409: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6410: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6411: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6412: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6413: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6414: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6415: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6416: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6417: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6418: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6419: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6420: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6421: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6422: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT), 6423: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6424: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE), 6425: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6426: TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE), 6427: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.