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