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