diff --git a/gcc/config/rs6000/integer.md b/gcc/config/rs6000/integer.md
new file mode 100644
index 0000000..0884e0f
--- /dev/null
+++ b/gcc/config/rs6000/integer.md
@@ -0,0 +1,148 @@
+; Generated by mdm.pl; do not edit (edit the .mdm instead).
+; vi:ro
+
+
+; Copyright (C) 1990-2013 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+
+; This file describes the integer (GPR-to-GPR) PowerPC instructions.
+; Most of these have record-form ("dot") variants, and are described
+; using define_dot_insn.
+
+
+; -- Rotate and shift instructions:
+; rlwinm[.], rlwnm[.], rldicl[.], rldicr[.], rldic[.], rldcl[.], rldcr[.]
+; rlwimi[.], rldimi[.]
+; slw[.], srw[.], srawi[.], sraw[.], sld[.], srd[.], sradi[.], srad[.]
+
+
+(define_insn "lshrdi3"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+		     (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
+  "TARGET_POWERPC64"
+  "@
+   srd %0,%1,%2
+   srdi %0,%1,%H2"
+  [(set_attr "type" "var_shift_rotate,shift") ; var_delayed_compare,delayed_compare
+])
+
+(define_insn "*lshrdi3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+     (compare:CC
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+		     (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
+	(const_int 0)))
+   (clobber (match_scratch:DI 0 "=r,r,r,r"))]
+  "(TARGET_POWERPC64)
+   && (DImode == Pmode && rs6000_gen_cell_microcode)"
+  "@
+   srd. %0,%1,%2
+   srdi. %0,%1,%H2
+   #
+   #"
+  [(set_attr "length" "4,4,8,8")
+   (set_attr "dot" "yes,yes,no,no")
+   (set_attr "type" "var_shift_rotate,shift,var_shift_rotate,shift") ; var_delayed_compare,delayed_compare
+])
+
+(define_split
+  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
+     (compare:CC
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
+		     (match_operand:SI 2 "reg_or_cint_operand" ""))
+	(const_int 0)))
+   (clobber (match_scratch:DI 0 ""))]
+  "((TARGET_POWERPC64)
+   && (DImode == Pmode && rs6000_gen_cell_microcode))
+   && (reload_completed)"
+  [(set (match_dup 0)
+	(lshiftrt:DI (match_dup 1)
+		     (match_dup 2)))
+   (set (match_dup 3)
+	(compare:CC (match_dup 0)
+		    (const_int 0)))]
+  "")
+
+(define_insn "*lshrdi3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
+     (compare:CC
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
+		     (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
+	(const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
+	(lshiftrt:DI (match_dup 1)
+		     (match_dup 2)))]
+  "(TARGET_POWERPC64)
+   && (DImode == Pmode && rs6000_gen_cell_microcode)"
+  "@
+   srd. %0,%1,%2
+   srdi. %0,%1,%H2
+   #
+   #"
+  [(set_attr "length" "4,4,8,8")
+   (set_attr "dot" "yes,yes,no,no")
+   (set_attr "type" "var_shift_rotate,shift,var_shift_rotate,shift") ; var_delayed_compare,delayed_compare
+])
+
+(define_split
+  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
+     (compare:CC
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
+		     (match_operand:SI 2 "reg_or_cint_operand" ""))
+	(const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "")
+	(lshiftrt:DI (match_dup 1)
+		     (match_dup 2)))]
+  "((TARGET_POWERPC64)
+   && (DImode == Pmode && rs6000_gen_cell_microcode))
+   && (reload_completed)"
+  [(set (match_dup 0)
+	(lshiftrt:DI (match_dup 1)
+		     (match_dup 2)))
+   (set (match_dup 3)
+	(compare:CC (match_dup 0)
+		    (const_int 0)))]
+  "")
+
+
+; -- Logical instructions:
+; andi., andis., ori, oris, xori, xoris
+; and[.], or[.], xor[.], nand[.], nor[.], eqv[.], andc[.], orc[.]
+; extsb[.], extsh[.], extsw[.], cntlzw[.], cntlzd[.]
+
+
+; -- Arithmetic instructions:
+; addi, addis, add[.], subf[.], neg[.]
+; addic[.], subfic, addc[.], subfc[.]
+; adde[.], subfe[.], addme[.], subfme[.], addze[.], subfze[.]
+; mulli, mullw[.], mulhw[.], mulhwu[.], mulld[.], mulhd[.], mulhdu[.]
+; divw[.], divwu[.], divd[.], divdu[.]
+
+
+; -- Compare instructions:
+; cmpwi, cmpdi, cmpw, cmpd, cmplwi, cmpldi, cmplw, cmpld
+
+
+; -- Trap instructions:
+; twi, tw, tdi, td
+
+
+; -- System register instructions:
+; mtcrf, mfcr, mtocrf, mfocrf
diff --git a/gcc/config/rs6000/integer.mdm b/gcc/config/rs6000/integer.mdm
new file mode 100644
index 0000000..23ff8ca
--- /dev/null
+++ b/gcc/config/rs6000/integer.mdm
@@ -0,0 +1,67 @@
+; Copyright (C) 1990-2013 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+
+; This file describes the integer (GPR-to-GPR) PowerPC instructions.
+; Most of these have record-form ("dot") variants, and are described
+; using define_dot_insn.
+
+
+; -- Rotate and shift instructions:
+; rlwinm[.], rlwnm[.], rldicl[.], rldicr[.], rldic[.], rldcl[.], rldcr[.]
+; rlwimi[.], rldimi[.]
+; slw[.], srw[.], srawi[.], sraw[.], sld[.], srd[.], sradi[.], srad[.]
+
+
+(define_dot_insn "lshrdi3"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+		     (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
+  "TARGET_POWERPC64"
+  "DImode == Pmode && rs6000_gen_cell_microcode"
+  "@
+   srd %0,%1,%2
+   srdi %0,%1,%H2"
+  [(set_attr "type" "var_shift_rotate,shift") ; var_delayed_compare,delayed_compare
+])
+
+
+; -- Logical instructions:
+; andi., andis., ori, oris, xori, xoris
+; and[.], or[.], xor[.], nand[.], nor[.], eqv[.], andc[.], orc[.]
+; extsb[.], extsh[.], extsw[.], cntlzw[.], cntlzd[.]
+
+
+; -- Arithmetic instructions:
+; addi, addis, add[.], subf[.], neg[.]
+; addic[.], subfic, addc[.], subfc[.]
+; adde[.], subfe[.], addme[.], subfme[.], addze[.], subfze[.]
+; mulli, mullw[.], mulhw[.], mulhwu[.], mulld[.], mulhd[.], mulhdu[.]
+; divw[.], divwu[.], divd[.], divdu[.]
+
+
+; -- Compare instructions:
+; cmpwi, cmpdi, cmpw, cmpd, cmplwi, cmpldi, cmplw, cmpld
+
+
+; -- Trap instructions:
+; twi, tw, tdi, td
+
+
+; -- System register instructions:
+; mtcrf, mfcr, mtocrf, mfocrf
diff --git a/gcc/config/rs6000/mdm.pl b/gcc/config/rs6000/mdm.pl
new file mode 100755
index 0000000..607e9cc
--- /dev/null
+++ b/gcc/config/rs6000/mdm.pl
@@ -0,0 +1,470 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2013 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+
+# Pre-process a machine description file as text.  Preserve whitespace and
+# comments as much as possible.
+#
+# Currently this just expands "define_dot_insn" constructs into three
+# "define_insn"s and two "define_split"s, which handle integer PowerPC
+# record form instructions.
+
+
+use v5.14;     # Needed for /r; otherwise, v5.10 for (?-1).
+use strict;
+use warnings;
+use re "/s";   # Newlines are not usually significant in MD files.
+
+
+# Interpolate arrays into strings without spaces between the elements.
+$" = "";
+
+
+my $ws = qr/
+		(?>
+			\s		# whitespace char
+			| ;.*?\n	# lisp comment
+			| \/\*.*?\*\/	# C comment
+		)+
+	/x;
+
+my $string = qr/
+		(?>
+			"
+			(?: \\. | [^\"] )*
+			"
+		)
+	/x;
+
+my $block = qr/
+		((?>
+			\{
+			(?: [^{}]++ | (?-1) )*+
+			\}
+		))
+	/x;
+
+# An "atom" is any RTL construct, followed by optional whitespace.
+my $atom = qr/
+		((?>
+			\( $ws?+ (?: (?-1) )++ \)
+			| \[ $ws?+ (?: (?-1) )++ \]
+			| [-:<>\w]++
+			| $string
+			| $block
+		)$ws?+)
+	/x;
+
+
+# Split an atom into something that matches $head, a list of atoms, and
+# finally something that matches $tail.  No error checking is done or
+# needed, that's the callers' job.
+sub decompose {
+	my ($x, $head, $tail) = @_;
+	$x =~ /^(\Q$head\E$ws?+)/g;
+	$head = $1;
+
+	my @body;
+	my $last = pos $x;
+	while ($x =~ /\G($atom)/g) {
+		push @body, $1;
+		$last = pos $x;
+	}
+	pos $x = $last;
+
+	$x =~ /\G(\Q$tail\E$ws?+)/g;
+	$tail = $1;
+
+	return ($head, @body, $tail);
+}
+
+# Merge two conditions (double-quoted pieces of C code) into one.
+sub join_cond {
+	my ($c1, $c2) = @_;
+
+	return $c1 if $c2 =~ /^""/;
+	return $c2 if $c1 =~ /^""/;
+
+	$c1 =~ s/^"([^"]*).*/"\($1\)\n  /;
+	$c2 =~ s/^"([^"]*)"/ && \($1\)"/;
+
+	return "$c1$c2";
+}
+
+# Double a constraint, e.g. "=r,i" becomes "=r,i,r,i".
+sub double_constraint {
+	my $x = shift;
+	return $x =~ s/(\w[^"]*)/$1,$1/r;
+}
+
+# Double all constraints in an atom.
+sub double_constraints {
+	my $pattern = shift;
+
+	if ($pattern =~ /^\(match_operand\b/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		$body[3] = double_constraint $body[3];
+		return "$head@body";
+	}
+
+	if ($pattern =~ /^\(match_scratch\b/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		$body[2] = double_constraint $body[2];
+		return "$head@body";
+	}
+
+	if ($pattern =~ /^[([]/) {
+		my $first = substr $pattern, 0, 1;
+		my $last = ($first eq "(") ? ")" : "]";
+		my ($head, @body) = decompose $pattern, $first, $last;
+		my $tail = pop @body;
+
+		@body = map { double_constraints($_) } @body;
+
+		return "$head@body$tail";
+	}
+
+	return $pattern;
+}
+
+# Remove a constraint, e.g. "=r,i" becomes "".
+sub remove_constraint {
+	my $x = shift;
+	return $x =~ s/"[^"]*/"/r;
+}
+
+# Remove all constraints in an atom.
+sub remove_constraints {
+	my $pattern = shift;
+
+	if ($pattern =~ /^\(match_operand\b/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		$body[3] = remove_constraint $body[3];
+		return "$head@body";
+	}
+
+	if ($pattern =~ /^\(match_scratch\b/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		$body[2] = remove_constraint $body[2];
+		return "$head@body";
+	}
+
+	if ($pattern =~ /^[([]/) {
+		my $first = substr $pattern, 0, 1;
+		my $last = ($first eq "(") ? ")" : "]";
+		my ($head, @body) = decompose $pattern, $first, $last;
+		my $tail = pop @body;
+
+		@body = map { remove_constraints($_) } @body;
+
+		return "$head@body$tail";
+	}
+
+	return $pattern;
+}
+
+# Change all "match_operand" and "match_scratch" to the equally numbered
+# "match_dup" construct.
+sub make_match_dups {
+	my $pattern = shift;
+
+	if ($pattern =~ /^\(match_(?:operand|scratch)\b/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		my $tail = pop @body;
+		$body[1] =~ /(\d+)/;
+		return "${head}match_dup $1$tail";
+	}
+
+	if ($pattern =~ /^[([]/) {
+		my $first = substr $pattern, 0, 1;
+		my $last = ($first eq "(") ? ")" : "]";
+		my ($head, @body) = decompose $pattern, $first, $last;
+		my $tail = pop @body;
+
+		@body = map { make_match_dups($_) } @body;
+
+		return "$head@body$tail";
+	}
+
+	return $pattern;
+}
+
+# Find out the highest operand number used in a "match_<anything>".
+sub max_op {
+	my $pattern = shift;
+
+	if ($pattern =~ /^\(match_/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		return $body[1];
+	}
+
+	if ($pattern =~ /^[([]/) {
+		my $first = substr $pattern, 0, 1;
+		my $last = ($first eq "(") ? ")" : "]";
+		my ($head, @body) = decompose $pattern, $first, $last;
+		pop @body;
+
+		my $max = -1;
+		for (@body) {
+			my $x = max_op($_);
+			$max = $x if $x > $max;
+		}
+		return $max;
+	}
+
+	return -1;
+}
+
+# Find out the number of alternatives in this insn pattern.
+sub num_alts {
+	my $pattern = shift;
+
+	if ($pattern =~ /^\(match_operand/) {
+		my ($head, @body) = decompose $pattern, "(", ")";
+		$body[3] =~ /"([^"]*)"/;
+		return 1 + $1 =~ tr/,//;
+	}
+
+	if ($pattern =~ /^[([]/) {
+		my $first = substr $pattern, 0, 1;
+		my $last = ($first eq "(") ? ")" : "]";
+		my ($head, @body) = decompose $pattern, $first, $last;
+		pop @body;
+
+		my $max = 1;
+		for (@body) {
+			my $x = num_alts($_);
+			$max = $x if $x > $max;
+		}
+		return $max;
+	}
+
+	return 1;
+}
+
+# Make the various new patterns used in the two "define_insn"s and the
+# two "define_split"s we manufacture: a "dot" pattern for the "compare
+# the result of the insn to zero, and clobber" version; a "dot2" pattern
+# for the "compare and set" version; and a "split" pattern for the result
+# of the splitters.
+#
+# If the original pattern is a parallel, the set of the GPR that the dot
+# compare uses has to be first.
+sub make_dotpatterns {
+	my ($pattern, $n_ops, $n_alts) = @_;
+
+	my ($head, @body) = decompose $pattern, "[", "]";
+	my $tail = pop @body;
+
+	my $first = shift @body;
+	my ($ihead, @ibody) = decompose $first, "(", ")";
+	my $itail = pop @ibody;
+	die "$ARGV: insn not a valid SET in define_dot_insn pattern: $pattern\n"
+		if $ibody[0] !~ /^set\b/ or scalar @ibody != 3;
+	my ($set, $dst, $src) = @ibody;
+
+	my $compare = "(compare:CC\n\t$src\n\t(const_int 0))";
+	$compare = double_constraints $compare;
+	my $constraint = (",x" x $n_alts) . (",?y" x $n_alts);
+	$constraint =~ s/^,/=/;
+
+	my $set_cc = "$set(match_operand:CC $n_ops " .
+		qq/"cc_reg_operand" "$constraint")\n     /;
+
+	my @double_body = map { double_constraints $_ } @body;
+
+	my $dotset = "(clobber $dst" =~ s/\).*/))/r =~ s/operand/scratch/r;
+	$dotset =~ s/"[^"]*"$ws//;
+	$dotset = double_constraints $dotset;
+	my $dotpat = "$head$ihead$set_cc$compare)";
+	$dotpat .= "\n   @double_body" if scalar @body;
+	$dotpat .= "\n   $dotset$tail";
+
+	my $src_dup = make_match_dups $src;
+	my $dot2set = double_constraints "$ihead$set$dst$src_dup$itail";
+	my $dot2pat = "$head$ihead$set_cc$compare)\n   $dot2set";
+	$dot2pat .= "@double_body" if scalar @body;
+	$dot2pat .= $tail;
+
+	my @dup_body = map { make_match_dups $_ } @body;
+
+	my $dup = make_match_dups $first;
+	my @dd = decompose $dup, "(", ")";
+	$dd[2] =~ s/\).*/)/;
+	my $comp = "(set (match_dup $n_ops)\n\t" .
+		"(compare:CC $dd[2]\n\t\t    " .
+		"(const_int 0)))";
+	my $splitpat = "$dup";
+	$splitpat = "(parallel [\n   $splitpat@dup_body])" if (scalar @body);
+	$splitpat = "$head$splitpat\n   $comp$tail";
+
+	return ($dotpat, $dot2pat, $splitpat);
+}
+
+# Construct an output template suitable for the dot instructions: change
+# the mnemonics to include the ".", and add "#" alternatives for the split.
+sub make_dottemplate {
+	my ($template, $n_alts) = @_;
+
+	die "$ARGV: template not a string: $template\n" if $template !~ /^"/;
+
+	$template =~ s/^"(?:\s*@\s*)?//;
+	$template =~ s/(^\s*+\S++)/$1./mg;
+	my $hashes = "\n   #" x $n_alts;
+	$template =~ s/"/$hashes"/;
+	return qq/"@\n   $template/;
+}
+
+# Change a set_attr with multiple alternatives to have those alternatives
+# twice, that is, for the split versions as well.
+sub make_dotattr {
+	my $attr = shift;
+
+	die "$ARGV: syntax error in attr: $attr\n" if $attr !~ /^\(/;
+
+	my ($head, @body) = decompose $attr, "(", ")";
+
+	$body[2] =~ s/"([^"]*)"/"$1,$1"/
+		if $body[0] =~ /^set_attr\b/
+		and $body[2] =~ /,/;
+
+	return "$head@body";
+}
+
+# Make an attribute vector for a dot insn: double all existing attributes,
+# add a "length" attribute, add a "dot" attribute.
+#
+# This currently only supports single insns in the pattern.
+sub make_dotattrs {
+	my ($attrs, $n_alts) = @_;
+
+	$attrs ||= "[]";
+
+	my ($head, @body) = decompose $attrs, "[", "]";
+	my $tail = pop @body;
+
+	@body = map { make_dotattr($_) } @body;
+
+	my $length_attr = (",4" x $n_alts) . (",8" x $n_alts);
+	$length_attr =~ s/^,//;
+	$length_attr = qq/(set_attr "length" "$length_attr")\n   /;
+
+	my $dot_attr = (",yes" x $n_alts) . (",no" x $n_alts);
+	$dot_attr =~ s/^,//;
+	$dot_attr = qq/(set_attr "dot" "$dot_attr")/;
+	$dot_attr .= "\n   " unless $attrs eq "[]";
+
+	return "$head$length_attr$dot_attr@body$tail";
+}
+
+# Split a "define_dot_insn" into the appropriate three "define_insn"s and
+# two "define_split"s.
+sub handle_define_dot_insn {
+	my $x = shift;
+	my ($head, @body) = decompose $x, "(", ")";
+	my $tail = pop @body;
+
+	# TODO: check the atom types of @body here?  This script might
+	# die a fiery death if the input file gets it wrong.
+
+	my $define_dot_insn = shift @body;
+	my $name = shift @body;
+	my $pattern = shift @body;
+	my $cond = shift @body;
+	my $dotcond = shift @body;
+	my $template = shift @body;
+	my $attrs = shift @body;
+
+	my $n_ops = 1 + max_op $pattern;
+	my $n_alts = num_alts $pattern;
+
+	my $define_insn = $define_dot_insn =~ s/dot_//r;
+	my $define_split = $name =~ s/^"[^"]*"/define_split/r;
+
+	my $name1 = $name =~ s/^"\*?([^"]*)/"*$1_dot/r;
+	my $name2 = $name =~ s/^"\*?([^"]*)/"*$1_dot2/r;
+
+	my ($dotpat, $dot2pat, $splittedpat) =
+		make_dotpatterns $pattern, $n_ops, $n_alts;
+
+	$dotcond = join_cond $cond, $dotcond;
+
+	my $dottemplate = make_dottemplate $template, $n_alts;
+
+	my $dotattrs = make_dotattrs $attrs, $n_alts;
+
+	my $splitpat = remove_constraints $dotpat;
+	my $split2pat = remove_constraints $dot2pat;
+	$splitpat =~ s/cc_reg/cc_reg_not_cr0/;
+	$split2pat =~ s/cc_reg/cc_reg_not_cr0/;
+
+	my $splitcond = join_cond $dotcond, qq/"reload_completed"\n  /;
+
+	my $prep = qq/""/;
+
+	if (not defined $attrs) {
+		$attrs = "";
+		$dottemplate .= "\n  ";
+	}
+
+	print $head;
+	print $define_insn, $name, $pattern, $cond, $template, $attrs;
+	print ")\n\n(";
+	print $define_insn, $name1, $dotpat, $dotcond, $dottemplate, $dotattrs;
+	print ")\n\n(";
+	print $define_split, $splitpat, $splitcond, $splittedpat, $prep;
+	print ")\n\n(";
+	print $define_insn, $name2, $dot2pat, $dotcond, $dottemplate, $dotattrs;
+	print ")\n\n(";
+	print $define_split, $split2pat, $splitcond, $splittedpat, $prep;
+	print $tail;
+}
+
+sub handle_other {
+	print @_;
+}
+
+
+# Slurp the whole input file.
+my $mdm;
+{
+	local $/;
+	$mdm = <>;
+}
+
+print "; Generated by mdm.pl; do not edit (edit the .mdm instead).\n";
+print "; vi:ro\n\n\n";
+
+# Handle leading whitespace.
+$mdm =~ /^($ws?+)/g;
+print $1;
+
+# Finally, handle the rest.
+while ($mdm =~ /\G($atom|(?>.))/g) {
+	my $x = $1;
+
+	$x =~ /^\((\w+)/ or die "$ARGV: bad toplevel construct:\n$x\n";
+
+	if ($1 eq "define_dot_insn") {
+		handle_define_dot_insn $x;
+	} else {
+		handle_other $x;
+	}
+}
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 6be05a4..7adde36 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -149,6 +149,9 @@ (define_c_enum "unspecv"
 (define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto"
   (const_string "integer"))
 
+;; Is this instruction a "dot" (record) instruction or not?
+(define_attr "dot" "no,yes" (const_string "no"))
+
 ;; Define floating point instruction sub-types for use with Xfpu.md
 (define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default"))
 
@@ -361,6 +364,8 @@ (define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS")
 (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
 				(DF "TARGET_DOUBLE_FLOAT")])
 
+(include "integer.md")
+
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
 
@@ -7671,83 +7676,6 @@ (define_split
 		    (const_int 0)))]
   "")
 
-(define_expand "lshrdi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-		     (match_operand:SI 2 "reg_or_cint_operand" "")))]
-  "TARGET_POWERPC64"
-  "")
-
-(define_insn "*lshrdi3_internal1"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-	(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-		     (match_operand:SI 2 "reg_or_cint_operand" "r,i")))]
-  "TARGET_POWERPC64"
-  "@
-   srd %0,%1,%2
-   srdi %0,%1,%H2"
-  [(set_attr "type" "var_shift_rotate,shift")])
-
-(define_insn "*lshrdi3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-	(compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
-				 (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
-		    (const_int 0)))
-   (clobber (match_scratch:DI 3 "=r,r,r,r"))]
-  "TARGET_64BIT "
-  "@
-   srd. %3,%1,%2
-   srdi. %3,%1,%H2
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-	(compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-				 (match_operand:SI 2 "reg_or_cint_operand" ""))
-		    (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-	(lshiftrt:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-	(compare:CC (match_dup 3)
-		    (const_int 0)))]
-  "")
-
-(define_insn "*lshrdi3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-	(compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
-				 (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i"))
-		    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
-	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   srd. %0,%1,%2
-   srdi. %0,%1,%H2
-   #
-   #"
-  [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
-   (set_attr "length" "4,4,8,8")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-	(compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-				 (match_operand:SI 2 "reg_or_cint_operand" ""))
-		    (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-	(lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 0)
-	(lshiftrt:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-	(compare:CC (match_dup 0)
-		    (const_int 0)))]
-  "")
-
 (define_expand "ashrdi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
 	(ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index ecfdf0e..5e1cf54 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -65,6 +65,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rs64.md \
 	$(srcdir)/config/rs6000/a2.md \
 	$(srcdir)/config/rs6000/predicates.md \
 	$(srcdir)/config/rs6000/constraints.md \
+	$(srcdir)/config/rs6000/integer.md \
 	$(srcdir)/config/rs6000/darwin.md \
 	$(srcdir)/config/rs6000/sync.md \
 	$(srcdir)/config/rs6000/vector.md \
@@ -74,3 +75,8 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rs64.md \
 	$(srcdir)/config/rs6000/spe.md \
 	$(srcdir)/config/rs6000/dfp.md \
 	$(srcdir)/config/rs6000/paired.md
+
+MDM := $(srcdir)/config/rs6000/mdm.pl
+
+$(srcdir)/config/rs6000/%.md: $(srcdir)/config/rs6000/%.mdm $(MDM)
+	$(MDM) $< > $@ || (rm $@ ; exit 1)
