]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/pdp11/pdp11.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
index a41e159012ebfae1be0dc51d3688190a9391c26d..585f09813d4c7fd96bb48c6b53ab7bbb42eded16 100644 (file)
@@ -1,5 +1,5 @@
 ;;- Machine description for the pdp11 for GNU C compiler
-;; Copyright (C) 1994-2018 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
 ;; This file is part of GCC.
@@ -26,6 +26,7 @@
     UNSPECV_BLOCKAGE
     UNSPECV_SETD
     UNSPECV_SETI
+    UNSPECV_CPYMEM
   ])
 
 (define_constants
    ;; Register numbers
    (R0_REGNUM            0)
    (RETVAL_REGNUM        0)
-   (HARD_FRAME_POINTER_REGNUM  5)
+   (FRAME_POINTER_REGNUM  5)
    (STACK_POINTER_REGNUM  6)
    (PC_REGNUM             7)
    (AC0_REGNUM            8)
    (AC3_REGNUM            11)
    (AC4_REGNUM            12)
    (AC5_REGNUM            13)
-   ;; The next two are not physical registers but are used for addressing
-   ;; arguments.
-   (FRAME_POINTER_REGNUM  14)
-   (ARG_POINTER_REGNUM    15)
+   ;; The next one is not a physical register but is used for
+   ;; addressing arguments.
+   (ARG_POINTER_REGNUM    14)
    ;; Condition code registers
-   (CC_REGNUM             16)
-   (FCC_REGNUM            17)
+   (CC_REGNUM             15)
+   (FCC_REGNUM            16)
    ;; End of hard registers
-   (FIRST_PSEUDO_REGISTER 18)
+   (FIRST_PSEUDO_REGISTER 17)
    
    ;; Branch offset limits, as byte offsets from (pc).  That is NOT
    ;; the same thing as "instruction address" -- it is for backward
@@ -82,6 +82,8 @@
 
 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
 
+(define_mode_iterator PDPfp [SF DF])
+
 ;; Substitution to turn a CC clobber into a CC setter.  We have four of
 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
 (define_subst "cc_cc"
    (set (match_dup 0) (match_dup 1))])
 
 (define_subst "fcc_cc"
-  [(set (match_operand 0 "") (match_operand 1 ""))
+  [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
    (clobber (reg FCC_REGNUM))]
   ""
   [(set (reg:CC FCC_REGNUM)
-       (compare:CC (match_dup 1) (const_int 0)))
+       (compare:CC (match_dup 1) (const_double_zero:PDPfp)))
    (set (match_dup 0) (match_dup 1))])
 
 (define_subst "fcc_ccnz"
-  [(set (match_operand 0 "") (match_operand 1 ""))
+  [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
    (clobber (reg FCC_REGNUM))]
   ""
   [(set (reg:CCNZ FCC_REGNUM)
-       (compare:CCNZ (match_dup 1) (const_int 0)))
+       (compare:CCNZ (match_dup 1) (const_double_zero:PDPfp)))
    (set (match_dup 0) (match_dup 1))])
 
 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
   DONE;
 })
 
-(define_expand "return"
-  [(return)]
-  "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
-  "")
-
-(define_insn "*rts"
+(define_insn "rtspc"
   [(return)]
   ""
   "rts\tpc")
    cmp<PDPint:isfx>\t%0,%1"
   [(set_attr "length" "2,2,4,4,4,6")])
 
+;; Two word compare
+(define_insn "cmpsi"
+  [(set (reg:CC CC_REGNUM)
+       (compare:CC (match_operand:SI 0 "general_operand" "rDQi")
+                   (match_operand:SI 1 "general_operand" "rDQi")))]
+  ""
+{
+  rtx inops[2];
+  rtx exops[2][2];
+  rtx lb[1];
+  
+  inops[0] = operands[0];
+  inops[1] = operands[1];
+  pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
+  lb[0] = gen_label_rtx ();
+  
+  if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0)
+   output_asm_insn ("tst\t%0", exops[0]);
+  else
+   output_asm_insn ("cmp\t%0,%1", exops[0]);
+  output_asm_insn ("bne\t%l0", lb);
+  if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0)
+   output_asm_insn ("tst\t%0", exops[1]);
+  else
+   output_asm_insn ("cmp\t%0,%1", exops[1]);
+  output_asm_label (lb[0]);
+  fputs (":\n", asm_out_file);
+
+  return "";
+}
+  [(set (attr "length")
+       (symbol_ref "pdp11_cmp_length (operands, 2)"))
+   (set_attr "base_cost" "0")])
+
+;; Four word compare
+(define_insn "cmpdi"
+  [(set (reg:CC CC_REGNUM)
+       (compare:CC (match_operand:DI 0 "general_operand" "rDQi")
+                   (match_operand:DI 1 "general_operand" "rDQi")))]
+  ""
+{
+  rtx inops[4];
+  rtx exops[4][2];
+  rtx lb[1];
+  int i;
+  
+  inops[0] = operands[0];
+  inops[1] = operands[1];
+  pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
+  lb[0] = gen_label_rtx ();
+
+  for (i = 0; i < 3; i++)
+    {
+      if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0)
+        output_asm_insn ("tst\t%0", exops[i]);
+      else
+        output_asm_insn ("cmp\t%0,%1", exops[i]);
+       output_asm_insn ("bne\t%l0", lb);
+     }
+  if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0)
+   output_asm_insn ("tst\t%0", exops[3]);
+  else
+   output_asm_insn ("cmp\t%0,%1", exops[3]);
+  output_asm_label (lb[0]);
+   fputs (":\n", asm_out_file);
+
+  return "";
+}
+  [(set (attr "length")
+       (symbol_ref "pdp11_cmp_length (operands, 2)"))
+   (set_attr "base_cost" "0")])
+
 ;; sob instruction
 ;;
