target-m68k: introduce read_imXX() functions

Read a 8, 16 or 32bit immediat constant.

An immediate constant is stored in the instruction opcode and
can be in one or two extension words.

Backports commit 28b68cd79ef01e8b1f5bd26718cd8c09a12c625f from qemu
This commit is contained in:
Laurent Vivier 2018-02-27 08:32:02 -05:00 committed by Lioncash
parent d29cbb70b3
commit 2653165c63
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -237,13 +237,27 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
} }
} }
/* Read a 16-bit immediate constant */
static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
{
uint16_t im;
im = cpu_lduw_code(env, s->pc);
s->pc += 2;
return im;
}
/* Read an 8-bit immediate constant */
static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
{
return read_im16(env, s);
}
/* Read a 32-bit immediate constant. */ /* Read a 32-bit immediate constant. */
static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s) static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
{ {
uint32_t im; uint32_t im;
im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16; im = read_im16(env, s) << 16;
s->pc += 2; im |= 0xffff & read_im16(env, s);
im |= cpu_lduw_code(env, s->pc);
s->pc += 2; s->pc += 2;
return im; return im;
} }
@ -280,8 +294,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
uint32_t bd, od; uint32_t bd, od;
offset = s->pc; offset = s->pc;
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
return tcg_ctx->NULL_QREG; return tcg_ctx->NULL_QREG;
@ -299,8 +312,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
if ((ext & 0x30) > 0x10) { if ((ext & 0x30) > 0x10) {
/* base displacement */ /* base displacement */
if ((ext & 0x30) == 0x20) { if ((ext & 0x30) == 0x20) {
bd = (int16_t)cpu_lduw_code(env, s->pc); bd = (int16_t)read_im16(env, s);
s->pc += 2;
} else { } else {
bd = read_im32(env, s); bd = read_im32(env, s);
} }
@ -348,8 +360,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
if ((ext & 3) > 1) { if ((ext & 3) > 1) {
/* outer displacement */ /* outer displacement */
if ((ext & 3) == 2) { if ((ext & 3) == 2) {
od = (int16_t)cpu_lduw_code(env, s->pc); od = (int16_t)read_im16(env, s);
s->pc += 2;
} else { } else {
od = read_im32(env, s); od = read_im32(env, s);
} }
@ -511,8 +522,7 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
case 5: /* Indirect displacement. */ case 5: /* Indirect displacement. */
reg = AREG(insn, 0); reg = AREG(insn, 0);
tmp = tcg_temp_new(tcg_ctx); tmp = tcg_temp_new(tcg_ctx);
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
tcg_gen_addi_i32(tcg_ctx, tmp, reg, (int16_t)ext); tcg_gen_addi_i32(tcg_ctx, tmp, reg, (int16_t)ext);
return tmp; return tmp;
case 6: /* Indirect index + displacement. */ case 6: /* Indirect index + displacement. */
@ -521,16 +531,14 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
case 7: /* Other */ case 7: /* Other */
switch (insn & 7) { switch (insn & 7) {
case 0: /* Absolute short. */ case 0: /* Absolute short. */
offset = cpu_ldsw_code(env, s->pc); offset = (int16_t)read_im16(env, s);
s->pc += 2;
return tcg_const_i32(tcg_ctx, offset); return tcg_const_i32(tcg_ctx, offset);
case 1: /* Absolute long. */ case 1: /* Absolute long. */
offset = read_im32(env, s); offset = read_im32(env, s);
return tcg_const_i32(tcg_ctx, offset); return tcg_const_i32(tcg_ctx, offset);
case 2: /* pc displacement */ case 2: /* pc displacement */
offset = s->pc; offset = s->pc;
offset += cpu_ldsw_code(env, s->pc); offset += (int16_t)read_im16(env, s);
s->pc += 2;
return tcg_const_i32(tcg_ctx, offset); return tcg_const_i32(tcg_ctx, offset);
case 3: /* pc index+displacement. */ case 3: /* pc index+displacement. */
return gen_lea_indexed(env, s, tcg_ctx->NULL_QREG); return gen_lea_indexed(env, s, tcg_ctx->NULL_QREG);
@ -639,19 +647,17 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
switch (opsize) { switch (opsize) {
case OS_BYTE: case OS_BYTE:
if (what == EA_LOADS) { if (what == EA_LOADS) {
offset = cpu_ldsb_code(env, s->pc + 1); offset = (int8_t)read_im8(env, s);
} else { } else {
offset = cpu_ldub_code(env, s->pc + 1); offset = read_im8(env, s);
} }
s->pc += 2;
break; break;
case OS_WORD: case OS_WORD:
if (what == EA_LOADS) { if (what == EA_LOADS) {
offset = cpu_ldsw_code(env, s->pc); offset = (int16_t)read_im16(env, s);
} else { } else {
offset = cpu_lduw_code(env, s->pc); offset = read_im16(env, s);
} }
s->pc += 2;
break; break;
case OS_LONG: case OS_LONG:
offset = read_im32(env, s); offset = read_im32(env, s);
@ -955,8 +961,7 @@ DISAS_INSN(divl)
TCGv reg; TCGv reg;
uint16_t ext; uint16_t ext;
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if (ext & 0x87f8) { if (ext & 0x87f8) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
return; return;
@ -1113,8 +1118,7 @@ DISAS_INSN(movem)
TCGv tmp; TCGv tmp;
int is_load; int is_load;
mask = cpu_lduw_code(env, s->pc); mask = read_im16(env, s);
s->pc += 2;
tmp = gen_lea(env, s, insn, OS_LONG); tmp = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) { if (IS_NULL_QREG(tmp)) {
gen_addr_fault(s); gen_addr_fault(s);
@ -1158,8 +1162,7 @@ DISAS_INSN(bitop_im)
opsize = OS_LONG; opsize = OS_LONG;
op = (insn >> 6) & 3; op = (insn >> 6) & 3;
bitnum = cpu_lduw_code(env, s->pc); bitnum = read_im16(env, s);
s->pc += 2;
if (bitnum & 0xff00) { if (bitnum & 0xff00) {
disas_undef(env, s, insn); disas_undef(env, s, insn);
return; return;
@ -1423,8 +1426,7 @@ static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
else if ((insn & 0x3f) == 0x3c) else if ((insn & 0x3f) == 0x3c)
{ {
uint16_t val; uint16_t val;
val = cpu_lduw_code(env, s->pc); val = read_im16(env, s);
s->pc += 2;
gen_set_sr_im(s, val, ccr_only); gen_set_sr_im(s, val, ccr_only);
} }
else else
@ -1554,8 +1556,7 @@ DISAS_INSN(mull)
/* The upper 32 bits of the product are discarded, so /* The upper 32 bits of the product are discarded, so
muls.l and mulu.l are functionally equivalent. */ muls.l and mulu.l are functionally equivalent. */
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if (ext & 0x87ff) { if (ext & 0x87ff) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
return; return;
@ -1702,8 +1703,7 @@ DISAS_INSN(branch)
op = (insn >> 8) & 0xf; op = (insn >> 8) & 0xf;
offset = (int8_t)insn; offset = (int8_t)insn;
if (offset == 0) { if (offset == 0) {
offset = cpu_ldsw_code(env, s->pc); offset = (int16_t)read_im16(env, s);
s->pc += 2;
} else if (offset == -1) { } else if (offset == -1) {
offset = read_im32(env, s); offset = read_im32(env, s);
} }
@ -2003,14 +2003,12 @@ DISAS_INSN(strldsr)
uint32_t addr; uint32_t addr;
addr = s->pc - 2; addr = s->pc - 2;
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if (ext != 0x46FC) { if (ext != 0x46FC) {
gen_exception(s, addr, EXCP_UNSUPPORTED); gen_exception(s, addr, EXCP_UNSUPPORTED);
return; return;
} }
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if (IS_USER(s) || (ext & SR_S) == 0) { if (IS_USER(s) || (ext & SR_S) == 0) {
gen_exception(s, addr, EXCP_PRIVILEGE); gen_exception(s, addr, EXCP_PRIVILEGE);
return; return;
@ -2085,8 +2083,7 @@ DISAS_INSN(stop)
return; return;
} }
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
gen_set_sr_im(s, ext, 0); gen_set_sr_im(s, ext, 0);
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_halted, 1); tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_halted, 1);
@ -2113,8 +2110,7 @@ DISAS_INSN(movec)
return; return;
} }
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
if (ext & 0x8000) { if (ext & 0x8000) {
reg = AREG(ext, 12); reg = AREG(ext, 12);
@ -2181,8 +2177,7 @@ DISAS_INSN(fpu)
int set_dest; int set_dest;
int opsize; int opsize;
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
opmode = ext & 0x7f; opmode = ext & 0x7f;
switch ((ext >> 13) & 7) { switch ((ext >> 13) & 7) {
case 0: case 2: case 0: case 2:
@ -2465,8 +2460,7 @@ DISAS_INSN(fbcc)
offset = cpu_ldsw_code(env, s->pc); offset = cpu_ldsw_code(env, s->pc);
s->pc += 2; s->pc += 2;
if (insn & (1 << 6)) { if (insn & (1 << 6)) {
offset = (offset << 16) | cpu_lduw_code(env, s->pc); offset = (offset << 16) | read_im16(env, s);
s->pc += 2;
} }
l1 = gen_new_label(tcg_ctx); l1 = gen_new_label(tcg_ctx);
@ -2594,8 +2588,7 @@ DISAS_INSN(mac)
s->done_mac = 1; s->done_mac = 1;
} }
ext = cpu_lduw_code(env, s->pc); ext = read_im16(env, s);
s->pc += 2;
acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
dual = ((insn & 0x30) != 0 && (ext & 3) != 0); dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
@ -3091,8 +3084,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
check_exit_request(tcg_ctx); check_exit_request(tcg_ctx);
} }
insn = cpu_lduw_code(env, s->pc); insn = read_im16(env, s);
s->pc += 2;
((disas_proc)tcg_ctx->opcode_table[insn])(env, s, insn); ((disas_proc)tcg_ctx->opcode_table[insn])(env, s, insn);
} }