Revision defb0e31 targets390x/op_helper.c
b/targets390x/op_helper.c  

1  1 
/* 
2  2 
* S/390 helper routines 
3  3 
* 
4 
* Copyright (c) 2009 Ulrich Hecht 

4  5 
* Copyright (c) 2009 Alexander Graf 
5  6 
* 
6  7 
* This library is free software; you can redistribute it and/or 
...  ...  
18  19 
*/ 
19  20  
20  21 
#include "exec.h" 
22 
#include "hostutils.h" 

23 
#include "helpers.h" 

24 
#include <string.h> 

25 
#include "kvm.h" 

26 
#include "qemutimer.h" 

21  27  
22  28 
/*****************************************************************************/ 
23  29 
/* Softmmu support */ 
...  ...  
64  70 
cpu_restore_state(tb, env, pc); 
65  71 
} 
66  72 
} 
67 
/* XXX */ 

68 
/* helper_raise_exception_err(env>exception_index, env>error_code); */ 

73 
cpu_loop_exit(); 

69  74 
} 
70  75 
env = saved_env; 
71  76 
} 
72  77  
73  78 
#endif 
74  79  
80 
/* #define DEBUG_HELPER */ 

81 
#ifdef DEBUG_HELPER 

82 
#define HELPER_LOG(x...) qemu_log(x) 

83 
#else 

84 
#define HELPER_LOG(x...) 

85 
#endif 

86  
87 
/* raise an exception */ 

88 
void HELPER(exception)(uint32_t excp) 

89 
{ 

90 
HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp); 

91 
env>exception_index = excp; 

92 
cpu_loop_exit(); 

93 
} 

94  
95 
#ifndef CONFIG_USER_ONLY 

96 
static void mvc_fast_memset(CPUState *env, uint32_t l, uint64_t dest, 

97 
uint8_t byte) 

98 
{ 

99 
target_phys_addr_t dest_phys; 

100 
target_phys_addr_t len = l; 

101 
void *dest_p; 

102 
uint64_t asc = env>psw.mask & PSW_MASK_ASC; 

103 
int flags; 

104  
105 
if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { 

106 
stb(dest, byte); 

107 
cpu_abort(env, "should never reach here"); 

108 
} 

109 
dest_phys = dest & ~TARGET_PAGE_MASK; 

110  
111 
dest_p = cpu_physical_memory_map(dest_phys, &len, 1); 

112  
113 
memset(dest_p, byte, len); 

114  
115 
cpu_physical_memory_unmap(dest_p, 1, len, len); 

116 
} 

117  
118 
static void mvc_fast_memmove(CPUState *env, uint32_t l, uint64_t dest, 

119 
uint64_t src) 

120 
{ 

121 
target_phys_addr_t dest_phys; 

122 
target_phys_addr_t src_phys; 

123 
target_phys_addr_t len = l; 

124 
void *dest_p; 

125 
void *src_p; 

126 
uint64_t asc = env>psw.mask & PSW_MASK_ASC; 

127 
int flags; 

128  
129 
if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { 

130 
stb(dest, 0); 

131 
cpu_abort(env, "should never reach here"); 

132 
} 

133 
dest_phys = dest & ~TARGET_PAGE_MASK; 

134  
135 
if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) { 

136 
ldub(src); 

137 
cpu_abort(env, "should never reach here"); 

138 
} 

139 
src_phys = src & ~TARGET_PAGE_MASK; 

140  
141 
dest_p = cpu_physical_memory_map(dest_phys, &len, 1); 

142 
src_p = cpu_physical_memory_map(src_phys, &len, 0); 

143  
144 
memmove(dest_p, src_p, len); 

145  
146 
cpu_physical_memory_unmap(dest_p, 1, len, len); 

147 
cpu_physical_memory_unmap(src_p, 0, len, len); 

148 
} 

149 
#endif 

150  
151 
/* and on array */ 

152 
uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) 

153 
{ 

154 
int i; 

155 
unsigned char x; 

156 
uint32_t cc = 0; 

157  
158 
HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", 

159 
__FUNCTION__, l, dest, src); 

160 
for (i = 0; i <= l; i++) { 

161 
x = ldub(dest + i) & ldub(src + i); 

162 
if (x) { 

163 
cc = 1; 

164 
} 

165 
stb(dest + i, x); 

166 
} 

167 
return cc; 

168 
} 

169  
170 
/* xor on array */ 

171 
uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) 

172 
{ 

173 
int i; 

174 
unsigned char x; 

175 
uint32_t cc = 0; 

176  
177 
HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", 

178 
__FUNCTION__, l, dest, src); 

179  
180 
#ifndef CONFIG_USER_ONLY 

181 
/* xor with itself is the same as memset(0) */ 

182 
if ((l > 32) && (src == dest) && 

183 
(src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) { 

184 
mvc_fast_memset(env, l + 1, dest, 0); 

185 
return 0; 

186 
} 

187 
#else 

188 
if (src == dest) { 

189 
memset(g2h(dest), 0, l + 1); 

190 
return 0; 

191 
} 

192 
#endif 

193  
194 
for (i = 0; i <= l; i++) { 

195 
x = ldub(dest + i) ^ ldub(src + i); 

196 
if (x) { 

197 
cc = 1; 

198 
} 

199 
stb(dest + i, x); 

200 
} 

201 
return cc; 

202 
} 

203  
204 
/* or on array */ 

205 
uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) 

206 
{ 

207 
int i; 

208 
unsigned char x; 

209 
uint32_t cc = 0; 

210  
211 
HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", 

212 
__FUNCTION__, l, dest, src); 

213 
for (i = 0; i <= l; i++) { 

214 
x = ldub(dest + i)  ldub(src + i); 

215 
if (x) { 

216 
cc = 1; 

217 
} 

218 
stb(dest + i, x); 

219 
} 

220 
return cc; 

221 
} 

222  
223 
/* memmove */ 

224 
void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) 

225 
{ 

226 
int i = 0; 

227 
int x = 0; 

228 
uint32_t l_64 = (l + 1) / 8; 

229  
230 
HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", 

231 
__FUNCTION__, l, dest, src); 

232  
233 
#ifndef CONFIG_USER_ONLY 

234 
if ((l > 32) && 

235 
(src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) && 

236 
(dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) { 

237 
if (dest == (src + 1)) { 

238 
mvc_fast_memset(env, l + 1, dest, ldub(src)); 

239 
return; 

240 
} else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) { 

241 
mvc_fast_memmove(env, l + 1, dest, src); 

242 
return; 

243 
} 

244 
} 

245 
#else 

246 
if (dest == (src + 1)) { 

247 
memset(g2h(dest), ldub(src), l + 1); 

248 
return; 

249 
} else { 

250 
memmove(g2h(dest), g2h(src), l + 1); 

251 
return; 

252 
} 

