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)
