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