253 
#endif 

254  
255 
/* handle the parts that fit into 8byte loads/stores */ 

256 
if (dest != (src + 1)) { 

257 
for (i = 0; i < l_64; i++) { 

258 
stq(dest + x, ldq(src + x)); 

259 
x += 8; 

260 
} 

261 
} 

262  
263 
/* slow version crossing pages with byte accesses */ 

264 
for (i = x; i <= l; i++) { 

265 
stb(dest + i, ldub(src + i)); 

266 
} 

267 
} 

268  
269 
/* compare unsigned byte arrays */ 

270 
uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) 

271 
{ 

272 
int i; 

273 
unsigned char x,y; 

274 
uint32_t cc; 

275 
HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", 

276 
__FUNCTION__, l, s1, s2); 

277 
for (i = 0; i <= l; i++) { 

278 
x = ldub(s1 + i); 

279 
y = ldub(s2 + i); 

280 
HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); 

281 
if (x < y) { 

282 
cc = 1; 

283 
goto done; 

284 
} else if (x > y) { 

285 
cc = 2; 

286 
goto done; 

287 
} 

288 
} 

289 
cc = 0; 

290 
done: 

291 
HELPER_LOG("\n"); 

292 
return cc; 

293 
} 

294  
295 
/* compare logical under mask */ 

296 
uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) 

297 
{ 

298 
uint8_t r,d; 

299 
uint32_t cc; 

300 
HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1, 

301 
mask, addr); 

302 
cc = 0; 

303 
while (mask) { 

304 
if (mask & 8) { 

305 
d = ldub(addr); 

306 
r = (r1 & 0xff000000UL) >> 24; 

307 
HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, 

308 
addr); 

309 
if (r < d) { 

310 
cc = 1; 

311 
break; 

312 
} else if (r > d) { 

313 
cc = 2; 

314 
break; 

315 
} 

316 
addr++; 

317 
} 

318 
mask = (mask << 1) & 0xf; 

319 
r1 <<= 8; 

320 
} 

321 
HELPER_LOG("\n"); 

322 
return cc; 

323 
} 

324  
325 
/* store character under mask */ 

326 
void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) 

327 
{ 

328 
uint8_t r; 

329 
HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask, 

330 
addr); 

331 
while (mask) { 

332 
if (mask & 8) { 

333 
r = (r1 & 0xff000000UL) >> 24; 

334 
stb(addr, r); 

335 
HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr); 

336 
addr++; 

337 
} 

338 
mask = (mask << 1) & 0xf; 

339 
r1 <<= 8; 

340 
} 

341 
HELPER_LOG("\n"); 

342 
} 

343  
344 
/* 64/64 > 128 unsigned multiplication */ 

345 
void HELPER(mlg)(uint32_t r1, uint64_t v2) 

346 
{ 

347 
#if HOST_LONG_BITS == 64 && defined(__GNUC__) 

348 
/* assuming 64bit hosts have __uint128_t */ 

349 
__uint128_t res = (__uint128_t)env>regs[r1 + 1]; 

350 
res *= (__uint128_t)v2; 

351 
env>regs[r1] = (uint64_t)(res >> 64); 

352 
env>regs[r1 + 1] = (uint64_t)res; 

353 
#else 

354 
mulu64(&env>regs[r1 + 1], &env>regs[r1], env>regs[r1 + 1], v2); 

355 
#endif 

356 
} 

357  
358 
/* 128 > 64/64 unsigned division */ 

359 
void HELPER(dlg)(uint32_t r1, uint64_t v2) 

360 
{ 

361 
uint64_t divisor = v2; 

362  
363 
if (!env>regs[r1]) { 

364 
/* 64 > 64/64 case */ 

365 
env>regs[r1] = env>regs[r1+1] % divisor; 

366 
env>regs[r1+1] = env>regs[r1+1] / divisor; 

367 
return; 

368 
} else { 

369  
370 
#if HOST_LONG_BITS == 64 && defined(__GNUC__) 

371 
/* assuming 64bit hosts have __uint128_t */ 

372 
__uint128_t dividend = (((__uint128_t)env>regs[r1]) << 64)  

373 
(env>regs[r1+1]); 

374 
__uint128_t quotient = dividend / divisor; 

375 
env>regs[r1+1] = quotient; 

376 
__uint128_t remainder = dividend % divisor; 

377 
env>regs[r1] = remainder; 

378 
#else 

379 
/* 32bit hosts would need special wrapper functionality  just abort if 

380 
we encounter such a case; it's very unlikely anyways. */ 

381 
cpu_abort(env, "128 > 64/64 division not implemented\n"); 

382 
#endif 

383 
} 

384 
} 

385  
386 
static inline uint64_t get_address(int x2, int b2, int d2) 

387 
{ 

388 
uint64_t r = d2; 

389  
390 
if (x2) { 

391 
r += env>regs[x2]; 

392 
} 

393  
394 
if (b2) { 

395 
r += env>regs[b2]; 

396 
} 

397  
398 
/* 31Bit mode */ 

399 
if (!(env>psw.mask & PSW_MASK_64)) { 

400 
r &= 0x7fffffff; 

401 
} 

402  
403 
return r; 

404 
} 

405  
406 
static inline uint64_t get_address_31fix(int reg) 

407 
{ 

408 
uint64_t r = env>regs[reg]; 

409  
410 
/* 31Bit mode */ 

411 
if (!(env>psw.mask & PSW_MASK_64)) { 

412 
r &= 0x7fffffff; 

413 
} 

414  
415 
return r; 

416 
} 

417  
418 
/* search string (c is byte to search, r2 is string, r1 end of string) */ 

419 
uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) 

420 
{ 

421 
uint64_t i; 

422 
uint32_t cc = 2; 

423 
uint64_t str = get_address_31fix(r2); 

424 
uint64_t end = get_address_31fix(r1); 

425  
426 
HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__, 

427 
c, env>regs[r1], env>regs[r2]); 

428  
429 
for (i = str; i != end; i++) { 

430 
if (ldub(i) == c) { 

431 
env>regs[r1] = i; 

432 
cc = 1; 

433 
break; 

434 
} 

435 
} 

436  
437 
return cc; 

438 
} 

439  
440 
/* unsigned string compare (c is string terminator) */ 

441 
uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) 

