diff --git a/gcc/common/config/rs6000/rs6000-common.cc b/gcc/common/config/rs6000/rs6000-common.cc
index 8e393d08a23..c76b5c27bb6 100644
--- a/gcc/common/config/rs6000/rs6000-common.cc
+++ b/gcc/common/config/rs6000/rs6000-common.cc
@@ -119,19 +119,8 @@ rs6000_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
 #else
     case OPT_m64:
 #endif
-      opts->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
       opts->x_rs6000_isa_flags |= (~opts_set->x_rs6000_isa_flags
 				   & OPTION_MASK_PPC_GFXOPT);
-      opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
-      break;
-
-#ifdef TARGET_USES_AIX64_OPT
-    case OPT_maix32:
-#else
-    case OPT_m32:
-#endif
-      opts->x_rs6000_isa_flags &= ~OPTION_MASK_POWERPC64;
-      opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
       break;

     case OPT_mminimal_toc:
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index e6fa3ad0eb7..605d35893f9 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -3648,17 +3648,12 @@ rs6000_option_override_internal (bool global_init_p)
       rs6000_pointer_size = 32;
     }

-  /* Some OSs don't support saving the high part of 64-bit registers on context
-     switch.  Other OSs don't support saving Altivec registers.  On those OSs,
-     we don't touch the OPTION_MASK_POWERPC64 or OPTION_MASK_ALTIVEC settings;
-     if the user wants either, the user must explicitly specify them and we
-     won't interfere with the user's specification.  */
+  /* Some OSs don't support saving Altivec registers.  On those OSs, we don't
+     touch the OPTION_MASK_POWERPC64 or OPTION_MASK_ALTIVEC settings; if the
+     user wants either, the user must explicitly specify them and we won't
+     interfere with the user's specification.  */

   set_masks = POWERPC_MASKS;
-#ifdef OS_MISSING_POWERPC64
-  if (OS_MISSING_POWERPC64)
-    set_masks &= ~OPTION_MASK_POWERPC64;
-#endif
 #ifdef OS_MISSING_ALTIVEC
   if (OS_MISSING_ALTIVEC)
     set_masks &= ~(OPTION_MASK_ALTIVEC | OPTION_MASK_VSX
@@ -3753,6 +3748,26 @@ rs6000_option_override_internal (bool global_init_p)
 	error ("AltiVec not supported in this target");
     }

+  /* With option powerpc64 specified explicitly (either on or off), even if
+     being compiled for 64 bit we don't need to check if it's disabled here,
+     since subtargets will check and raise an error message if necessary
+     later.  But without option powerpc64 specified explicitly, we need to
+     ensure powerpc64 enabled for 64 bit and disabled on those OSes with
+     OS_MISSING_POWERPC64, since they don't support saving the high part of
+     64-bit registers on context switch.  */
+  if (!(rs6000_isa_flags_explicit & OPTION_MASK_POWERPC64))
+    {
+      if (TARGET_64BIT)
+	/* Make sure we always enable it by default for 64 bit.  */
+	rs6000_isa_flags |= OPTION_MASK_POWERPC64;
+#ifdef OS_MISSING_POWERPC64
+      else if (OS_MISSING_POWERPC64)
+	/* It's unexpected to have OPTION_MASK_POWERPC64 on for OSes which
+	   miss powerpc64 support, so disable it.  */
+	rs6000_isa_flags &= ~OPTION_MASK_POWERPC64;
+#endif
+    }
+
   /* If we are optimizing big endian systems for space, use the load/store
      multiple instructions.  */
   if (BYTES_BIG_ENDIAN && optimize_size)
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106680-1.c b/gcc/testsuite/gcc.target/powerpc/pr106680-1.c
new file mode 100644
index 00000000000..ff33f6864c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106680-1.c
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-mno-powerpc64" } */
+
+/* Verify there is an error message about PowerPC64 requirement.  */
+
+int foo ()
+{
+  return 1;
+}
+
+/* { dg-error "'-m64' requires a PowerPC64 cpu" "PR106680" { target powerpc*-*-linux* powerpc-*-rtems* } 0 } */
+/* { dg-warning "'-maix64' requires PowerPC64 architecture remain enabled" "PR106680" { target powerpc*-*-aix* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106680-2.c b/gcc/testsuite/gcc.target/powerpc/pr106680-2.c
new file mode 100644
index 00000000000..25439910c27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106680-2.c
@@ -0,0 +1,13 @@
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-mno-powerpc64 -m64" } */
+
+/* Verify option -m64 doesn't override option -mno-powerpc64,
+   and there is an error message about PowerPC64 requirement.  */
+
+int foo ()
+{
+  return 1;
+}
+
+/* { dg-error "'-m64' requires a PowerPC64 cpu" "PR106680" { target powerpc*-*-linux* powerpc-*-rtems* } 0 } */
+/* { dg-warning "'-maix64' requires PowerPC64 architecture remain enabled" "PR106680" { target powerpc*-*-aix* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106680-3.c b/gcc/testsuite/gcc.target/powerpc/pr106680-3.c
new file mode 100644
index 00000000000..f8eea8ea645
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106680-3.c
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-m64 -mno-powerpc64" } */
+
+/* Verify there is an error message about PowerPC64 requirement.  */
+
+int foo ()
+{
+  return 1;
+}
+
+/* { dg-error "'-m64' requires a PowerPC64 cpu" "PR106680" { target powerpc*-*-linux* powerpc-*-rtems* } 0 } */
+/* { dg-warning "'-maix64' requires PowerPC64 architecture remain enabled" "PR106680" { target powerpc*-*-aix* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106680-4.c b/gcc/testsuite/gcc.target/powerpc/pr106680-4.c
new file mode 100644
index 00000000000..bfbdd8eb0b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106680-4.c
@@ -0,0 +1,16 @@
+/* Skip this on aix, otherwise it emits the error message like "64-bit
+   computation with 32-bit addressing not yet supported" on aix.  */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-mpowerpc64 -m32 -O2" } */
+
+/* Verify option -m32 doesn't override option -mpowerpc64.
+   If option -mpowerpc64 gets overridden, the assembly would
+   end up with addc and adde.  */
+/* { dg-final { scan-assembler-not "addc" } } */
+/* { dg-final { scan-assembler-not "adde" } } */
+
+long long foo (long long a, long long b)
+{
+  return a+b;
+}
