summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--user/orc/APKBUILD32
-rw-r--r--user/orc/ppc-fixes.patch990
2 files changed, 1003 insertions, 19 deletions
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 <ncopa@alpinelinux.org>
# Maintainer: A. Wilcox <awilfox@adelielinux.org>
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;i<compiler->n_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;i<ORC_N_COMPILER_VARIABLES;i++){
+ if (compiler->vars[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;i<n;i++){
+ if (verbose) printf("%s\n", programs[i]->name);
+- 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<max;i++){
++ for(i=0;i<max;i+=2){
+ double x = i*0.1 + 6.0;
+ int size = pow(2.0, x);
+