442 
{ 

443 
uint64_t s1 = get_address_31fix(r1); 

444 
uint64_t s2 = get_address_31fix(r2); 

445 
uint8_t v1, v2; 

446 
uint32_t cc; 

447 
c = c & 0xff; 

448 
#ifdef CONFIG_USER_ONLY 

449 
if (!c) { 

450 
HELPER_LOG("%s: comparing '%s' and '%s'\n", 

451 
__FUNCTION__, (char*)g2h(s1), (char*)g2h(s2)); 

452 
} 

453 
#endif 

454 
for (;;) { 

455 
v1 = ldub(s1); 

456 
v2 = ldub(s2); 

457 
if ((v1 == c  v2 == c)  (v1 != v2)) { 

458 
break; 

459 
} 

460 
s1++; 

461 
s2++; 

462 
} 

463  
464 
if (v1 == v2) { 

465 
cc = 0; 

466 
} else { 

467 
cc = (v1 < v2) ? 1 : 2; 

468 
/* FIXME: 31bit mode! */ 

469 
env>regs[r1] = s1; 

470 
env>regs[r2] = s2; 

471 
} 

472 
return cc; 

473 
} 

474  
475 
/* move page */ 

476 
void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2) 

477 
{ 

478 
/* XXX missing r0 handling */ 

479 
#ifdef CONFIG_USER_ONLY 

480 
int i; 

481  
482 
for (i = 0; i < TARGET_PAGE_SIZE; i++) { 

483 
stb(r1 + i, ldub(r2 + i)); 

484 
} 

485 
#else 

486 
mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2); 

487 
#endif 

488 
} 

489  
490 
/* string copy (c is string terminator) */ 

491 
void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) 

492 
{ 

493 
uint64_t dest = get_address_31fix(r1); 

494 
uint64_t src = get_address_31fix(r2); 

495 
uint8_t v; 

496 
c = c & 0xff; 

497 
#ifdef CONFIG_USER_ONLY 

498 
if (!c) { 

499 
HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src), 

500 
dest); 

501 
} 

502 
#endif 

503 
for (;;) { 

504 
v = ldub(src); 

505 
stb(dest, v); 

506 
if (v == c) { 

507 
break; 

508 
} 

509 
src++; 

510 
dest++; 

511 
} 

512 
env>regs[r1] = dest; /* FIXME: 31bit mode! */ 

513 
} 

514  
515 
/* compare and swap 64bit */ 

516 
uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) 

517 
{ 

518 
/* FIXME: locking? */ 

519 
uint32_t cc; 

520 
uint64_t v2 = ldq(a2); 

521 
if (env>regs[r1] == v2) { 

522 
cc = 0; 

523 
stq(a2, env>regs[r3]); 

524 
} else { 

525 
cc = 1; 

526 
env>regs[r1] = v2; 

527 
} 

528 
return cc; 

529 
} 

530  
531 
/* compare double and swap 64bit */ 

532 
uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) 

533 
{ 

534 
/* FIXME: locking? */ 

535 
uint32_t cc; 

536 
uint64_t v2_hi = ldq(a2); 

537 
uint64_t v2_lo = ldq(a2 + 8); 

538 
uint64_t v1_hi = env>regs[r1]; 

539 
uint64_t v1_lo = env>regs[r1 + 1]; 

540  
541 
if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) { 

542 
cc = 0; 

543 
stq(a2, env>regs[r3]); 

544 
stq(a2 + 8, env>regs[r3 + 1]); 

545 
} else { 

546 
cc = 1; 

547 
env>regs[r1] = v2_hi; 

548 
env>regs[r1 + 1] = v2_lo; 

549 
} 

550  
551 
return cc; 

552 
} 

553  
554 
/* compare and swap 32bit */ 

555 
uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) 

556 
{ 

557 
/* FIXME: locking? */ 

558 
uint32_t cc; 

559 
HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3); 

560 
uint32_t v2 = ldl(a2); 

561 
if (((uint32_t)env>regs[r1]) == v2) { 

562 
cc = 0; 

563 
stl(a2, (uint32_t)env>regs[r3]); 

564 
} else { 

565 
cc = 1; 

566 
env>regs[r1] = (env>regs[r1] & 0xffffffff00000000ULL)  v2; 

567 
} 

568 
return cc; 

569 
} 

570  
571 
static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) 

572 
{ 

573 
int pos = 24; /* top of the lower half of r1 */ 

574 
uint64_t rmask = 0xff000000ULL; 

575 
uint8_t val = 0; 

576 
int ccd = 0; 

577 
uint32_t cc = 0; 

578  
579 
while (mask) { 

580 
if (mask & 8) { 

581 
env>regs[r1] &= ~rmask; 

582 
val = ldub(address); 

583 
if ((val & 0x80) && !ccd) { 

584 
cc = 1; 

585 
} 

586 
ccd = 1; 

587 
if (val && cc == 0) { 

588 
cc = 2; 

589 
} 

590 
env>regs[r1] = (uint64_t)val << pos; 

591 
address++; 

592 
} 

593 
mask = (mask << 1) & 0xf; 

594 
pos = 8; 

595 
rmask >>= 8; 

596 
} 

597  
598 
return cc; 

599 
} 

600  
601 
/* execute instruction 

602 
this instruction executes an insn modified with the contents of r1 

603 
it does not change the executed instruction in memory 

604 
it does not change the program counter 

605 
in other words: tricky... 

606 
currently implemented by interpreting the cases it is most commonly used in 

607 
*/ 

608 
uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) 

609 
{ 

610 
uint16_t insn = lduw_code(addr); 

611 
HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr, 

612 
insn); 

613 
if ((insn & 0xf0ff) == 0xd000) { 

614 
uint32_t l, insn2, b1, b2, d1, d2; 

615 
l = v1 & 0xff; 

616 
insn2 = ldl_code(addr + 2); 

617 
b1 = (insn2 >> 28) & 0xf; 

618 
b2 = (insn2 >> 12) & 0xf; 

619 
d1 = (insn2 >> 16) & 0xfff; 

620 
d2 = insn2 & 0xfff; 

621 
switch (insn & 0xf00) { 

622 
case 0x200: 

623 
helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2)); 

624 
break; 

625 
case 0x500: 

626 
cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2)); 

627 
break; 

628 
case 0x700: 

629 
cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2)); 

630 
break; 

631 
default: 

632 
goto abort; 

633 
break; 

634 
} 

635 
} else if ((insn & 0xff00) == 0x0a00) { 

636 
/* supervisor call */ 

637 
HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insnv1) & 0xff); 

638 
env>psw.addr = ret  4; 

639 
env>int_svc_code = (insnv1) & 0xff; 

640 
env>int_svc_ilc = 4; 

641 
helper_exception(EXCP_SVC); 

642 
} else if ((insn & 0xff00) == 0xbf00) { 

643 
uint32_t insn2, r1, r3, b2, d2; 

644 
insn2 = ldl_code(addr + 2); 

645 
r1 = (insn2 >> 20) & 0xf; 

646 
r3 = (insn2 >> 16) & 0xf; 

647 
b2 = (insn2 >> 12) & 0xf; 

648 
d2 = insn2 & 0xfff; 

649 
cc = helper_icm(r1, get_address(0, b2, d2), r3); 

650 
} else { 

651 
abort: 

652 
cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", 

653 
insn); 

