Revision 1ac5889f
b/target-s390x/cpu.h | ||
---|---|---|
60 | 60 |
} ExtQueue; |
61 | 61 |
|
62 | 62 |
typedef struct CPUS390XState { |
63 |
uint64_t regs[16]; /* GP registers */ |
|
63 |
uint64_t regs[16]; /* GP registers */ |
|
64 |
CPU_DoubleU fregs[16]; /* FP registers */ |
|
65 |
uint32_t aregs[16]; /* access registers */ |
|
64 | 66 |
|
65 |
uint32_t aregs[16]; /* access registers */ |
|
67 |
uint32_t fpc; /* floating-point control register */ |
|
68 |
uint32_t cc_op; |
|
66 | 69 |
|
67 |
uint32_t fpc; /* floating-point control register */ |
|
68 |
CPU_DoubleU fregs[16]; /* FP registers */ |
|
69 | 70 |
float_status fpu_status; /* passed to softfloat lib */ |
70 | 71 |
|
72 |
/* The low part of a 128-bit return, or remainder of a divide. */ |
|
73 |
uint64_t retxl; |
|
74 |
|
|
71 | 75 |
PSW psw; |
72 | 76 |
|
73 |
uint32_t cc_op; |
|
74 | 77 |
uint64_t cc_src; |
75 | 78 |
uint64_t cc_dst; |
76 | 79 |
uint64_t cc_vr; |
... | ... | |
86 | 89 |
|
87 | 90 |
uint64_t cregs[16]; /* control registers */ |
88 | 91 |
|
89 |
int pending_int; |
|
90 | 92 |
ExtQueue ext_queue[MAX_EXT_QUEUE]; |
93 |
int pending_int; |
|
91 | 94 |
|
92 | 95 |
int ext_index; |
93 | 96 |
|
b/target-s390x/helper.h | ||
---|---|---|
9 | 9 |
DEF_HELPER_3(mvcl, i32, env, i32, i32) |
10 | 10 |
DEF_HELPER_4(clm, i32, env, i32, i32, i64) |
11 | 11 |
DEF_HELPER_4(stcm, void, env, i32, i32, i64) |
12 |
DEF_HELPER_3(mlg, void, env, i32, i64)
|
|
12 |
DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
|
13 | 13 |
DEF_HELPER_3(dlg, void, env, i32, i64) |
14 | 14 |
DEF_HELPER_4(srst, i32, env, i32, i32, i32) |
15 | 15 |
DEF_HELPER_4(clst, i32, env, i32, i32, i32) |
b/target-s390x/insn-data.def | ||
---|---|---|
54 | 54 |
/* MULTIPLY LOGICAL */ |
55 | 55 |
C(0xb996, MLR, RRE, Z, r1p1_32u, r2_32u, new, r1_D32, mul, 0) |
56 | 56 |
C(0xe396, ML, RXY_a, Z, r1p1_32u, m2_32u, new, r1_D32, mul, 0) |
57 |
C(0xb986, MLGR, RRE, Z, r1p1, r2_o, r1_P, 0, mul128, 0) |
|
58 |
C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0) |
|
57 | 59 |
/* MULTIPLY SINGLE */ |
58 | 60 |
C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0) |
59 | 61 |
C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0) |
b/target-s390x/int_helper.c | ||
---|---|---|
30 | 30 |
#endif |
31 | 31 |
|
32 | 32 |
/* 64/64 -> 128 unsigned multiplication */ |
33 |
void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
|
|
33 |
uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
|
|
34 | 34 |
{ |
35 |
#if HOST_LONG_BITS == 64 && defined(__GNUC__) |
|
36 |
/* assuming 64-bit hosts have __uint128_t */ |
|
37 |
__uint128_t res = (__uint128_t)env->regs[r1 + 1]; |
|
38 |
|
|
39 |
res *= (__uint128_t)v2; |
|
40 |
env->regs[r1] = (uint64_t)(res >> 64); |
|
41 |
env->regs[r1 + 1] = (uint64_t)res; |
|
42 |
#else |
|
43 |
mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2); |
|
44 |
#endif |
|
35 |
uint64_t reth; |
|
36 |
mulu64(&env->retxl, &reth, v1, v2); |
|
37 |
return reth; |
|
45 | 38 |
} |
46 | 39 |
|
47 | 40 |
/* 128 -> 64/64 unsigned division */ |
b/target-s390x/translate.c | ||
---|---|---|
293 | 293 |
#endif |
294 | 294 |
} |
295 | 295 |
|
296 |
static inline void return_low128(TCGv_i64 dest) |
|
297 |
{ |
|
298 |
tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl)); |
|
299 |
} |
|
300 |
|
|
296 | 301 |
static inline void update_psw_addr(DisasContext *s) |
297 | 302 |
{ |
298 | 303 |
/* psw.addr */ |
... | ... | |
1563 | 1568 |
set_cc_nz_u64(s, regs[r1]); |
1564 | 1569 |
tcg_temp_free_i64(tmp3); |
1565 | 1570 |
break; |
1566 |
case 0x86: /* MLG R1,D2(X2,B2) [RXY] */ |
|
1567 |
tmp2 = tcg_temp_new_i64(); |
|
1568 |
tmp32_1 = tcg_const_i32(r1); |
|
1569 |
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s)); |
|
1570 |
gen_helper_mlg(cpu_env, tmp32_1, tmp2); |
|
1571 |
tcg_temp_free_i64(tmp2); |
|
1572 |
tcg_temp_free_i32(tmp32_1); |
|
1573 |
break; |
|
1574 | 1571 |
case 0x87: /* DLG R1,D2(X2,B2) [RXY] */ |
1575 | 1572 |
tmp2 = tcg_temp_new_i64(); |
1576 | 1573 |
tmp32_1 = tcg_const_i32(r1); |
... | ... | |
4732 | 4729 |
return NO_EXIT; |
4733 | 4730 |
} |
4734 | 4731 |
|
4732 |
static ExitStatus op_mul128(DisasContext *s, DisasOps *o) |
|
4733 |
{ |
|
4734 |
gen_helper_mul128(o->out, cpu_env, o->in1, o->in2); |
|
4735 |
return_low128(o->out2); |
|
4736 |
return NO_EXIT; |
|
4737 |
} |
|
4738 |
|
|
4735 | 4739 |
static ExitStatus op_sub(DisasContext *s, DisasOps *o) |
4736 | 4740 |
{ |
4737 | 4741 |
tcg_gen_sub_i64(o->out, o->in1, o->in2); |
... | ... | |
4800 | 4804 |
o->g_out = true; |
4801 | 4805 |
} |
4802 | 4806 |
|
4807 |
static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o) |
|
4808 |
{ |
|
4809 |
/* ??? Specification exception: r1 must be even. */ |
|
4810 |
int r1 = get_field(f, r1); |
|
4811 |
o->out = regs[r1]; |
|
4812 |
o->out2 = regs[(r1 + 1) & 15]; |
|
4813 |
o->g_out = o->g_out2 = true; |
|
4814 |
} |
|
4815 |
|
|
4803 | 4816 |
/* ====================================================================== */ |
4804 | 4817 |
/* The "Write OUTput" generators. These generally perform some non-trivial |
4805 | 4818 |
copy of data to TCG globals, or to main memory. The trivial cases are |
... | ... | |
4844 | 4857 |
o->g_in1 = true; |
4845 | 4858 |
} |
4846 | 4859 |
|
4860 |
static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o) |
|
4861 |
{ |
|
4862 |
/* ??? Specification exception: r1 must be even. */ |
|
4863 |
int r1 = get_field(f, r1); |
|
4864 |
o->in1 = load_reg((r1 + 1) & 15); |
|
4865 |
} |
|
4866 |
|
|
4847 | 4867 |
static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o) |
4848 | 4868 |
{ |
4849 | 4869 |
/* ??? Specification exception: r1 must be even. */ |
Also available in: Unified diff