Commit e6dbd3b3f08318196cbdb1f0c23a7eefd9b38cb7

Authored by pbrook
1 parent 5aca8c3b

M68k extended addressing modes.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2870 c046a42c-6fe2-441c-8c8c-71466251a162
target-m68k/cpu.h
... ... @@ -160,7 +160,8 @@ enum m68k_features {
160 160 M68K_FEATURE_CF_FPU,
161 161 M68K_FEATURE_CF_MAC,
162 162 M68K_FEATURE_CF_EMAC,
163   - M68K_FEATURE_EXT_FULL /* 68020+ full extension word. */
  163 + M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */
  164 + M68K_FEATURE_WORD_INDEX /* word sized address index registers. */
164 165 };
165 166  
166 167 static inline int m68k_feature(CPUM68KState *env, int feature)
... ...
target-m68k/translate.c
... ... @@ -42,6 +42,7 @@ static inline void qemu_assert(int cond, const char *msg)
42 42  
43 43 /* internal defines */
44 44 typedef struct DisasContext {
  45 + CPUM68KState *env;
45 46 target_ulong pc;
46 47 int is_jmp;
47 48 int cc_op;
... ... @@ -198,50 +199,139 @@ static int gen_ldst(DisasContext *s, int opsize, int addr, int val)
198 199 }
199 200 }
200 201  
  202 +/* Read a 32-bit immediate constant. */
  203 +static inline uint32_t read_im32(DisasContext *s)
  204 +{
  205 + uint32_t im;
  206 + im = ((uint32_t)lduw_code(s->pc)) << 16;
  207 + s->pc += 2;
  208 + im |= lduw_code(s->pc);
  209 + s->pc += 2;
  210 + return im;
  211 +}
  212 +
  213 +/* Calculate and address index. */
  214 +static int gen_addr_index(uint16_t ext, int tmp)
  215 +{
  216 + int add;
  217 + int scale;
  218 +
  219 + add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
  220 + if ((ext & 0x800) == 0) {
  221 + gen_op_ext16s32(tmp, add);
  222 + add = tmp;
  223 + }
  224 + scale = (ext >> 9) & 3;
  225 + if (scale != 0) {
  226 + gen_op_shl32(tmp, add, gen_im32(scale));
  227 + add = tmp;
  228 + }
  229 + return add;
  230 +}
  231 +
201 232 /* Handle a base + index + displacement effective addresss. A base of
202 233 -1 means pc-relative. */
203 234 static int gen_lea_indexed(DisasContext *s, int opsize, int base)
204 235 {
205   - int scale;
206 236 uint32_t offset;
207 237 uint16_t ext;
208 238 int add;
209 239 int tmp;
  240 + uint32_t bd, od;
210 241  
211 242 offset = s->pc;
212 243 ext = lduw_code(s->pc);
213 244 s->pc += 2;
214   - tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
215   - /* ??? Check W/L bit. */
216   - scale = (ext >> 9) & 3;
217   - if (scale == 0) {
218   - add = tmp;
219   - } else {
220   - add = gen_new_qreg(QMODE_I32);
221   - gen_op_shl32(add, tmp, gen_im32(scale));
222   - }
223   - tmp = gen_new_qreg(QMODE_I32);
224   - if (base != -1) {
225   - gen_op_add32(tmp, base, gen_im32((int8_t)ext));
226   - gen_op_add32(tmp, tmp, add);
  245 +
  246 + if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
  247 + return -1;
  248 +
  249 + if (ext & 0x100) {
  250 + /* full extension word format */
  251 + if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
  252 + return -1;
  253 +
  254 + if ((ext & 0x30) > 0x10) {
  255 + /* base displacement */
  256 + if ((ext & 0x30) == 0x20) {
  257 + bd = (int16_t)lduw_code(s->pc);
  258 + s->pc += 2;
  259 + } else {
  260 + bd = read_im32(s);
  261 + }
  262 + } else {
  263 + bd = 0;
  264 + }
  265 + tmp = gen_new_qreg(QMODE_I32);
  266 + if ((ext & 0x44) == 0) {
  267 + /* pre-index */
  268 + add = gen_addr_index(ext, tmp);
  269 + } else {
  270 + add = QREG_NULL;
  271 + }
  272 + if ((ext & 0x80) == 0) {
  273 + /* base not suppressed */
  274 + if (base == -1) {
  275 + base = gen_im32(offset + bd);
  276 + bd = 0;
  277 + }
  278 + if (add) {
  279 + gen_op_add32(tmp, add, base);
  280 + add = tmp;
  281 + } else {
  282 + add = base;
  283 + }
  284 + }
  285 + if (add) {
  286 + if (bd != 0) {
  287 + gen_op_add32(tmp, add, gen_im32(bd));
  288 + add = tmp;
  289 + }
  290 + } else {
  291 + add = gen_im32(bd);
  292 + }
  293 + if ((ext & 3) != 0) {
  294 + /* memory indirect */
  295 + base = gen_load(s, OS_LONG, add, 0);
  296 + if ((ext & 0x44) == 4) {
  297 + add = gen_addr_index(ext, tmp);
  298 + gen_op_add32(tmp, add, base);
  299 + add = tmp;
  300 + } else {
  301 + add = base;
  302 + }
  303 + if ((ext & 3) > 1) {
  304 + /* outer displacement */
  305 + if ((ext & 3) == 2) {
  306 + od = (int16_t)lduw_code(s->pc);
  307 + s->pc += 2;
  308 + } else {
  309 + od = read_im32(s);
  310 + }
  311 + } else {
  312 + od = 0;
  313 + }
  314 + if (od != 0) {
  315 + gen_op_add32(add, tmp, gen_im32(od));
  316 + add = tmp;
  317 + }
  318 + }
227 319 } else {
228   - gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
  320 + /* brief extension word format */
  321 + tmp = gen_new_qreg(QMODE_I32);
  322 + add = gen_addr_index(ext, tmp);
  323 + if (base != -1) {
  324 + gen_op_add32(tmp, add, base);
  325 + if ((int8_t)ext)
  326 + gen_op_add32(tmp, tmp, gen_im32((int8_t)ext));
  327 + } else {
  328 + gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
  329 + }
  330 + add = tmp;
229 331 }
230   - return tmp;
231   -}
232   -
233   -/* Read a 32-bit immediate constant. */
234   -static inline uint32_t read_im32(DisasContext *s)
235   -{
236   - uint32_t im;
237   - im = ((uint32_t)lduw_code(s->pc)) << 16;
238   - s->pc += 2;
239   - im |= lduw_code(s->pc);
240   - s->pc += 2;
241   - return im;
  332 + return add;
242 333 }
243 334  
244   -
245 335 /* Update the CPU env CC_OP state. */
246 336 static inline void gen_flush_cc_op(DisasContext *s)
247 337 {
... ... @@ -2721,6 +2811,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2721 2811 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2722 2812 gen_opparam_ptr = gen_opparam_buf;
2723 2813  
  2814 + dc->env = env;
2724 2815 dc->is_jmp = DISAS_NEXT;
2725 2816 dc->pc = pc_start;
2726 2817 dc->cc_op = CC_OP_DYNAMIC;
... ...