654 
} 

655 
return cc; 

656 
} 

657  
658 
/* absolute value 32bit */ 

659 
uint32_t HELPER(abs_i32)(int32_t val) 

660 
{ 

661 
if (val < 0) { 

662 
return val; 

663 
} else { 

664 
return val; 

665 
} 

666 
} 

667  
668 
/* negative absolute value 32bit */ 

669 
int32_t HELPER(nabs_i32)(int32_t val) 

670 
{ 

671 
if (val < 0) { 

672 
return val; 

673 
} else { 

674 
return val; 

675 
} 

676 
} 

677  
678 
/* absolute value 64bit */ 

679 
uint64_t HELPER(abs_i64)(int64_t val) 

680 
{ 

681 
HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val); 

682  
683 
if (val < 0) { 

684 
return val; 

685 
} else { 

686 
return val; 

687 
} 

688 
} 

689  
690 
/* negative absolute value 64bit */ 

691 
int64_t HELPER(nabs_i64)(int64_t val) 

692 
{ 

693 
if (val < 0) { 

694 
return val; 

695 
} else { 

696 
return val; 

697 
} 

698 
} 

699  
700 
/* add with carry 32bit unsigned */ 

701 
uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2) 

702 
{ 

703 
uint32_t res; 

704  
705 
res = v1 + v2; 

706 
if (cc & 2) { 

707 
res++; 

708 
} 

709  
710 
return res; 

711 
} 

712  
713 
/* store character under mask high operates on the upper half of r1 */ 

714 
void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) 

715 
{ 

716 
int pos = 56; /* top of the upper half of r1 */ 

717  
718 
while (mask) { 

719 
if (mask & 8) { 

720 
stb(address, (env>regs[r1] >> pos) & 0xff); 

721 
address++; 

722 
} 

723 
mask = (mask << 1) & 0xf; 

724 
pos = 8; 

725 
} 

726 
} 

727  
728 
/* insert character under mask high; same as icm, but operates on the 

729 
upper half of r1 */ 

730 
uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) 

731 
{ 

732 
int pos = 56; /* top of the upper half of r1 */ 

733 
uint64_t rmask = 0xff00000000000000ULL; 

734 
uint8_t val = 0; 

735 
int ccd = 0; 

736 
uint32_t cc = 0; 

737  
738 
while (mask) { 

739 
if (mask & 8) { 

740 
env>regs[r1] &= ~rmask; 

741 
val = ldub(address); 

742 
if ((val & 0x80) && !ccd) { 

743 
cc = 1; 

744 
} 

745 
ccd = 1; 

746 
if (val && cc == 0) { 

747 
cc = 2; 

748 
} 

749 
env>regs[r1] = (uint64_t)val << pos; 

750 
address++; 

751 
} 

752 
mask = (mask << 1) & 0xf; 

753 
pos = 8; 

754 
rmask >>= 8; 

755 
} 

756  
757 
return cc; 

758 
} 

759  
760 
/* insert psw mask and condition code into r1 */ 

761 
void HELPER(ipm)(uint32_t cc, uint32_t r1) 

762 
{ 

763 
uint64_t r = env>regs[r1]; 

764  
765 
r &= 0xffffffff00ffffffULL; 

766 
r = (cc << 28)  ( (env>psw.mask >> 40) & 0xf ); 

767 
env>regs[r1] = r; 

768 
HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__, 

769 
cc, env>psw.mask, r); 

770 
} 

771  
772 
/* load access registers r1 to r3 from memory at a2 */ 

773 
void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) 

774 
{ 

775 
int i; 

776  
777 
for (i = r1;; i = (i + 1) % 16) { 

778 
env>aregs[i] = ldl(a2); 

779 
a2 += 4; 

780  
781 
if (i == r3) { 

782 
break; 

783 
} 

784 
} 

785 
} 

786  
787 
/* store access registers r1 to r3 in memory at a2 */ 

788 
void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) 

789 
{ 

790 
int i; 

791  
792 
for (i = r1;; i = (i + 1) % 16) { 

793 
stl(a2, env>aregs[i]); 

794 
a2 += 4; 

795  
796 
if (i == r3) { 

797 
break; 

798 
} 

799 
} 

800 
} 

801  
802 
/* move long */ 

803 
uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) 

804 
{ 

805 
uint64_t destlen = env>regs[r1 + 1] & 0xffffff; 

806 
uint64_t dest = get_address_31fix(r1); 

807 
uint64_t srclen = env>regs[r2 + 1] & 0xffffff; 

808 
uint64_t src = get_address_31fix(r2); 

809 
uint8_t pad = src >> 24; 

810 
uint8_t v; 

811 
uint32_t cc; 

812  
813 
if (destlen == srclen) { 

814 
cc = 0; 

815 
} else if (destlen < srclen) { 

816 
cc = 1; 

817 
} else { 

818 
cc = 2; 

819 
} 

820  
821 
if (srclen > destlen) { 

822 
srclen = destlen; 

823 
} 

824  
825 
for (; destlen && srclen; src++, dest++, destlen, srclen) { 

826 
v = ldub(src); 

827 
stb(dest, v); 

828 
} 

829  
830 
for (; destlen; dest++, destlen) { 

831 
stb(dest, pad); 

832 
} 

833  
834 
env>regs[r1 + 1] = destlen; 

835 
/* can't use srclen here, we trunc'ed it */ 

836 
env>regs[r2 + 1] = src  env>regs[r2]; 

837 
env>regs[r1] = dest; 

838 
env>regs[r2] = src; 

839  
840 
return cc; 

841 
} 

842  
843 
/* move long extended another memcopy insn with more bells and whistles */ 

844 
uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) 

845 
{ 

846 
uint64_t destlen = env>regs[r1 + 1]; 

847 
uint64_t dest = env>regs[r1]; 

848 
uint64_t srclen = env>regs[r3 + 1]; 

849 
uint64_t src = env>regs[r3]; 

850 
uint8_t pad = a2 & 0xff; 

851 
uint8_t v; 

852 
uint32_t cc; 

853  
854 
if (!(env>psw.mask & PSW_MASK_64)) { 

855 
destlen = (uint32_t)destlen; 

856 
srclen = (uint32_t)srclen; 

857 
dest &= 0x7fffffff; 

858 
src &= 0x7fffffff; 

859 
} 

860  
861 
if (destlen == srclen) { 

862 
cc = 0; 

863 
} else if (destlen < srclen) { 

864 
cc = 1; 

865 
} else { 

866 
cc = 2; 

867 
} 

868  
869 
if (srclen > destlen) { 

870 
srclen = destlen; 

871 
} 

872  
873 
for (; destlen && srclen; src++, dest++, destlen, srclen) { 

874 
v = ldub(src); 

875 
stb(dest, v); 

876 
} 

877  
878 
for (; destlen; dest++, destlen) { 

879 
stb(dest, pad); 

880 
} 

881  
882 
env>regs[r1 + 1] = destlen; 

883 
/* can't use srclen here, we trunc'ed it */ 

884 
/* FIXME: 31bit mode! */ 

885 
env>regs[r3 + 1] = src  env>regs[r3]; 

886 
env>regs[r1] = dest; 

887 
env>regs[r3] = src; 

888  
889 
return cc; 

890 
} 

