This patch implements the full extension word format addressing mode in the m68k emulation. I have manually verified that it gets all cases right.
Andreas. Index: target-m68k/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-m68k/translate.c,v retrieving revision 1.5 diff -u -a -p -a -u -p -r1.5 target-m68k/translate.c --- target-m68k/translate.c 23 May 2007 19:58:11 -0000 1.5 +++ target-m68k/translate.c 26 May 2007 12:56:00 -0000 @@ -217,6 +217,18 @@ static int gen_ldst(DisasContext *s, int } } +/* Read a 32-bit immediate constant. */ +static inline uint32_t read_im32(DisasContext *s) +{ + uint32_t im; + im = ((uint32_t)lduw_code(s->pc)) << 16; + s->pc += 2; + im |= lduw_code(s->pc); + s->pc += 2; + return im; +} + + /* Handle a base + index + displacement effective addresss. A base of -1 means pc-relative. */ static int gen_lea_indexed(DisasContext *s, int opsize, int base) @@ -226,41 +238,105 @@ static int gen_lea_indexed(DisasContext uint16_t ext; int add; int tmp; + uint32_t bd, od; offset = s->pc; ext = lduw_code(s->pc); s->pc += 2; - tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0); - /* ??? Check W/L bit. */ - scale = (ext >> 9) & 3; - if (scale == 0) { - add = tmp; - } else { - add = gen_new_qreg(QMODE_I32); - gen_op_shl32(add, tmp, gen_im32(scale)); - } - tmp = gen_new_qreg(QMODE_I32); - if (base != -1) { - gen_op_add32(tmp, base, gen_im32((int8_t)ext)); - gen_op_add32(tmp, tmp, add); - } else { - gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext)); + if (ext & 0x100) { + /* full extension word format */ + if ((ext & 0x30) > 0x10) + /* base displacement */ + if ((ext & 0x30) == 0x20) { + bd = (int16_t)lduw_code(s->pc); + s->pc += 2; + } else + bd = read_im32(s); + else + bd = 0; + if ((ext & 0x40) == 0) { + /* index not suppressed */ + add = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0); + if ((ext & 0x800) == 0) { + tmp = gen_new_qreg(QMODE_I32); + gen_op_ext16s32(tmp, add); + add = tmp; + } + scale = (ext >> 9) & 3; + if (scale != 0) { + if ((ext & 0x800) == 0) + tmp = add; + else + tmp = gen_new_qreg(QMODE_I32); + gen_op_shl32(tmp, add, gen_im32(scale)); + add = tmp; + } + } + if ((ext & 0x80) == 0) { + /* base not suppressed */ + if (base == -1) + tmp = gen_im32(offset + bd); + else if (bd != 0) { + tmp = gen_new_qreg(QMODE_I32); + gen_op_add32(tmp, base, gen_im32(bd)); + } else + tmp = base; + if ((ext & 0x44) == 0) + gen_op_add32(tmp, tmp, add); + } else if (bd != 0) { + tmp = gen_im32(bd); + if ((ext & 0x44) == 0) + gen_op_add32(tmp, tmp, add); + } else if ((ext & 0x44) == 0) + tmp = add; + else + tmp = gen_im32(0); + if ((ext & 3) != 0) { + /* memory indirect */ + tmp = gen_load(s, OS_LONG, tmp, 0); + if ((ext & 0x44) == 4) + gen_op_add32(tmp, tmp, add); + if ((ext & 3) > 1) + /* outer displacement */ + if ((ext & 3) == 2) { + od = (int16_t)lduw_code(s->pc); + s->pc += 2; + } else + od = read_im32(s); + else + od = 0; + if (od != 0) + gen_op_add32(tmp, tmp, gen_im32(od)); + } + } else { + /* brief extension word format */ + tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0); + if ((ext & 0x800) == 0) { + add = gen_new_qreg(QMODE_I32); + gen_op_ext16s32(add, tmp); + tmp = add; + } + scale = (ext >> 9) & 3; + if (scale == 0) { + add = tmp; + } else { + if ((ext & 0x800) == 0) + add = tmp; + else + add = gen_new_qreg(QMODE_I32); + gen_op_shl32(add, tmp, gen_im32(scale)); + } + tmp = gen_new_qreg(QMODE_I32); + if (base != -1) { + gen_op_add32(tmp, base, gen_im32((int8_t)ext)); + gen_op_add32(tmp, tmp, add); + } else { + gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext)); + } } return tmp; } -/* Read a 32-bit immediate constant. */ -static inline uint32_t read_im32(DisasContext *s) -{ - uint32_t im; - im = ((uint32_t)lduw_code(s->pc)) << 16; - s->pc += 2; - im |= lduw_code(s->pc); - s->pc += 2; - return im; -} - - /* Update the CPU env CC_OP state. */ static inline void gen_flush_cc_op(DisasContext *s) { -- Andreas Schwab, SuSE Labs, [EMAIL PROTECTED] SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."