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,7 +160,8 @@ enum m68k_features {
160 M68K_FEATURE_CF_FPU, 160 M68K_FEATURE_CF_FPU,
161 M68K_FEATURE_CF_MAC, 161 M68K_FEATURE_CF_MAC,
162 M68K_FEATURE_CF_EMAC, 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 static inline int m68k_feature(CPUM68KState *env, int feature) 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,6 +42,7 @@ static inline void qemu_assert(int cond, const char *msg)
42 42
43 /* internal defines */ 43 /* internal defines */
44 typedef struct DisasContext { 44 typedef struct DisasContext {
  45 + CPUM68KState *env;
45 target_ulong pc; 46 target_ulong pc;
46 int is_jmp; 47 int is_jmp;
47 int cc_op; 48 int cc_op;
@@ -198,50 +199,139 @@ static int gen_ldst(DisasContext *s, int opsize, int addr, int val) @@ -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 /* Handle a base + index + displacement effective addresss. A base of 232 /* Handle a base + index + displacement effective addresss. A base of
202 -1 means pc-relative. */ 233 -1 means pc-relative. */
203 static int gen_lea_indexed(DisasContext *s, int opsize, int base) 234 static int gen_lea_indexed(DisasContext *s, int opsize, int base)
204 { 235 {
205 - int scale;  
206 uint32_t offset; 236 uint32_t offset;
207 uint16_t ext; 237 uint16_t ext;
208 int add; 238 int add;
209 int tmp; 239 int tmp;
  240 + uint32_t bd, od;
210 241
211 offset = s->pc; 242 offset = s->pc;
212 ext = lduw_code(s->pc); 243 ext = lduw_code(s->pc);
213 s->pc += 2; 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 } else { 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 /* Update the CPU env CC_OP state. */ 335 /* Update the CPU env CC_OP state. */
246 static inline void gen_flush_cc_op(DisasContext *s) 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,6 +2811,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2721 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 2811 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2722 gen_opparam_ptr = gen_opparam_buf; 2812 gen_opparam_ptr = gen_opparam_buf;
2723 2813
  2814 + dc->env = env;
2724 dc->is_jmp = DISAS_NEXT; 2815 dc->is_jmp = DISAS_NEXT;
2725 dc->pc = pc_start; 2816 dc->pc = pc_start;
2726 dc->cc_op = CC_OP_DYNAMIC; 2817 dc->cc_op = CC_OP_DYNAMIC;