891  
892 
/* compare logical long extended memcompare insn with padding */ 

893 
uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) 

894 
{ 

895 
uint64_t destlen = env>regs[r1 + 1]; 

896 
uint64_t dest = get_address_31fix(r1); 

897 
uint64_t srclen = env>regs[r3 + 1]; 

898 
uint64_t src = get_address_31fix(r3); 

899 
uint8_t pad = a2 & 0xff; 

900 
uint8_t v1 = 0,v2 = 0; 

901 
uint32_t cc = 0; 

902  
903 
if (!(destlen  srclen)) { 

904 
return cc; 

905 
} 

906  
907 
if (srclen > destlen) { 

908 
srclen = destlen; 

909 
} 

910  
911 
for (; destlen  srclen; src++, dest++, destlen, srclen) { 

912 
v1 = srclen ? ldub(src) : pad; 

913 
v2 = destlen ? ldub(dest) : pad; 

914 
if (v1 != v2) { 

915 
cc = (v1 < v2) ? 1 : 2; 

916 
break; 

917 
} 

918 
} 

919  
920 
env>regs[r1 + 1] = destlen; 

921 
/* can't use srclen here, we trunc'ed it */ 

922 
env>regs[r3 + 1] = src  env>regs[r3]; 

923 
env>regs[r1] = dest; 

924 
env>regs[r3] = src; 

925  
926 
return cc; 

927 
} 

928  
929 
/* subtract unsigned v2 from v1 with borrow */ 

930 
uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2) 

931 
{ 

932 
uint32_t v1 = env>regs[r1]; 

933 
uint32_t res = v1 + (~v2) + (cc >> 1); 

934  
935 
env>regs[r1] = (env>regs[r1] & 0xffffffff00000000ULL)  res; 

936 
if (cc & 2) { 

937 
/* borrow */ 

938 
return v1 ? 1 : 0; 

939 
} else { 

940 
return v1 ? 3 : 2; 

941 
} 

942 
} 

943  
944 
/* subtract unsigned v2 from v1 with borrow */ 

945 
uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) 

946 
{ 

947 
uint64_t res = v1 + (~v2) + (cc >> 1); 

948  
949 
env>regs[r1] = res; 

950 
if (cc & 2) { 

951 
/* borrow */ 

952 
return v1 ? 1 : 0; 

953 
} else { 

954 
return v1 ? 3 : 2; 

955 
} 

956 
} 

957  
958 
static inline int float_comp_to_cc(int float_compare) 

959 
{ 

960 
switch (float_compare) { 

961 
case float_relation_equal: 

962 
return 0; 

963 
case float_relation_less: 

964 
return 1; 

965 
case float_relation_greater: 

966 
return 2; 

967 
case float_relation_unordered: 

968 
return 3; 

969 
default: 

970 
cpu_abort(env, "unknown return value for float compare\n"); 

971 
} 

972 
} 

973  
974 
/* condition codes for binary FP ops */ 

975 
static uint32_t set_cc_f32(float32 v1, float32 v2) 

976 
{ 

977 
return float_comp_to_cc(float32_compare_quiet(v1, v2, &env>fpu_status)); 

978 
} 

979  
980 
static uint32_t set_cc_f64(float64 v1, float64 v2) 

981 
{ 

982 
return float_comp_to_cc(float64_compare_quiet(v1, v2, &env>fpu_status)); 

983 
} 

984  
985 
/* condition codes for unary FP ops */ 

986 
static uint32_t set_cc_nz_f32(float32 v) 

987 
{ 

988 
if (float32_is_any_nan(v)) { 

989 
return 3; 

990 
} else if (float32_is_zero(v)) { 

991 
return 0; 

992 
} else if (float32_is_neg(v)) { 

993 
return 1; 

994 
} else { 

995 
return 2; 

996 
} 

997 
} 

998  
999 
static uint32_t set_cc_nz_f64(float64 v) 

1000 
{ 

1001 
if (float64_is_any_nan(v)) { 

1002 
return 3; 

1003 
} else if (float64_is_zero(v)) { 

1004 
return 0; 

1005 
} else if (float64_is_neg(v)) { 

1006 
return 1; 

1007 
} else { 

1008 
return 2; 

1009 
} 

1010 
} 

1011  
1012 
static uint32_t set_cc_nz_f128(float128 v) 

1013 
{ 

1014 
if (float128_is_any_nan(v)) { 

1015 
return 3; 

1016 
} else if (float128_is_zero(v)) { 

1017 
return 0; 

1018 
} else if (float128_is_neg(v)) { 

1019 
return 1; 

1020 
} else { 

1021 
return 2; 

1022 
} 

1023 
} 

1024  
1025 
/* convert 32bit int to 64bit float */ 

1026 
void HELPER(cdfbr)(uint32_t f1, int32_t v2) 

1027 
{ 

1028 
HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1); 

1029 
env>fregs[f1].d = int32_to_float64(v2, &env>fpu_status); 

1030 
} 

1031  
1032 
/* convert 32bit int to 128bit float */ 

1033 
void HELPER(cxfbr)(uint32_t f1, int32_t v2) 

1034 
{ 

1035 
CPU_QuadU v1; 

1036 
v1.q = int32_to_float128(v2, &env>fpu_status); 

1037 
env>fregs[f1].ll = v1.ll.upper; 

1038 
env>fregs[f1 + 2].ll = v1.ll.lower; 

1039 
} 

1040  
1041 
/* convert 64bit int to 32bit float */ 

1042 
void HELPER(cegbr)(uint32_t f1, int64_t v2) 

1043 
{ 

1044 
HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); 

1045 
env>fregs[f1].l.upper = int64_to_float32(v2, &env>fpu_status); 

1046 
} 

1047  
1048 
/* convert 64bit int to 64bit float */ 

1049 
void HELPER(cdgbr)(uint32_t f1, int64_t v2) 

1050 
{ 

1051 
HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); 

1052 
env>fregs[f1].d = int64_to_float64(v2, &env>fpu_status); 

1053 
} 

1054  
1055 
/* convert 64bit int to 128bit float */ 

1056 
void HELPER(cxgbr)(uint32_t f1, int64_t v2) 

