add (init_integer_type (alloc, 32, 1, "u32"));
   add (init_integer_type (alloc, 64, 0, "i64"));
   add (init_integer_type (alloc, 64, 1, "u64"));
+  add (init_integer_type (alloc, 128, 0, "i128"));
+  add (init_integer_type (alloc, 128, 1, "u128"));
 
   unsigned int length = 8 * builtin->builtin_data_ptr->length ();
   add (init_integer_type (alloc, length, 0, "isize"));
 
 #define INT_TEXT 5
 #define INT_TYPE 6
   "(0x[a-fA-F0-9_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*)"
-  "([iu](size|8|16|32|64))?"
+  "([iu](size|8|16|32|64|128))?"
   ")";
 /* The number of subexpressions to allocate space for, including the
    "0th" whole match subexpression.  */
 
 struct typed_val_int
 {
-  ULONGEST val;
+  gdb_mpz val;
   struct type *type;
 };
 
   /* Parse the number.  */
   if (is_integer)
     {
-      uint64_t value;
       int radix = 10;
       int offset = 0;
 
            }
        }
 
-      const char *trailer;
-      value = strtoulst (number.c_str () + offset, &trailer, radix);
-      if (*trailer != '\0')
-       error (_("Integer literal is too large"));
-      if (implicit_i32 && value >= ((uint64_t) 1) << 31)
-       type = get_type ("i64");
+      if (!current_int_val.val.set (number.c_str () + offset, radix))
+       {
+         /* Shouldn't be possible.  */
+         error (_("Invalid integer"));
+       }
+      if (implicit_i32)
+       {
+         static gdb_mpz sixty_three_bit = gdb_mpz::pow (2, 63);
+         static gdb_mpz thirty_one_bit = gdb_mpz::pow (2, 31);
+
+         if (current_int_val.val >= sixty_three_bit)
+           type = get_type ("i128");
+         else if (current_int_val.val >= thirty_one_bit)
+           type = get_type ("i64");
+       }
 
-      current_int_val.val = value;
       current_int_val.type = type;
     }
   else
       break;
 
     case DECIMAL_INTEGER:
-      result = make_operation<rust_struct_anon> (current_int_val.val,
-                                                std::move (lhs));
-      lex ();
+      {
+       int idx = current_int_val.val.as_integer<int> ();
+       result = make_operation<rust_struct_anon> (idx, std::move (lhs));
+       lex ();
+      }
       break;
 
     case INTEGER:
 
   if (current_token != INTEGER && current_token != DECIMAL_INTEGER)
     error (_("integer expected"));
-  ULONGEST val = current_int_val.val;
+  ULONGEST val = current_int_val.val.as_integer<ULONGEST> ();
   lex ();
   require (']');
 
 
            return [list "i32" $n]
        } elseif { [fits_in_type $n 64 s] } {
            return [list "i64" $n]
-       } elseif { [fits_in_type $n 64 u] } {
-           # Note: Interprets MAX_U64 as -1.
-           return [list "i64" $n]
+       } elseif { [fits_in_type $n 128 u] } {
+           return [list "i128" $n]
+       } elseif { [fits_in_type $n 128 u] } {
+           return [list "i128" $n]
        } else {
            # Overflow.
            return [list $re_overflow $re_overflow]
 
 gdb_test "print/x x & mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"
 gdb_test "print/x x ^ mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"
 gdb_test "print/x mask | (mask >> 4)" " = 0xffffffffffffffffffffffffffffffff"
+
+gdb_test "print 170141183460469231731687303715884105727" \
+    " = 170141183460469231731687303715884105727"
+gdb_test "ptype 23i128" "type = i128"