-;; Do a define_expand because some alternatives clobber CC.
+;; This expander has to check for mode match because the doloop pass
+;; in gcc that invokes it does not do so, i.e., it may attempt to apply
+;; this pattern even if the count operand is QI or SI mode.
+(define_expand "doloop_end"
+  [(parallel [(set (pc)
+                  (if_then_else
+                   (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
+                       (const_int 1))
+                   (label_ref (match_operand 1 "" ""))
+                   (pc)))
+             (set (match_dup 0)
+                  (plus:HI (match_dup 0)
+                        (const_int -1)))])]
+  "TARGET_40_PLUS"
+  "{
+    if (GET_MODE (operands[0]) != HImode)
+      FAIL;
+  }")
+
+;; Do a define_split because some alternatives clobber CC.
 ;; Some don't, but it isn't all that interesting to cover that case.
-(define_insn_and_split "doloop_end"
+(define_insn_and_split "doloop_end_insn"
   [(set (pc)
        (if_then_else
         (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
 (define_insn_and_split "cbranch<mode>4"
   [(set (pc)
        (if_then_else (match_operator 0 "ordered_comparison_operator"
-                      [(match_operand:PDPint 1 "general_operand" "g")
-                       (match_operand:PDPint 2 "general_operand" "g")])
+                      [(match_operand:QHSDint 1 "general_operand" "g")
+                       (match_operand:QHSDint 2 "general_operand" "g")])
                      (label_ref (match_operand 3 "" ""))
                      (pc)))]
   ""
   "* return output_move_multiple (operands);"
   [(set_attr "length" "4,6,8,16")])
 
+;; That long string of "Z" constraints enforces the restriction that
+;; a register source and auto increment or decrement destination must
+;; not use the same register, because that case is not consistently
+;; implemented across the PDP11 models.
+;; TODO: the same should be applied to insn like add, but this is not
+;; necessary yet because the incdec optimization pass does not apply
+;; that optimization to 3-operand insns at the moment.
 (define_insn "mov<mode>"
-  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
-       (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
+       (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))]
   ""
   ""
-  [(set_attr "length" "2,4,4,6")])
+  [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
 
 ;; This splits all the integer moves: DI and SI modes as well as
 ;; the simple machine operations.
   
 ;; MOV clears V
 (define_insn "*mov<mode>_<cc_cc>"
-  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
-       (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
+       (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))
    (clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   "*
 
   return \"mov<PDPint:isfx>\t%1,%0\";
 }"
-  [(set_attr "length" "2,4,4,6")])
+  [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
 
 ;; movdf has unusually complicated condition code handling, because
 ;; load (into float register) updates the FCC, while store (from
   [(set_attr "length" "2,2,4,4,2")])
 
 ;; Expand a block move.  We turn this into a move loop.
-(define_expand "movmemhi"
-  [(match_operand:BLK 0 "general_operand" "=g")
-   (match_operand:BLK 1 "general_operand" "g")
-   (match_operand:HI 2 "immediate_operand" "i")
-   (match_operand:HI 3 "immediate_operand" "i")]
+(define_expand "cpymemhi"
+  [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
+             (match_operand:BLK 0 "general_operand" "=g")
+             (match_operand:BLK 1 "general_operand" "g")
+             (match_operand:HI 2 "immediate_operand" "i")
+             (match_operand:HI 3 "immediate_operand" "i")
+             (clobber (mem:BLK (scratch)))
+             (clobber (match_dup 0))
+             (clobber (match_dup 1))
+             (clobber (match_dup 2))])]
   ""
   "
 {
-  if (INTVAL (operands[2]) != 0)
-    expand_block_move (operands);
-  DONE;
+  int count;
+  count = INTVAL (operands[2]);
+  if (count == 0)
+    DONE;
+  if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
+    count >>= 1;
+  else
+    operands[3] = const1_rtx;
+  operands[2] = copy_to_mode_reg (HImode,
+                                  gen_rtx_CONST_INT (HImode, count));
+
+  /* Load BLKmode MEM addresses into scratch registers.  */
+  operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+  operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
 }")
 
+;; Expand a block move.  We turn this into a move loop.
+(define_insn_and_split "cpymemhi1"
+  [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
+   (match_operand:HI 0 "register_operand" "+r")
+   (match_operand:HI 1 "register_operand" "+r")
+   (match_operand:HI 2 "register_operand" "+r")
+   (match_operand:HI 3 "immediate_operand" "i")
+   (clobber (mem:BLK (scratch)))
+   (clobber (match_dup 0))
+   (clobber (match_dup 1))
+   (clobber (match_dup 2))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
+             (match_dup 0)
+             (match_dup 1)
+             (match_dup 2)
+             (match_dup 3)
+             (clobber (mem:BLK (scratch)))
+             (clobber (match_dup 0))
+             (clobber (match_dup 1))
+             (clobber (match_dup 2))
+             (clobber (reg:CC CC_REGNUM))])]
+  "")
+
+(define_insn "cpymemhi_nocc"
+  [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
+   (match_operand:HI 0 "register_operand" "+r")
+   (match_operand:HI 1 "register_operand" "+r")
+   (match_operand:HI 2 "register_operand" "+r")
+   (match_operand:HI 3 "immediate_operand" "i")
+   (clobber (mem:BLK (scratch)))
+   (clobber (match_dup 0))
+   (clobber (match_dup 1))
+   (clobber (match_dup 2))
+   (clobber (reg:CC CC_REGNUM))]
+  "reload_completed"
+  "*
+{
+  rtx lb[2];
+  
+  lb[0] = operands[2];
+  lb[1] = gen_label_rtx ();
+  
+  output_asm_label (lb[1]);
+  fputs (\":\n\", asm_out_file);
+  if (INTVAL (operands[3]) > 1)
+    output_asm_insn (\"mov\t(%1)+,(%0)+\", operands);
+  else
+    output_asm_insn (\"movb\t(%1)+,(%0)+\", operands);
+  if (TARGET_40_PLUS)
+    output_asm_insn (\"sob\t%0,%l1\", lb);
+  else
+    {
+      output_asm_insn (\"dec\t%0\", lb);
+      output_asm_insn (\"bne\t%l1\", lb);
+    }
+  return \"\";
+}"
+  [(set (attr "length")
+       (if_then_else (match_test "TARGET_40_PLUS")
+                     (const_int 4)
+                     (const_int 6)))])
 \f
 ;;- truncation instructions
 
         emit_move_insn (r, const0_rtx);
         DONE;
       }
-    else if (!rtx_equal_p (operands[0], operands[1]))
+    else if (!REG_P (operands[1]) ||
+             REGNO (operands[0]) != REGNO (operands[1]))
       {
         /* Alternatives 2 and 3 */
         emit_move_insn (operands[0], const0_rtx);
   
   inops[0] = operands[0];
   inops[1] = operands[2];
-  pdp11_expand_operands (inops, exops, 2, NULL, either);
+  pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
   
-  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
+  if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
     output_asm_insn (\"add\t%1,%0\", exops[0]);
-  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
+  if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
   {
     output_asm_insn (\"add\t%1,%0\", exops[1]);
     output_asm_insn (\"adc\t%0\", exops[0]);
   }
-  if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
+  if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
   {
     output_asm_insn (\"add\t%1,%0\", exops[2]);
     output_asm_insn (\"adc\t%0\", exops[1]);
     output_asm_insn (\"adc\t%0\", exops[0]);
   }
-  if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
+  if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
   {
     output_asm_insn (\"add\t%1,%0\", exops[3]);
     output_asm_insn (\"adc\t%0\", exops[2]);
   
   inops[0] = operands[0];
   inops[1] = operands[2];
-  pdp11_expand_operands (inops, exops, 2, NULL, either);
+  pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
   
-  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
+  if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
     output_asm_insn (\"add\t%1,%0\", exops[0]);
-  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
+  if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
   {
     output_asm_insn (\"add\t%1,%0\", exops[1]);
     output_asm_insn (\"adc\t%0\", exops[0]);
 }"
   [(set_attr "length" "2,4,4,6")])
 
+(define_insn_and_split "addqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
+       (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+                (match_operand:QI 2 "incdec_operand" "LM,LM")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0)
+                  (plus:QI (match_dup 1) (match_dup 2)))
+             (clobber (reg:CC CC_REGNUM))])]
+  ""
+  [(set_attr "length" "2,4")])
+
+;; Inc/dec sets V if overflow from the operation
+(define_insn "*addqi3<cc_ccnz>"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
+       (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+                (match_operand:QI 2 "incdec_operand" "LM,LM")))
+   (clobber (reg:CC CC_REGNUM))]
+  "reload_completed"
+  "*
+{
+  if (INTVAL(operands[2]) == 1)
+    return \"incb\t%0\";
+  else
+    return \"decb\t%0\";
+}"
+  [(set_attr "length" "2,4")])
+
 \f
 ;;- subtract instructions
 ;; we don't have to care for constant second 
   
   inops[0] = operands[0];
   inops[1] = operands[2];
-  pdp11_expand_operands (inops, exops, 2, NULL, either);
+  pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
   
-  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
+  if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
     output_asm_insn (\"sub\t%1,%0\", exops[0]);
-  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
+  if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
   {
     output_asm_insn (\"sub\t%1,%0\", exops[1]);
     output_asm_insn (\"sbc\t%0\", exops[0]);
   }
-  if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
+  if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
   {
     output_asm_insn (\"sub\t%1,%0\", exops[2]);
     output_asm_insn (\"sbc\t%0\", exops[1]);
     output_asm_insn (\"sbc\t%0\", exops[0]);
   }
-  if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
+  if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
   {
     output_asm_insn (\"sub\t%1,%0\", exops[3]);
     output_asm_insn (\"sbc\t%0\", exops[2]);
   
   inops[0] = operands[0];
   inops[1] = operands[2];
-  pdp11_expand_operands (inops, exops, 2, NULL, either);
+  pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
   
-  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
+  if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
     output_asm_insn (\"sub\t%1,%0\", exops[0]);
-  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
+  if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
   {
     output_asm_insn (\"sub\t%1,%0\", exops[1]);
     output_asm_insn (\"sbc\t%0\", exops[0]);
 }"
   [(set_attr "length" "2,4,4,6")])
 
+(define_insn_and_split "subqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
+       (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+                (match_operand:QI 2 "incdec_operand" "LM,LM")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0)
+                  (plus:QI (match_dup 1) (match_dup 2)))
+             (clobber (reg:CC CC_REGNUM))])]
+  ""
+  [(set_attr "length" "2,4")])
+
+;; Inc/dec sets V if overflow from the operation
+(define_insn "*subqi3<cc_ccnz>"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
+       (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+                (match_operand:QI 2 "incdec_operand" "LM,LM")))
+   (clobber (reg:CC CC_REGNUM))]
+  "reload_completed"
+  "*
+{
+  if (INTVAL(operands[2]) == -1)
+    return \"incb\t%0\";
+  else
+    return \"decb\t%0\";
+}"
+  [(set_attr "length" "2,4")])
+
 ;;;;- and instructions
 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
 
    (clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   {
+    rtx inops[2];
     rtx exops[4][2];
-    
-    pdp11_expand_operands (operands, exops, 1, NULL, either);
+
+    inops[0] = operands[0];
+    pdp11_expand_operands (inops, exops, 1, 4, NULL, big);
   
     output_asm_insn (\"com\t%0\", exops[3]);
     output_asm_insn (\"com\t%0\", exops[2]);
    (clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   {
-    rtx exops[2][2];
-    
-    pdp11_expand_operands (operands, exops, 1, NULL, either);
+    rtx inops[2];
+    rtx exops[4][2];
+
+    inops[0] = operands[0];
+    pdp11_expand_operands (inops, exops, 1, 2, NULL, big);
   
     output_asm_insn (\"com\t%0\", exops[1]);
     output_asm_insn (\"com\t%0\", exops[0]);
 
 ;; Note that there is no corresponding CC setter pattern.
 ;; The reason is that it won't be generated, because
-;; compare-elim.c only does the transformation on input
+;; compare-elim.cc only does the transformation on input
 ;; insns that have a two-element PARALLEL, as opposed to
 ;; the three-element one we have here.     
 (define_insn "divmodhi4_nocc"
    (clobber (reg:CC CC_REGNUM))]
   ""
   {
+    rtx inops[2];
     rtx exops[2][2];
     rtx t;
-  
-    pdp11_expand_operands (operands, exops, 2, NULL, either);
+
+    inops[0] = operands[0];
+    inops[1] = operands[1];
+    pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
 
     t = exops[0][0];
     exops[0][0] = exops[1][0];