1057 
{ 

1058 
CPU_QuadU x1; 

1059 
x1.q = int64_to_float128(v2, &env>fpu_status); 

1060 
HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2, 

1061 
x1.ll.upper, x1.ll.lower); 

1062 
env>fregs[f1].ll = x1.ll.upper; 

1063 
env>fregs[f1 + 2].ll = x1.ll.lower; 

1064 
} 

1065  
1066 
/* convert 32bit int to 32bit float */ 

1067 
void HELPER(cefbr)(uint32_t f1, int32_t v2) 

1068 
{ 

1069 
env>fregs[f1].l.upper = int32_to_float32(v2, &env>fpu_status); 

1070 
HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2, 

1071 
env>fregs[f1].l.upper, f1); 

1072 
} 

1073  
1074 
/* 32bit FP addition RR */ 

1075 
uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) 

1076 
{ 

1077 
env>fregs[f1].l.upper = float32_add(env>fregs[f1].l.upper, 

1078 
env>fregs[f2].l.upper, 

1079 
&env>fpu_status); 

1080 
HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, 

1081 
env>fregs[f2].l.upper, env>fregs[f1].l.upper, f1); 

1082  
1083 
return set_cc_nz_f32(env>fregs[f1].l.upper); 

1084 
} 

1085  
1086 
/* 64bit FP addition RR */ 

1087 
uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) 

1088 
{ 

1089 
env>fregs[f1].d = float64_add(env>fregs[f1].d, env>fregs[f2].d, 

1090 
&env>fpu_status); 

1091 
HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__, 

1092 
env>fregs[f2].d, env>fregs[f1].d, f1); 

1093  
1094 
return set_cc_nz_f64(env>fregs[f1].d); 

1095 
} 

1096  
1097 
/* 32bit FP subtraction RR */ 

1098 
uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) 

1099 
{ 

1100 
env>fregs[f1].l.upper = float32_sub(env>fregs[f1].l.upper, 

1101 
env>fregs[f2].l.upper, 

1102 
&env>fpu_status); 

1103 
HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, 

1104 
env>fregs[f2].l.upper, env>fregs[f1].l.upper, f1); 

1105  
1106 
return set_cc_nz_f32(env>fregs[f1].l.upper); 

1107 
} 

1108  
1109 
/* 64bit FP subtraction RR */ 

1110 
uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) 

1111 
{ 

1112 
env>fregs[f1].d = float64_sub(env>fregs[f1].d, env>fregs[f2].d, 

1113 
&env>fpu_status); 

1114 
HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", 

1115 
__FUNCTION__, env>fregs[f2].d, env>fregs[f1].d, f1); 

1116  
1117 
return set_cc_nz_f64(env>fregs[f1].d); 

1118 
} 

1119  
1120 
/* 32bit FP division RR */ 

1121 
void HELPER(debr)(uint32_t f1, uint32_t f2) 

1122 
{ 

1123 
env>fregs[f1].l.upper = float32_div(env>fregs[f1].l.upper, 

1124 
env>fregs[f2].l.upper, 

1125 
&env>fpu_status); 

1126 
} 

1127  
1128 
/* 128bit FP division RR */ 

1129 
void HELPER(dxbr)(uint32_t f1, uint32_t f2) 

1130 
{ 

1131 
CPU_QuadU v1; 

1132 
v1.ll.upper = env>fregs[f1].ll; 

1133 
v1.ll.lower = env>fregs[f1 + 2].ll; 

1134 
CPU_QuadU v2; 

1135 
v2.ll.upper = env>fregs[f2].ll; 

1136 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1137 
CPU_QuadU res; 

1138 
res.q = float128_div(v1.q, v2.q, &env>fpu_status); 

1139 
env>fregs[f1].ll = res.ll.upper; 

1140 
env>fregs[f1 + 2].ll = res.ll.lower; 

1141 
} 

1142  
1143 
/* 64bit FP multiplication RR */ 

1144 
void HELPER(mdbr)(uint32_t f1, uint32_t f2) 

1145 
{ 

1146 
env>fregs[f1].d = float64_mul(env>fregs[f1].d, env>fregs[f2].d, 

1147 
&env>fpu_status); 

1148 
} 

1149  
1150 
/* 128bit FP multiplication RR */ 

1151 
void HELPER(mxbr)(uint32_t f1, uint32_t f2) 

1152 
{ 

1153 
CPU_QuadU v1; 

1154 
v1.ll.upper = env>fregs[f1].ll; 

1155 
v1.ll.lower = env>fregs[f1 + 2].ll; 

1156 
CPU_QuadU v2; 

1157 
v2.ll.upper = env>fregs[f2].ll; 

1158 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1159 
CPU_QuadU res; 

1160 
res.q = float128_mul(v1.q, v2.q, &env>fpu_status); 

1161 
env>fregs[f1].ll = res.ll.upper; 

1162 
env>fregs[f1 + 2].ll = res.ll.lower; 

1163 
} 

1164  
1165 
/* convert 32bit float to 64bit float */ 

1166 
void HELPER(ldebr)(uint32_t r1, uint32_t r2) 

1167 
{ 

1168 
env>fregs[r1].d = float32_to_float64(env>fregs[r2].l.upper, 

1169 
&env>fpu_status); 

1170 
} 

1171  
1172 
/* convert 128bit float to 64bit float */ 

1173 
void HELPER(ldxbr)(uint32_t f1, uint32_t f2) 

1174 
{ 

1175 
CPU_QuadU x2; 

1176 
x2.ll.upper = env>fregs[f2].ll; 

1177 
x2.ll.lower = env>fregs[f2 + 2].ll; 

1178 
env>fregs[f1].d = float128_to_float64(x2.q, &env>fpu_status); 

1179 
HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env>fregs[f1].d); 

1180 
} 

1181  
1182 
/* convert 64bit float to 128bit float */ 

1183 
void HELPER(lxdbr)(uint32_t f1, uint32_t f2) 

1184 
{ 

1185 
CPU_QuadU res; 

1186 
res.q = float64_to_float128(env>fregs[f2].d, &env>fpu_status); 

1187 
env>fregs[f1].ll = res.ll.upper; 

1188 
env>fregs[f1 + 2].ll = res.ll.lower; 

1189 
} 

1190  
1191 
/* convert 64bit float to 32bit float */ 

1192 
void HELPER(ledbr)(uint32_t f1, uint32_t f2) 

1193 
{ 

1194 
float64 d2 = env>fregs[f2].d; 

1195 
env>fregs[f1].l.upper = float64_to_float32(d2, &env>fpu_status); 

1196 
} 

1197  
1198 
/* convert 128bit float to 32bit float */ 

1199 
void HELPER(lexbr)(uint32_t f1, uint32_t f2) 

