From 391fb6865f80f84c40cf46494b4f844fea19cee3 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 3 Oct 2019 18:03:09 +0000 Subject: user/orc: bump to 0.4.30, migrate to meson --- user/orc/APKBUILD | 32 +- user/orc/ppc-fixes.patch | 990 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1003 insertions(+), 19 deletions(-) create mode 100644 user/orc/ppc-fixes.patch diff --git a/user/orc/APKBUILD b/user/orc/APKBUILD index de40d3f31..fc760912f 100644 --- a/user/orc/APKBUILD +++ b/user/orc/APKBUILD @@ -2,37 +2,30 @@ # Contributor: Natanael Copa # Maintainer: A. Wilcox pkgname=orc -pkgver=0.4.29 +pkgver=0.4.30 pkgrel=0 pkgdesc="The Oil Run-time Compiler" url="https://gstreamer.freedesktop.org/modules/orc.html" arch="all" license="BSD-2-Clause AND BSD-3-Clause" -makedepends="linux-headers" -subpackages="$pkgname-dev $pkgname-doc $pkgname-compiler" -source="https://gstreamer.freedesktop.org/src/orc/${pkgname}-${pkgver}.tar.xz" +makedepends="linux-headers meson ninja" +subpackages="$pkgname-dev $pkgname-compiler" +source="https://gstreamer.freedesktop.org/src/orc/${pkgname}-${pkgver}.tar.xz + ppc-fixes.patch + " build() { - cd "$builddir" - ./configure \ - --build=$CBUILD \ - --host=$CHOST \ - --prefix=/usr \ - --sysconfdir=/etc \ - --mandir=/usr/share/man \ - --infodir=/usr/share/info \ - --localstatedir=/var - make + meson -Dprefix=/usr \ + build + ninja -C build } check() { - cd "$builddir" - make check + ninja -C build test } package() { - cd "$builddir" - make DESTDIR="$pkgdir" install + DESTDIR="$pkgdir" ninja -C build install } dev() { @@ -47,4 +40,5 @@ compiler() { mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ } -sha512sums="57aa75bbefa9ba9ffcce97affd504c13c57612e2409863c011555bed6ff6ba224d38ed66b715bf103679a8ee28ddae427db3d78c7b4a2ddfa7dbd72a4fa81726 orc-0.4.29.tar.xz" +sha512sums="da254347f5ebb278f0932a7bfa878adc2a14c42c7e6a20a4e6bb68c0883e307fef57bef867d54e150bd1d875f79eee27f9d34aede410d3eddd4093e5b055cd22 orc-0.4.30.tar.xz +b049e4ab9e2ee71013cc1f387dfc24df97c25fcf72dd3fd0502d891ee5e1e305dd710a639839ac64f6a58383b18d49ccffd32645dc64255b15945920acaf56d6 ppc-fixes.patch" diff --git a/user/orc/ppc-fixes.patch b/user/orc/ppc-fixes.patch new file mode 100644 index 000000000..ab4aecd40 --- /dev/null +++ b/user/orc/ppc-fixes.patch @@ -0,0 +1,990 @@ +diff --git a/orc-test/orctest.c b/orc-test/orctest.c +index 614421b..d9cb9d5 100644 +--- a/orc-test/orctest.c ++++ b/orc-test/orctest.c +@@ -523,14 +523,14 @@ float_compare (OrcArray *array1, OrcArray *array2, int i, int j) + if (isnan(*(float *)ptr1) && isnan(*(float *)ptr2)) return TRUE; + if (*(float *)ptr1 == *(float *)ptr2) return TRUE; + if ((*(float *)ptr1 < 0.0) == (*(float *)ptr2 < 0.0) && +- abs((orc_int32)(*(orc_uint32 *)ptr1 - *(orc_uint32 *)ptr2) <= 2)) ++ abs((orc_int32)(*(orc_uint32 *)ptr1 - *(orc_uint32 *)ptr2)) <= 2) + return TRUE; + return FALSE; + case 8: + if (isnan(*(double *)ptr1) && isnan(*(double *)ptr2)) return TRUE; + if (*(double *)ptr1 == *(double *)ptr2) return TRUE; + if ((*(double *)ptr1 < 0.0) == (*(double *)ptr2 < 0.0) && +- llabs((orc_int64)(*(orc_uint64 *)ptr1 - *(orc_uint64 *)ptr2) <= 2)) ++ llabs((orc_int64)(*(orc_uint64 *)ptr1 - *(orc_uint64 *)ptr2)) <= 2) + return TRUE; + return FALSE; + } +diff --git a/orc/orcpowerpc.c b/orc/orcpowerpc.c +index e054d07..ed98437 100644 +--- a/orc/orcpowerpc.c ++++ b/orc/orcpowerpc.c +@@ -208,7 +208,7 @@ powerpc_emit_srawi (OrcCompiler *compiler, int regd, int rega, int shift, + powerpc_get_regname(regd), + powerpc_get_regname(rega), shift); + +- insn = (31<<26) | (powerpc_regnum (regd)<<21) | (powerpc_regnum (rega)<<16); ++ insn = (31<<26) | (powerpc_regnum (rega)<<21) | (powerpc_regnum (regd)<<16); + insn |= (shift<<11) | (824<<1) | record; + + powerpc_emit (compiler, insn); +@@ -233,7 +233,7 @@ powerpc_emit_D (OrcCompiler *compiler, const char *name, + ORC_ASM_CODE(compiler," %s %s, %s, %d\n", name, + powerpc_get_regname(regd), + powerpc_get_regname(rega), imm); +- insn |= (powerpc_regnum (regd)<<21) | (powerpc_regnum (rega)<<16); ++ insn |= (powerpc_regnum (rega)<<21) | (powerpc_regnum (regd)<<16); + insn |= imm&0xffff; + + powerpc_emit (compiler, insn); +@@ -543,7 +543,7 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg) + { + unsigned int insn; + +- ORC_ASM_CODE(p," addi %s, %s, %db - %s\n", ++ ORC_ASM_CODE(p," addi %s, %s, %df - %s\n", + powerpc_get_regname(greg), + powerpc_get_regname(greg), p->constants[i].label, p->program->name); + insn = (14<<26) | (powerpc_regnum (greg)<<21) | (powerpc_regnum (greg)<<16); +@@ -740,3 +740,42 @@ void powerpc_emit_label (OrcCompiler *compiler, int label) + powerpc_add_label (compiler, compiler->codeptr, label); + } + ++void ++powerpc_load_align (OrcCompiler *compiler, int vector_reg, int offset_reg, int src_reg) ++{ ++ if (IS_POWERPC_BE (compiler)) { ++ ORC_ASM_CODE(compiler," lvsl %s, %s, %s\n", ++ powerpc_get_regname (vector_reg), ++ offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), ++ powerpc_get_regname (src_reg)); ++ powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(vector_reg), ++ offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); ++ } else { ++ ORC_ASM_CODE(compiler," lvsr %s, %s, %s\n", ++ powerpc_get_regname (vector_reg), ++ offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), ++ powerpc_get_regname (src_reg)); ++ powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(vector_reg), ++ offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); ++ } ++} ++ ++void ++powerpc_store_align (OrcCompiler *compiler, int vector_reg, int offset_reg, int src_reg) ++{ ++ if (IS_POWERPC_BE (compiler)) { ++ ORC_ASM_CODE(compiler," lvsr %s, %s, %s\n", ++ powerpc_get_regname (vector_reg), ++ offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), ++ powerpc_get_regname (src_reg)); ++ powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(vector_reg), ++ offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); ++ } else { ++ ORC_ASM_CODE(compiler," lvsl %s, %s, %s\n", ++ powerpc_get_regname (vector_reg), ++ offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), ++ powerpc_get_regname (src_reg)); ++ powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(vector_reg), ++ offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); ++ } ++} +diff --git a/orc/orcpowerpc.h b/orc/orcpowerpc.h +index e6b315a..ba824b2 100644 +--- a/orc/orcpowerpc.h ++++ b/orc/orcpowerpc.h +@@ -138,6 +138,9 @@ void powerpc_emit_full_constants (OrcCompiler* p); + void powerpc_emit_load_address (OrcCompiler* compiler, int regd, int rega, int imm); + void powerpc_load_constant (OrcCompiler* p, int i, int reg); + ++void powerpc_load_align (OrcCompiler *compiler, int vector_reg, int offset_reg, int src_reg); ++void powerpc_store_align (OrcCompiler *compiler, int vector_reg, int offset_reg, int src_reg); ++ + /* instructions */ + #define powerpc_emit_vand(p,a,b,c) powerpc_emit_VX_2 (p, "vand", 0x10000404, a, b, c) + #define powerpc_emit_vandc(p,a,b,c) powerpc_emit_VX_2 (p, "vandc", 0x10000444, a, b, c) +@@ -159,8 +162,10 @@ void powerpc_load_constant (OrcCompiler* p, int i, int reg); + + #define powerpc_emit_vmrghb(p,a,b,c) powerpc_emit_VX_2 (p, "vmrghb", 0x1000000c, a, b, c) + #define powerpc_emit_vmrghh(p,a,b,c) powerpc_emit_VX_2 (p, "vmrghh", 0x1000004c, a, b, c) ++#define powerpc_emit_vmrghw(p,a,b,c) powerpc_emit_VX_2 (p, "vmrghw", 0x1000008c, a, b, c) + #define powerpc_emit_vmrglb(p,a,b,c) powerpc_emit_VX_2 (p, "vmrglb", 0x1000010c, a, b, c) + #define powerpc_emit_vmrglh(p,a,b,c) powerpc_emit_VX_2 (p, "vmrglh", 0x1000014c, a, b, c) ++#define powerpc_emit_vmrglw(p,a,b,c) powerpc_emit_VX_2 (p, "vmrglw", 0x1000018c, a, b, c) + + #define powerpc_emit_vpkshss(p,a,b,c) powerpc_emit_VX_2 (p, "vpkshss", 0x1000018e, a, b, c) + #define powerpc_emit_vpkshus(p,a,b,c) powerpc_emit_VX_2 (p, "vpkshus", 0x1000010e, a, b, c) +diff --git a/orc/orcprogram-altivec.c b/orc/orcprogram-altivec.c +index 659115e..808b4e1 100644 +--- a/orc/orcprogram-altivec.c ++++ b/orc/orcprogram-altivec.c +@@ -18,6 +18,8 @@ static void orc_compiler_powerpc_init (OrcCompiler *compiler); + static unsigned int orc_compiler_powerpc_get_default_flags (void); + static void orc_compiler_powerpc_assemble (OrcCompiler *compiler); + static const char* powerpc_get_flag_name (int shift); ++static int orc_powerpc_assemble_copy_check (OrcCompiler *compiler); ++static void orc_powerpc_assemble_copy (OrcCompiler *compiler); + + + static void +@@ -199,8 +201,8 @@ powerpc_load_constants_outer (OrcCompiler *compiler) + } + } + +- orc_compiler_emit_invariants (compiler); +- ++ /* Load constants first, as they may be used by invariants */ ++ ORC_ASM_CODE(compiler,"# load constants\n"); + for(i=0;in_constants;i++) { + if (compiler->constants[i].is_long && + !compiler->constants[i].alloc_reg) { +@@ -212,6 +214,9 @@ powerpc_load_constants_outer (OrcCompiler *compiler) + } + } + } ++ ++ ORC_ASM_CODE(compiler,"# load invariants\n"); ++ orc_compiler_emit_invariants (compiler); + } + + static void +@@ -219,6 +224,7 @@ powerpc_load_inner_constants (OrcCompiler *compiler) + { + int i; + ++ ORC_ASM_CODE(compiler,"# load inner constants\n"); + for(i=0;ivars[i].name == NULL) continue; + switch (compiler->vars[i].vartype) { +@@ -305,6 +311,11 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) + int label_leave; + int set_vscr = FALSE; + ++ if (orc_powerpc_assemble_copy_check (compiler)) { ++ orc_powerpc_assemble_copy (compiler); ++ return; ++ } ++ + label_outer_loop_start = orc_compiler_label_new (compiler); + label_loop_start = orc_compiler_label_new (compiler); + label_leave = orc_compiler_label_new (compiler); +@@ -312,6 +323,8 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) + { + int i; + ++ /* Emit invariants also to check for constants */ ++ orc_compiler_emit_invariants (compiler); + orc_powerpc_emit_loop (compiler, 0); + + compiler->codeptr = compiler->code; +@@ -486,3 +499,199 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) + powerpc_do_fixups (compiler); + } + ++static ++int orc_powerpc_assemble_copy_check (OrcCompiler *compiler) ++{ ++ if (compiler->program->n_insns == 1 && ++ compiler->program->is_2d == FALSE && ++ (strcmp (compiler->program->insns[0].opcode->name, "copyb") == 0 || ++ strcmp (compiler->program->insns[0].opcode->name, "copyw") == 0 || ++ strcmp (compiler->program->insns[0].opcode->name, "copyl") == 0 || ++ strcmp (compiler->program->insns[0].opcode->name, "copyq") == 0) && ++ (compiler->program->insns[0].flags & ++ (ORC_INSTRUCTION_FLAG_X2 | ORC_INSTRUCTION_FLAG_X4)) == 0 && ++ compiler->program->n_param_vars == 0 && ++ compiler->program->n_const_vars == 0) { ++ /* TODO: add param & const support if this turns out to be faster */ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static ++void orc_powerpc_assemply_copy_loop (OrcCompiler *compiler, int size, ++ int shift, int next_label) ++{ ++ const int src = POWERPC_R5; ++ const int dst = POWERPC_R6; ++ const int count = POWERPC_R7; ++ const int tmp = POWERPC_R0; ++ const int vtmp = POWERPC_V0; ++ const int vperm = POWERPC_V1; ++ int label_copy; ++ ++ label_copy = orc_compiler_label_new (compiler); ++ ++ ORC_ASM_CODE(compiler," cmplwi %s, %d\n", ++ powerpc_get_regname(count), size); ++ powerpc_emit(compiler, 0x28000000|(powerpc_regnum(count)<<16)|(size&0xffff)); ++ ++ ORC_ASM_CODE(compiler," blt %d%c\n", next_label, ++ (compiler->labels[next_label]!=NULL) ? 'b' : 'f'); ++ powerpc_add_fixup (compiler, 0, compiler->codeptr, next_label); ++ powerpc_emit (compiler, 0x41800000); ++ ++ powerpc_emit_D(compiler, "andi.", 0x70000000, tmp, src, size-1); ++ ORC_ASM_CODE(compiler," bgt %d%c\n", next_label, ++ (compiler->labels[next_label]!=NULL) ? 'b' : 'f'); ++ powerpc_add_fixup (compiler, 0, compiler->codeptr, next_label); ++ powerpc_emit (compiler, 0x41810000); ++ ++ powerpc_emit_D(compiler, "andi.", 0x70000000, tmp, dst, size-1); ++ ORC_ASM_CODE(compiler," bgt %d%c\n", next_label, ++ (compiler->labels[next_label]!=NULL) ? 'b' : 'f'); ++ powerpc_add_fixup (compiler, 0, compiler->codeptr, next_label); ++ powerpc_emit (compiler, 0x41810000); ++ ++ powerpc_emit_srawi (compiler, tmp, count, shift, 0); ++ ++ ORC_ASM_CODE (compiler, " mtctr %s\n", powerpc_get_regname(tmp)); ++ powerpc_emit (compiler, 0x7c0903a6 | (powerpc_regnum (tmp)<<21)); ++ ++ powerpc_emit_label (compiler, label_copy); ++ if (size == 16) { ++ ORC_ASM_CODE(compiler," lvx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (src)); ++ powerpc_emit_X (compiler, 0x7c0000ce, powerpc_regnum(vtmp), ++ 0, powerpc_regnum(src)); ++ ORC_ASM_CODE(compiler," stvx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (dst)); ++ powerpc_emit_X (compiler, 0x7c0001ce, ++ powerpc_regnum(vtmp), ++ 0, powerpc_regnum(dst)); ++ } else { ++ switch (size) { ++ case 1: ++ ORC_ASM_CODE(compiler," lvebx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (src)); ++ powerpc_emit_X (compiler, 0x7c00000e, powerpc_regnum(vtmp), ++ 0, powerpc_regnum(src)); ++ break; ++ case 2: ++ ORC_ASM_CODE(compiler," lvehx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (src)); ++ powerpc_emit_X (compiler, 0x7c00004e, powerpc_regnum(vtmp), ++ 0, powerpc_regnum(src)); ++ break; ++ case 4: ++ ORC_ASM_CODE(compiler," lvewx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (src)); ++ powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(vtmp), ++ 0, powerpc_regnum(src)); ++ break; ++ } ++ powerpc_load_align (compiler, vperm, 0, src); ++ powerpc_emit_vperm (compiler, vtmp, vtmp, vtmp, vperm); ++ powerpc_store_align (compiler, vperm, 0, dst); ++ powerpc_emit_vperm (compiler, vtmp, vtmp, vtmp, vperm); ++ switch (size) { ++ case 1: ++ ORC_ASM_CODE(compiler," stvebx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (dst)); ++ powerpc_emit_X (compiler, 0x7c00010e, ++ powerpc_regnum(vtmp), ++ 0, powerpc_regnum(dst)); ++ break; ++ case 2: ++ ORC_ASM_CODE(compiler," stvehx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (dst)); ++ powerpc_emit_X (compiler, 0x7c00014e, ++ powerpc_regnum(vtmp), ++ 0, powerpc_regnum(dst)); ++ break; ++ case 4: ++ ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", ++ powerpc_get_regname (vtmp), ++ powerpc_get_regname (dst)); ++ powerpc_emit_X (compiler, 0x7c00018e, ++ powerpc_regnum(vtmp), ++ 0, powerpc_regnum(dst)); ++ break; ++ } ++ } ++ ++ powerpc_emit_addi (compiler, src, src, size); ++ powerpc_emit_addi (compiler, dst, dst, size); ++ powerpc_emit_addi (compiler, count, count, -size); ++ powerpc_emit_bne (compiler, label_copy); ++ ++ powerpc_emit_label (compiler, next_label); ++} ++ ++static ++void orc_powerpc_assemble_copy (OrcCompiler *compiler) ++{ ++ const int src = POWERPC_R5; ++ const int dst = POWERPC_R6; ++ const int count = POWERPC_V7; ++ OrcInstruction *insn; ++ int shift = 0; ++ int label_word; ++ int label_halfword; ++ int label_byte; ++ int label_done; ++ ++ insn = compiler->program->insns + 0; ++ ++ if (strcmp (insn->opcode->name, "copyw") == 0) { ++ shift = 1; ++ } else if (strcmp (insn->opcode->name, "copyl") == 0) { ++ shift = 2; ++ } else if (strcmp (insn->opcode->name, "copyq") == 0) { ++ shift = 3; ++ } ++ ++ label_word = orc_compiler_label_new (compiler); ++ label_halfword = orc_compiler_label_new (compiler); ++ label_byte = orc_compiler_label_new (compiler); ++ label_done = orc_compiler_label_new (compiler); ++ ++ powerpc_emit_prologue (compiler); ++ ++ powerpc_emit_load_address (compiler, ++ dst, ++ POWERPC_R3, ++ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[insn->dest_args[0]])); ++ powerpc_emit_load_address (compiler, ++ src, ++ POWERPC_R3, ++ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[insn->src_args[0]])); ++ powerpc_emit_lwz (compiler, count, POWERPC_R3, ++ (int)ORC_STRUCT_OFFSET(OrcExecutor, n)); ++ ++ powerpc_emit_addi (compiler, POWERPC_R0, 0, shift); ++ ORC_ASM_CODE(compiler, " slw %s, %s, %s\n", ++ powerpc_get_regname(count), ++ powerpc_get_regname(count), ++ powerpc_get_regname(POWERPC_R0)); ++ powerpc_emit (compiler, (31<<26) | ++ (powerpc_regnum (count)<<21) | ++ (powerpc_regnum (count)<<16) | ++ (powerpc_regnum (POWERPC_R0)<<11) | (24<<1)); ++ ++ orc_powerpc_assemply_copy_loop (compiler, 16, 4, label_word); ++ orc_powerpc_assemply_copy_loop (compiler, 4, 2, label_halfword); ++ orc_powerpc_assemply_copy_loop (compiler, 2, 1, label_byte); ++ orc_powerpc_assemply_copy_loop (compiler, 1, 0, label_done); ++ ++ powerpc_emit_epilogue (compiler); ++ powerpc_do_fixups (compiler); ++} +diff --git a/orc/orcrules-altivec.c b/orc/orcrules-altivec.c +index fa40ac3..7729b69 100644 +--- a/orc/orcrules-altivec.c ++++ b/orc/orcrules-altivec.c +@@ -15,26 +15,6 @@ + + /* rules */ + +-static void +-powerpc_load_align (OrcCompiler *compiler, int vector_reg, int offset_reg, int src_reg) +-{ +- if (IS_POWERPC_BE (compiler)) { +- ORC_ASM_CODE(compiler," lvsl %s, %s, %s\n", +- powerpc_get_regname (vector_reg), +- offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), +- powerpc_get_regname (src_reg)); +- powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(vector_reg), +- offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); +- } else { +- ORC_ASM_CODE(compiler," lvsr %s, %s, %s\n", +- powerpc_get_regname (vector_reg), +- offset_reg == 0 ? "0" : powerpc_get_regname (offset_reg), +- powerpc_get_regname (src_reg)); +- powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(vector_reg), +- offset_reg == 0 ? 0 : powerpc_regnum(offset_reg), powerpc_regnum(src_reg)); +- } +-} +- + static inline int + powerpc_select_value (OrcCompiler *compiler, int be_value, int le_value) + { +@@ -322,19 +302,7 @@ powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn) + int perm = orc_compiler_get_temp_reg (compiler); + int tmp = orc_compiler_get_temp_reg (compiler); + +- if (IS_POWERPC_BE (compiler)) { +- ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n", +- powerpc_get_regname (perm), +- powerpc_get_regname (dest->ptr_register)); +- powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(perm), +- 0, powerpc_regnum(dest->ptr_register)); +- } else { +- ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", +- powerpc_get_regname (perm), +- powerpc_get_regname (dest->ptr_register)); +- powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(perm), +- 0, powerpc_regnum(dest->ptr_register)); +- } ++ powerpc_store_align (compiler, perm, 0, dest->ptr_register); + powerpc_emit_vperm (compiler, tmp, src->alloc, src->alloc, perm); + + switch (size) { +@@ -370,8 +338,7 @@ powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn) + powerpc_regnum(tmp), + 0, powerpc_regnum(dest->ptr_register)); + +- powerpc_emit_D (compiler, "addi", 0x38000000, compiler->gp_tmpreg, +- 0, 4); ++ powerpc_emit_addi (compiler, compiler->gp_tmpreg, 0, 4); + + ORC_ASM_CODE(compiler," stvewx %s, %s, %s\n", + powerpc_get_regname (tmp), +@@ -397,6 +364,48 @@ powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn) + } + } + ++static void ++powerpc_denormalize_sp_full(OrcCompiler *p, int reg, int zero, int mask) ++{ ++ int tmp = p->tmpreg; ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, reg, mask); ++ powerpc_emit_VX_2(p, "vcmpequw", 0x10000086, tmp, tmp, zero); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, tmp, reg, zero, tmp); ++ powerpc_emit_VX_2(p, "xvcpsgnsp", 0xf0000687, reg, reg, tmp); ++} ++ ++static void ++powerpc_denormalize_sp_zero(OrcCompiler *p, int reg, int zero) ++{ ++ int mask = powerpc_get_constant_full (p, 0x7f800000, 0x7f800000, ++ 0x7f800000, 0x7f800000); ++ powerpc_denormalize_sp_full(p, reg, zero, mask); ++} ++ ++static void ++powerpc_denormalize_sp(OrcCompiler *p, int reg) ++{ ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_sp_zero(p, reg, zero); ++} ++ ++static void ++powerpc_denormalize_dp_full(OrcCompiler *p, int reg, int zero, int mask) ++{ ++ int tmp = p->tmpreg; ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, reg, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, zero); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, tmp, reg, zero, tmp); ++ powerpc_emit_VX_2(p, "xvcpsgndp", 0xf0000787, reg, reg, tmp); ++} ++ ++static void ++powerpc_denormalize_dp_zero(OrcCompiler *p, int reg, int zero) ++{ ++ int mask = powerpc_get_constant_full (p, 0x7ff00000, 0x00000000, ++ 0x7ff00000, 0x00000000); ++ powerpc_denormalize_dp_full(p, reg, zero, mask); ++} + + + #define RULE(name, opcode, code) \ +@@ -409,6 +418,33 @@ powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ + powerpc_emit_VX_2 (p, opcode, code , dest, src1, src2);\ + } + ++#define RULE_DP(name, opcode, code) \ ++static void \ ++powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ ++{ \ ++ int src1 = ORC_SRC_ARG (p, insn, 0); \ ++ int src2 = ORC_SRC_ARG (p, insn, 1); \ ++ int dest = ORC_DEST_ARG (p, insn, 0); \ ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); \ ++ powerpc_denormalize_dp_zero (p, src1, zero); \ ++ powerpc_denormalize_dp_zero (p, src2, zero); \ ++ powerpc_emit_VX_2 (p, opcode, code , dest, src1, src2); \ ++ powerpc_denormalize_dp_zero (p, dest, zero); \ ++} ++ ++#define RULE_DP_SRC(name, opcode, code) \ ++static void \ ++powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ ++{ \ ++ int src1 = ORC_SRC_ARG (p, insn, 0); \ ++ int src2 = ORC_SRC_ARG (p, insn, 1); \ ++ int dest = ORC_DEST_ARG (p, insn, 0); \ ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); \ ++ powerpc_denormalize_dp_zero (p, src1, zero); \ ++ powerpc_denormalize_dp_zero (p, src2, zero); \ ++ powerpc_emit_VX_2 (p, opcode, code , dest, src1, src2); \ ++} ++ + #define RULE_SHIFT(name, opcode, code) \ + static void \ + powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ +@@ -503,13 +539,11 @@ RULE(maxf, "vmaxfp", 0x1000040a) + RULE(minf, "vminfp", 0x1000044a) + RULE(cmpeqf, "vcmpeqfp", 0x100000c6) + +-RULE(addd, "xvadddp", 0xf0000307) +-RULE(subd, "xvsubdp", 0xf0000347) +-RULE(muld, "xvmuldp", 0xf0000387) +-RULE(divd, "xvdivdp", 0xf00003c7) +-RULE(mind, "xvmindp", 0xf0000747) +-RULE(maxd, "xvmaxdp", 0xf0000707) +-RULE(cmpeqd, "xvcmpeqdp", 0xf000031f) ++RULE_DP(addd, "xvadddp", 0xf0000307) ++RULE_DP(subd, "xvsubdp", 0xf0000347) ++RULE_DP(muld, "xvmuldp", 0xf0000387) ++RULE_DP(divd, "xvdivdp", 0xf00003c7) ++RULE_DP_SRC(cmpeqd, "xvcmpeqdp", 0xf000031f) + + RULE(addq, "vaddudm", 0x100000c0) + RULE(subq, "vsubudm", 0x100004c0) +@@ -541,13 +575,12 @@ powerpc_rule_mullb (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int perm = powerpc_get_constant_full(p, 0x11011303, 0x15051707, ++ 0x19091b0b, 0x1d0d1f0f); + +- if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmulesb (p, dest, src1, src2); +- powerpc_emit_vsldoi (p, dest, dest, dest, 1); +- } else { +- powerpc_emit_vmulosb (p, dest, src1, src2); +- } ++ powerpc_emit_vmulesb (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulosb (p, dest, src1, src2); ++ powerpc_emit_vperm(p, dest, dest, p->tmpreg, perm); + } + + static void +@@ -556,15 +589,12 @@ powerpc_rule_mulhsb (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int perm = powerpc_get_constant_full(p, 0x10001202, 0x14041606, ++ 0x18081a0a, 0x1c0c1e0e); + +- if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmulesb (p, dest, src1, src2); +- } else { +- int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 8); +- +- powerpc_emit_vmulosb (p, dest, src1, src2); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, src1, tmp); +- } ++ powerpc_emit_vmulesb (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulosb (p, dest, src1, src2); ++ powerpc_emit_vperm(p, dest, dest, p->tmpreg, perm); + } + + static void +@@ -573,15 +603,12 @@ powerpc_rule_mulhub (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int perm = powerpc_get_constant_full(p, 0x10001202, 0x14041606, ++ 0x18081a0a, 0x1c0c1e0e); + +- if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmuleub (p, dest, src1, src2); +- } else { +- int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 8); +- +- powerpc_emit_vmuloub (p, dest, src1, src2); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +- } ++ powerpc_emit_vmuleub (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmuloub (p, dest, src1, src2); ++ powerpc_emit_vperm(p, dest, dest, p->tmpreg, perm); + } + + static void +@@ -590,16 +617,12 @@ powerpc_rule_mulhsw (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int perm = powerpc_get_constant_full(p, 0x10110001, 0x14150405, ++ 0x18190809, 0x1c1d0c0d); + +- if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmulesh (p, dest, src1, src2); +- } else { +- int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 8); +- +- powerpc_emit_vmulosh (p, dest, src1, src2); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +- } ++ powerpc_emit_vmulesh (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulosh (p, dest, src1, src2); ++ powerpc_emit_vperm(p, dest, dest, p->tmpreg, perm); + } + + static void +@@ -608,16 +631,12 @@ powerpc_rule_mulhuw (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int perm = powerpc_get_constant_full(p, 0x10110001, 0x14150405, ++ 0x18190809, 0x1c1d0c0d); + +- if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmuleuh (p, dest, src1, src2); +- } else { +- int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 8); +- +- powerpc_emit_vmulouh (p, dest, src1, src2); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +- powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +- } ++ powerpc_emit_vmuleuh(p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulouh(p, dest, src1, src2); ++ powerpc_emit_vperm(p, dest, dest, p->tmpreg, perm); + } + + static void +@@ -765,10 +784,12 @@ powerpc_rule_mulsbw (OrcCompiler *p, void *user, OrcInstruction *insn) + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + ++ powerpc_emit_vmulesb (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulosb (p, dest, src1, src2); + if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmulesb (p, dest, src1, src2); ++ powerpc_emit_vmrghh (p, dest, p->tmpreg, dest); + } else { +- powerpc_emit_vmulosb (p, dest, src1, src2); ++ powerpc_emit_vmrglh (p, dest, p->tmpreg, dest); + } + } + +@@ -779,10 +800,12 @@ powerpc_rule_mulubw (OrcCompiler *p, void *user, OrcInstruction *insn) + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + ++ powerpc_emit_vmuleub (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmuloub (p, dest, src1, src2); + if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmuleub (p, dest, src1, src2); ++ powerpc_emit_vmrghh (p, dest, p->tmpreg, dest); + } else { +- powerpc_emit_vmuloub (p, dest, src1, src2); ++ powerpc_emit_vmrglh (p, dest, p->tmpreg, dest); + } + } + +@@ -793,10 +816,12 @@ powerpc_rule_mulswl (OrcCompiler *p, void *user, OrcInstruction *insn) + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + ++ powerpc_emit_vmulesh (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulosh (p, dest, src1, src2); + if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmulesh (p, dest, src1, src2); ++ powerpc_emit_vmrghw (p, dest, p->tmpreg, dest); + } else { +- powerpc_emit_vmulosh (p, dest, src1, src2); ++ powerpc_emit_vmrglw (p, dest, p->tmpreg, dest); + } + } + +@@ -807,10 +832,12 @@ powerpc_rule_muluwl (OrcCompiler *p, void *user, OrcInstruction *insn) + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + ++ powerpc_emit_vmuleuh (p, p->tmpreg, src1, src2); ++ powerpc_emit_vmulouh (p, dest, src1, src2); + if (IS_POWERPC_BE (p)) { +- powerpc_emit_vmuleuh (p, dest, src1, src2); ++ powerpc_emit_vmrghw (p, dest, p->tmpreg, dest); + } else { +- powerpc_emit_vmulouh (p, dest, src1, src2); ++ powerpc_emit_vmrglw (p, dest, p->tmpreg, dest); + } + } + +@@ -848,17 +875,13 @@ powerpc_rule_mulll (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int tmp = orc_compiler_get_temp_reg(p); ++ int perm = powerpc_get_constant_full(p, 0x14151617, 0x04050607, ++ 0x1c1d1e1f, 0x0c0d0e0f); + +- if (IS_POWERPC_BE (p)) { +- int perm; +- +- powerpc_emit_vmuleuw (p, dest, src1, src2); +- perm = powerpc_get_constant_full (p, 0x04050607, 0x04050607, +- 0x0c0d0e0f, 0x0c0d0e0f); +- powerpc_emit_vperm (p, dest, dest, dest, perm); +- } else { +- powerpc_emit_vmulouw (p, dest, src1, src2); +- } ++ powerpc_emit_vmulouw (p, tmp, src1, src2); ++ powerpc_emit_vmuleuw (p, dest, src1, src2); ++ powerpc_emit_vperm (p, dest, tmp, dest, perm); + } + + static void +@@ -1428,20 +1451,11 @@ powerpc_rule_divf (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); +- int y = orc_compiler_get_temp_reg (p); +- int t = orc_compiler_get_temp_reg (p); +- int c1; +- int c0; +- +- c1 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x3f800000); /* 1.0 */ +- +- powerpc_emit_VX_db (p, "vrefp", 0x1000010a, y, src2); +- +- powerpc_emit_VA_acb (p, "vnmsubfp", 0x1000002f, t, y, c1, src2); +- powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, y, y, y, t); +- +- c0 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x00000000); /* 0.0 */ +- powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, dest, y, c0, src1); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_sp_zero (p, src1, zero); ++ powerpc_denormalize_sp_zero (p, src2, zero); ++ powerpc_emit_VX_2(p, "xvdivsp", 0xf00002c7, dest, src1, src2); ++ powerpc_denormalize_sp_zero (p, dest, zero); + } + + static void +@@ -1521,8 +1535,10 @@ powerpc_rule_sqrtf(OrcCompiler* p, void* user, OrcInstruction* insn) + { + int src1 = ORC_SRC_ARG(p, insn, 0); + int dest = ORC_DEST_ARG(p, insn, 0); +- ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_sp_zero (p, src1, zero); + powerpc_emit_VX_db(p, "xvsqrtsp", 0xf000022f, dest, src1); ++ powerpc_denormalize_sp_zero (p, dest, zero); + } + + static void +@@ -1530,18 +1546,65 @@ powerpc_rule_sqrtd(OrcCompiler* p, void* user, OrcInstruction* insn) + { + int src1 = ORC_SRC_ARG(p, insn, 0); + int dest = ORC_DEST_ARG(p, insn, 0); +- ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_dp_zero (p, src1, zero); + powerpc_emit_VX_db(p, "xvsqrtdp", 0xf000032f, dest, src1); ++ powerpc_denormalize_dp_zero (p, dest, zero); + } + + static void +-powerpc_rule_cmpltd (OrcCompiler *p, void *user, OrcInstruction *insn) ++powerpc_rule_mind (OrcCompiler *p, void *user, OrcInstruction *insn) + { + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ int mask = powerpc_get_constant_full (p, 0x7ff80000, 0x00000000, ++ 0x7ff80000, 0x00000000); ++ int tmp2 = orc_compiler_get_temp_reg(p); ++ int tmp = p->tmpreg; ++ powerpc_denormalize_dp_zero (p, src1, zero); ++ powerpc_denormalize_dp_zero (p, src2, zero); ++ powerpc_emit_VX_2(p, "xvmindp", 0xf0000747, tmp2, src2, src1); ++ // Handle QNaN ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, src1, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, mask); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, dest, tmp2, src1, tmp); ++} + +-// powerpc_emit_VXR (p, "vcmpgtfp", 0x100002c6, dest, src2, src1, FALSE); ++static void ++powerpc_rule_maxd (OrcCompiler *p, void *user, OrcInstruction *insn) ++{ ++ int src1 = ORC_SRC_ARG (p, insn, 0); ++ int src2 = ORC_SRC_ARG (p, insn, 1); ++ int dest = ORC_DEST_ARG (p, insn, 0); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ int mask = powerpc_get_constant_full (p, 0x7ff80000, 0x00000000, ++ 0x7ff80000, 0x00000000); ++ int tmp2 = orc_compiler_get_temp_reg(p); ++ int tmp3 = orc_compiler_get_temp_reg(p); ++ int tmp = p->tmpreg; ++ powerpc_denormalize_dp_zero (p, src1, zero); ++ powerpc_denormalize_dp_zero (p, src2, zero); ++ powerpc_emit_VX_2(p, "xvmaxdp", 0xf0000707, tmp2, src2, src1); ++ // Handle QNaN ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, src2, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, mask); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, tmp3, tmp2, src2, tmp); ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, src1, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, mask); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, dest, tmp3, src1, tmp); ++} ++ ++static void ++powerpc_rule_cmpltd (OrcCompiler *p, void *user, OrcInstruction *insn) ++{ ++ int src1 = ORC_SRC_ARG (p, insn, 0); ++ int src2 = ORC_SRC_ARG (p, insn, 1); ++ int dest = ORC_DEST_ARG (p, insn, 0); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_dp_zero (p, src1, zero); ++ powerpc_denormalize_dp_zero (p, src2, zero); + powerpc_emit_VX_2(p, "xvcmpgtdp", 0xf000035f, dest, src2, src1); + } + +@@ -1551,8 +1614,9 @@ powerpc_rule_cmpled (OrcCompiler *p, void *user, OrcInstruction *insn) + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); +- +-// powerpc_emit_VXR (p, "vcmpgefp", 0x100001c6, dest, src2, src1, FALSE); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ powerpc_denormalize_dp_zero (p, src1, zero); ++ powerpc_denormalize_dp_zero (p, src2, zero); + powerpc_emit_VX_2(p, "xvcmpgedp", 0xf000039f, dest, src2, src1); + } + +@@ -1561,11 +1625,13 @@ powerpc_rule_convld (OrcCompiler *p, void *user, OrcInstruction *insn) + { + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); + + if (IS_POWERPC_LE (p)) { + powerpc_emit_vsldoi(p, src1, src1, src1, 4); + } + powerpc_emit_VX_db (p, "xvcvsxddp", 0xf00003e3, dest, src1); ++ powerpc_denormalize_dp_zero (p, dest, zero); + } + + static void +@@ -1573,8 +1639,19 @@ powerpc_rule_convdl (OrcCompiler *p, void *user, OrcInstruction *insn) + { + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int mask = powerpc_get_constant_full (p, 0xfff00000, 0x00000000, ++ 0xfff00000, 0x00000000); ++ int nan = powerpc_get_constant_full (p, 0x7ff00000, 0x00000000, ++ 0x7ff00000, 0x00000000); ++ int maxint = powerpc_get_constant_full (p, 0x7fffffff, 0x7fffffff, ++ 0x7fffffff, 0x7fffffff); ++ int tmp = p->tmpreg; + ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, src1, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, nan); + powerpc_emit_VX_db (p, "xvcvdpsxws", 0xf0000363, dest, src1); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, dest, dest, maxint, tmp); ++ + if (IS_POWERPC_LE (p)) { + int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 32); + powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); +@@ -1586,11 +1663,23 @@ powerpc_rule_convfd (OrcCompiler *p, void *user, OrcInstruction *insn) + { + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); ++ int tmp2 = orc_compiler_get_temp_reg(p); ++ int zero = powerpc_get_constant (p, ORC_CONST_ZERO, 0); ++ int mask = powerpc_get_constant_full (p, 0x7f800000, 0x00000000, ++ 0x7f800000, 0x00000000); ++ int tmp = p->tmpreg; + + if (IS_POWERPC_LE (p)) { +- powerpc_emit_vsldoi(p, src1, src1, src1, 4); ++ powerpc_emit_vsldoi(p, tmp2, src1, src1, 4); ++ } else { ++ powerpc_emit_vor(p, tmp2, src1, src1); + } +- powerpc_emit_VX_db (p, "xvcvspdp", 0xf0000727, dest, src1); ++ powerpc_emit_VX_db (p, "xvcvspdp", 0xf0000727, dest, tmp2); ++ ++ powerpc_emit_VX_2(p, "xxland", 0xf0000417, tmp, tmp2, mask); ++ powerpc_emit_VX_2(p, "vcmpequd", 0x100000c7, tmp, tmp, zero); ++ powerpc_emit_VA(p, "xxsel", 0xf000003f, tmp, dest, zero, tmp); ++ powerpc_emit_VX_2(p, "xvcpsgndp", 0xf0000787, dest, dest, tmp); + } + + static void +@@ -1604,6 +1693,7 @@ powerpc_rule_convdf (OrcCompiler *p, void *user, OrcInstruction *insn) + int tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 32); + powerpc_emit_VX_2 (p, "vsro", 0x1000044c, dest, dest, tmp); + } ++ powerpc_denormalize_sp(p, dest); + } + + +@@ -1757,7 +1847,6 @@ orc_compiler_powerpc_register_rules (OrcTarget *target) + REG(cmplef); + REG(cmpltf); + REG(mulf); +- REG(divf); + REG(convfl); + REG(convlf); + +@@ -1789,6 +1878,7 @@ orc_compiler_powerpc_register_rules (OrcTarget *target) + + rule_set = orc_rule_set_new(orc_opcode_set_get("sys"), target, ORC_TARGET_POWERPC_VSX); + ++ REG(divf); + REG(sqrtf); + REG(addd); + REG(subd); +diff --git a/orc/orctarget.h b/orc/orctarget.h +index 642bfe3..53000b3 100644 +--- a/orc/orctarget.h ++++ b/orc/orctarget.h +@@ -19,7 +19,7 @@ enum { + ORC_TARGET_FAST_DENORMAL = (1<<31) + }; + +-enum { ++typedef enum { + ORC_TARGET_POWERPC_64BIT = (1<<0), + ORC_TARGET_POWERPC_LE = (1<<1), + ORC_TARGET_POWERPC_ALTIVEC = (1<<2), +diff --git a/testsuite/exec_parse.c b/testsuite/exec_parse.c +index 0858413..859ad4e 100644 +--- a/testsuite/exec_parse.c ++++ b/testsuite/exec_parse.c +@@ -20,6 +20,7 @@ main (int argc, char *argv[]) + char *code; + int n; + int i; ++ int ret; + OrcProgram **programs; + const char *filename = NULL; + +@@ -45,7 +46,11 @@ main (int argc, char *argv[]) + + for(i=0;iname); +- orc_test_compare_output_full (programs[i], 0); ++ ret = orc_test_compare_output_full (programs[i], 0); ++ if (!ret) { ++ printf("failed %s\n", programs[i]->name); ++ error = TRUE; ++ } + orc_program_free (programs[i]); + } + +diff --git a/testsuite/memcpy_speed.c b/testsuite/memcpy_speed.c +index a1a69f1..4cf1c39 100644 +--- a/testsuite/memcpy_speed.c ++++ b/testsuite/memcpy_speed.c +@@ -102,7 +102,7 @@ main(int argc, char *argv[]) + max = 140; + } + +- for(i=0;i