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