1200 
{ 

1201 
CPU_QuadU x2; 

1202 
x2.ll.upper = env>fregs[f2].ll; 

1203 
x2.ll.lower = env>fregs[f2 + 2].ll; 

1204 
env>fregs[f1].l.upper = float128_to_float32(x2.q, &env>fpu_status); 

1205 
HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env>fregs[f1].l.upper); 

1206 
} 

1207  
1208 
/* absolute value of 32bit float */ 

1209 
uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) 

1210 
{ 

1211 
float32 v1; 

1212 
float32 v2 = env>fregs[f2].d; 

1213 
v1 = float32_abs(v2); 

1214 
env>fregs[f1].d = v1; 

1215 
return set_cc_nz_f32(v1); 

1216 
} 

1217  
1218 
/* absolute value of 64bit float */ 

1219 
uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) 

1220 
{ 

1221 
float64 v1; 

1222 
float64 v2 = env>fregs[f2].d; 

1223 
v1 = float64_abs(v2); 

1224 
env>fregs[f1].d = v1; 

1225 
return set_cc_nz_f64(v1); 

1226 
} 

1227  
1228 
/* absolute value of 128bit float */ 

1229 
uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) 

1230 
{ 

1231 
CPU_QuadU v1; 

1232 
CPU_QuadU v2; 

1233 
v2.ll.upper = env>fregs[f2].ll; 

1234 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1235 
v1.q = float128_abs(v2.q); 

1236 
env>fregs[f1].ll = v1.ll.upper; 

1237 
env>fregs[f1 + 2].ll = v1.ll.lower; 

1238 
return set_cc_nz_f128(v1.q); 

1239 
} 

1240  
1241 
/* load and test 64bit float */ 

1242 
uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2) 

1243 
{ 

1244 
env>fregs[f1].d = env>fregs[f2].d; 

1245 
return set_cc_nz_f64(env>fregs[f1].d); 

1246 
} 

1247  
1248 
/* load and test 32bit float */ 

1249 
uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) 

1250 
{ 

1251 
env>fregs[f1].l.upper = env>fregs[f2].l.upper; 

1252 
return set_cc_nz_f32(env>fregs[f1].l.upper); 

1253 
} 

1254  
1255 
/* load and test 128bit float */ 

1256 
uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) 

1257 
{ 

1258 
CPU_QuadU x; 

1259 
x.ll.upper = env>fregs[f2].ll; 

1260 
x.ll.lower = env>fregs[f2 + 2].ll; 

1261 
env>fregs[f1].ll = x.ll.upper; 

1262 
env>fregs[f1 + 2].ll = x.ll.lower; 

1263 
return set_cc_nz_f128(x.q); 

1264 
} 

1265  
1266 
/* load complement of 32bit float */ 

1267 
uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) 

1268 
{ 

1269 
env>fregs[f1].l.upper = float32_chs(env>fregs[f2].l.upper); 

1270  
1271 
return set_cc_nz_f32(env>fregs[f1].l.upper); 

1272 
} 

1273  
1274 
/* load complement of 64bit float */ 

1275 
uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) 

1276 
{ 

1277 
env>fregs[f1].d = float64_chs(env>fregs[f2].d); 

1278  
1279 
return set_cc_nz_f64(env>fregs[f1].d); 

1280 
} 

1281  
1282 
/* load complement of 128bit float */ 

1283 
uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) 

1284 
{ 

1285 
CPU_QuadU x1, x2; 

1286 
x2.ll.upper = env>fregs[f2].ll; 

1287 
x2.ll.lower = env>fregs[f2 + 2].ll; 

1288 
x1.q = float128_chs(x2.q); 

1289 
env>fregs[f1].ll = x1.ll.upper; 

1290 
env>fregs[f1 + 2].ll = x1.ll.lower; 

1291 
return set_cc_nz_f128(x1.q); 

1292 
} 

1293  
1294 
/* 32bit FP addition RM */ 

1295 
void HELPER(aeb)(uint32_t f1, uint32_t val) 

1296 
{ 

1297 
float32 v1 = env>fregs[f1].l.upper; 

1298 
CPU_FloatU v2; 

1299 
v2.l = val; 

1300 
HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__, 

1301 
v1, f1, v2.f); 

1302 
env>fregs[f1].l.upper = float32_add(v1, v2.f, &env>fpu_status); 

1303 
} 

1304  
1305 
/* 32bit FP division RM */ 

1306 
void HELPER(deb)(uint32_t f1, uint32_t val) 

1307 
{ 

1308 
float32 v1 = env>fregs[f1].l.upper; 

1309 
CPU_FloatU v2; 

1310 
v2.l = val; 

1311 
HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__, 

1312 
v1, f1, v2.f); 

1313 
env>fregs[f1].l.upper = float32_div(v1, v2.f, &env>fpu_status); 

1314 
} 

1315  
1316 
/* 32bit FP multiplication RM */ 

1317 
void HELPER(meeb)(uint32_t f1, uint32_t val) 

1318 
{ 

1319 
float32 v1 = env>fregs[f1].l.upper; 

1320 
CPU_FloatU v2; 

1321 
v2.l = val; 

1322 
HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__, 

1323 
v1, f1, v2.f); 

1324 
env>fregs[f1].l.upper = float32_mul(v1, v2.f, &env>fpu_status); 

1325 
} 

1326  
1327 
/* 32bit FP compare RR */ 

1328 
uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) 

1329 
{ 

1330 
float32 v1 = env>fregs[f1].l.upper; 

1331 
float32 v2 = env>fregs[f2].l.upper;; 

1332 
HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__, 

1333 
v1, f1, v2); 

1334 
return set_cc_f32(v1, v2); 

1335 
} 

1336  
1337 
/* 64bit FP compare RR */ 

1338 
uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) 

1339 
{ 

1340 
float64 v1 = env>fregs[f1].d; 

1341 
float64 v2 = env>fregs[f2].d;; 

1342 
HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__, 

1343 
v1, f1, v2); 

1344 
return set_cc_f64(v1, v2); 

1345 
} 

1346  
1347 
/* 128bit FP compare RR */ 

1348 
uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) 

1349 
{ 

1350 
CPU_QuadU v1; 

1351 
v1.ll.upper = env>fregs[f1].ll; 

1352 
v1.ll.lower = env>fregs[f1 + 2].ll; 

1353 
CPU_QuadU v2; 

1354 
v2.ll.upper = env>fregs[f2].ll; 

1355 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1356  
1357 
return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q, 

1358 
&env>fpu_status)); 

1359 
} 

1360  
1361 
/* 64bit FP compare RM */ 

1362 
uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) 

1363 
{ 

1364 
float64 v1 = env>fregs[f1].d; 

1365 
CPU_DoubleU v2; 

1366 
v2.ll = ldq(a2); 

1367 
HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1, 

1368 
f1, v2.d); 

1369 
return set_cc_f64(v1, v2.d); 

1370 
} 

1371  
1372 
/* 64bit FP addition RM */ 

1373 
uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) 

1374 
{ 

1375 
float64 v1 = env>fregs[f1].d; 

1376 
CPU_DoubleU v2; 

1377 
v2.ll = ldq(a2); 

1378 
HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__, 

1379 
v1, f1, v2.d); 

1380 
env>fregs[f1].d = v1 = float64_add(v1, v2.d, &env>fpu_status); 

1381 
return set_cc_nz_f64(v1); 

1382 
} 

1383  
1384 
/* 32bit FP subtraction RM */ 

1385 
void HELPER(seb)(uint32_t f1, uint32_t val) 

1386 
{ 

1387 
float32 v1 = env>fregs[f1].l.upper; 

1388 
CPU_FloatU v2; 

1389 
v2.l = val; 

1390 
env>fregs[f1].l.upper = float32_sub(v1, v2.f, &env>fpu_status); 

1391 
} 

1392  
1393 
/* 64bit FP subtraction RM */ 

1394 
uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) 

1395 
{ 

1396 
float64 v1 = env>fregs[f1].d; 

1397 
CPU_DoubleU v2; 

1398 
v2.ll = ldq(a2); 

1399 
env>fregs[f1].d = v1 = float64_sub(v1, v2.d, &env>fpu_status); 

1400 
return set_cc_nz_f64(v1); 

1401 
} 

1402  
1403 
/* 64bit FP multiplication RM */ 

1404 
void HELPER(mdb)(uint32_t f1, uint64_t a2) 

1405 
{ 

1406 
float64 v1 = env>fregs[f1].d; 

1407 
CPU_DoubleU v2; 

1408 
v2.ll = ldq(a2); 

1409 
HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__, 

1410 
v1, f1, v2.d); 

1411 
env>fregs[f1].d = float64_mul(v1, v2.d, &env>fpu_status); 

1412 
} 

1413  
1414 
/* 64bit FP division RM */ 

1415 
void HELPER(ddb)(uint32_t f1, uint64_t a2) 

1416 
{ 

1417 
float64 v1 = env>fregs[f1].d; 

1418 
CPU_DoubleU v2; 

1419 
v2.ll = ldq(a2); 

1420 
HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__, 

1421 
v1, f1, v2.d); 

1422 
env>fregs[f1].d = float64_div(v1, v2.d, &env>fpu_status); 

1423 
} 

1424  
1425 
static void set_round_mode(int m3) 

1426 
{ 

1427 
switch (m3) { 

1428 
case 0: 

1429 
/* current mode */ 

1430 
break; 

1431 
case 1: 

1432 
/* biased round no nearest */ 

1433 
case 4: 

1434 
/* round to nearest */ 

1435 
set_float_rounding_mode(float_round_nearest_even, &env>fpu_status); 

1436 
break; 

1437 
case 5: 

1438 
/* round to zero */ 

1439 
set_float_rounding_mode(float_round_to_zero, &env>fpu_status); 

1440 
break; 

1441 
case 6: 

1442 
/* round to +inf */ 

1443 
set_float_rounding_mode(float_round_up, &env>fpu_status); 

1444 
break; 

1445 
case 7: 

1446 
/* round to inf */ 

1447 
set_float_rounding_mode(float_round_down, &env>fpu_status); 

1448 
break; 

1449 
} 

1450 
} 

1451  
1452 
/* convert 32bit float to 64bit int */ 

1453 
uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1454 
{ 

1455 
float32 v2 = env>fregs[f2].l.upper; 

1456 
set_round_mode(m3); 

1457 
env>regs[r1] = float32_to_int64(v2, &env>fpu_status); 

1458 
return set_cc_nz_f32(v2); 

1459 
} 

1460  
1461 
/* convert 64bit float to 64bit int */ 

1462 
uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1463 
{ 

1464 
float64 v2 = env>fregs[f2].d; 

1465 
set_round_mode(m3); 

1466 
env>regs[r1] = float64_to_int64(v2, &env>fpu_status); 

1467 
return set_cc_nz_f64(v2); 

1468 
} 

1469  
1470 
/* convert 128bit float to 64bit int */ 

1471 
uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1472 
{ 

1473 
CPU_QuadU v2; 

1474 
v2.ll.upper = env>fregs[f2].ll; 

1475 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1476 
set_round_mode(m3); 

1477 
env>regs[r1] = float128_to_int64(v2.q, &env>fpu_status); 

1478 
if (float128_is_any_nan(v2.q)) { 

1479 
return 3; 

1480 
} else if (float128_is_zero(v2.q)) { 

1481 
return 0; 

1482 
} else if (float128_is_neg(v2.q)) { 

1483 
return 1; 

1484 
} else { 

1485 
return 2; 

1486 
} 

1487 
} 

1488  
1489 
/* convert 32bit float to 32bit int */ 

1490 
uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1491 
{ 

1492 
float32 v2 = env>fregs[f2].l.upper; 

1493 
set_round_mode(m3); 

1494 
env>regs[r1] = (env>regs[r1] & 0xffffffff00000000ULL)  

1495 
float32_to_int32(v2, &env>fpu_status); 

1496 
return set_cc_nz_f32(v2); 

1497 
} 

1498  
1499 
/* convert 64bit float to 32bit int */ 

1500 
uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1501 
{ 

1502 
float64 v2 = env>fregs[f2].d; 

1503 
set_round_mode(m3); 

1504 
env>regs[r1] = (env>regs[r1] & 0xffffffff00000000ULL)  

1505 
float64_to_int32(v2, &env>fpu_status); 

1506 
return set_cc_nz_f64(v2); 

1507 
} 

1508  
1509 
/* convert 128bit float to 32bit int */ 

1510 
uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) 

1511 
{ 

1512 
CPU_QuadU v2; 

1513 
v2.ll.upper = env>fregs[f2].ll; 

1514 
v2.ll.lower = env>fregs[f2 + 2].ll; 

1515 
env>regs[r1] = (env>regs[r1] & 0xffffffff00000000ULL)  

1516 
float128_to_int32(v2.q, &env>fpu_status); 

1517 
return set_cc_nz_f128(v2.q); 

1518 
} 

1519  
1520 
/* load 32bit FP zero */ 

1521 
void HELPER(lzer)(uint32_t f1) 

1522 
{ 

1523 
env>fregs[f1].l.upper = float32_zero; 

1524 
} 

1525  
1526 
/* load 64bit FP zero */ 

1527 
void HELPER(lzdr)(uint32_t f1) 

1528 
{ 

1529 
env>fregs[f1].d = float64_zero; 

1530 
} 
Also available in: Unified diff