OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [config/] [m68hc11/] [m68hc11.md] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
;;- Machine description file for Motorola 68HC11 and 68HC12.
2
;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
3
;;- Free Software Foundation, Inc.
4
;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
5
 
6
;; This file is part of GCC.
7
 
8
;; GCC is free software; you can redistribute it and/or modify
9
;; it under the terms of the GNU General Public License as published by
10
;; the Free Software Foundation; either version 2, or (at your option)
11
;; any later version.
12
 
13
;; GCC is distributed in the hope that it will be useful,
14
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
;; GNU General Public License for more details.
17
 
18
;; You should have received a copy of the GNU General Public License
19
;; along with GCC; see the file COPYING.  If not, write to
20
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21
;; Boston, MA 02110-1301, USA.
22
 
23
;; Note:
24
;;   A first 68HC11 port was made by Otto Lind (otto@coactive.com)
25
;;   on gcc 2.6.3.  I have used it as a starting point for this port.
26
;;   However, this new port is a complete re-write.  Its internal
27
;;   design is completely different.  The generated code is not
28
;;   compatible with the gcc 2.6.3 port.
29
;;
30
;;   The gcc 2.6.3 port is available at:
31
;;
32
;;   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
33
;;
34
 
35
;;- Instruction patterns.  When multiple patterns apply,
36
;;- the first one in the file is chosen.
37
;;-
38
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
39
;;-
40
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
41
;;- updates for most instructions.
42
 
43
;;
44
;; The following constraints are used:
45
;;
46
;; Single pair registers:
47
;; a    register 'a'                     8-bit
48
;; b    register 'b'                     8-bit
49
;; d    register 'd'                    16-bit
50
;; t    pseudo soft register 'TMP'      16-bit
51
;; v    register 'd' for 68hc11,        16-bit
52
;;      NO_REG for 68hc12
53
;;      (used for scratch register)
54
;; w    register 'sp'                   16-bit
55
;; x    register 'x'                    16-bit
56
;; y    register 'y'                    16-bit
57
;; z    register 'z'                    16-bit  (fake r for 68HC11 and 68HC12)
58
;; D    register 'd+x'                  32-bit
59
;;
60
;; Group of registers:
61
;; q    register 'a' or 'b' or 'd'       8-bit
62
;; u    pseudo soft register            16-bit
63
;; A    register 'x', 'y', 'z'          16-bit
64
;; B    register 'x', 'y'               16-bit
65
;; h    register 'd', 'x', 'y', 'z'     16-bit
66
;;
67
;; Other constraints:
68
;;
69
;; Q    an operand which is in memory but whose address is constant
70
;;      (i.e., a (MEM (SYMBOL_REF x))).  This constraint is used by
71
;;      bset/bclr instructions together with linker relaxation.  The
72
;;      operand can be translated to a page0 addressing mode if the
73
;;      symbol address is in page0 (0..255).
74
;;
75
;; R    an operand which is in memory and whose address is expressed
76
;;      with 68HC11/68HC12 indexed addressing mode.  In general this
77
;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
78
;;
79
;; U    an operand which is in memory and if it uses the 68HC12 indexed
80
;;      addressing mode, the offset is in the range -16..+15.  This is
81
;;      used by 68HC12 movb/movw instructions since they do not accept
82
;;      the full 16-bit offset range (as other insn do).
83
;;
84
;;
85
;; Immediate integer operand constraints:
86
;;   `L' is for range -65536 to 65536
87
;;   `M' is for values whose 16-bit low part is 0
88
;;   'N' is for +1 or -1.
89
;;   'O' is for 16 (for rotate using swap).
90
;;   'P' is for range -8 to 2 (used by addhi_sp)
91
;;
92
;; In many cases, it's not possible to use the 'g' or 'r' constraints.
93
;;
94
;; Operands modifiers:
95
;;
96
;;     %b       Get the low part of the operand (to obtain a QImode)
97
;;              This modifier must always be used for QImode operations
98
;;              because a correction must be applied when the operand
99
;;              is a soft register (ex: *ZD1). Otherwise, we generate
100
;;              *ZD1 and this is the high part of the register. For other
101
;;              kinds of operands, if the operand is already QImode, no
102
;;              additional correction is made.
103
;;     %h       Get the high part of the operand (to obtain a QImode)
104
;;     %t       Represents the temporary/scratch register *_.tmp
105
;;              The scratch register is used in some cases when GCC puts
106
;;              some values in bad registers.
107
;;
108
;; 32/64-bit Patterns:
109
;;     The 68HC11 does not support 32/64-bit operations.  Most of the
110
;;     32/64-bit patterns are defined to split the instruction in
111
;;     16-bits patterns.  Providing split patterns generates better code
112
;;     than letting GCC implement the 32/64-bit operation itself.
113
;;
114
;;
115
;; Notes:
116
;;
117
;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
118
;;   otherwise some insn are not satisfied.
119
;;
120
;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
121
;;   be valid only when z_replacement_completed == 2 because once these
122
;;   swap instructions are generated, a flow/cse pass fails to handle
123
;;   them correctly (it would treat the X, Y or D register as dead sometimes).
124
;;
125
;; o Some split pattern generate instructions that operate on 'a' or 'b'
126
;;   register directly (high part and low part of D respectively).
127
;;   Such split pattern must also be valid when z_replacement_completed == 2
128
;;   because flow/cse is not aware that D is composed of {a, b}.
129
;;
130
;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
131
;;   the high part of a soft register must be expanded after z_replacement
132
;;   pass.
133
;;
134
;;---------------------------------------------------------------------------
135
;; Constants
136
 
137
(define_constants [
138
   ;; Register numbers
139
   (X_REGNUM        0)          ; Index X register
140
   (D_REGNUM        1)          ; Data register
141
   (Y_REGNUM        2)          ; Index Y register
142
   (SP_REGNUM       3)          ; Stack pointer
143
   (PC_REGNUM       4)          ; Program counter
144
   (A_REGNUM        5)          ; A (high part of D)
145
   (B_REGNUM        6)          ; B (low part of D)
146
   (CC_REGNUM       7)          ; Condition code register
147
   (SOFT_TMP_REGNUM 10)         ; TMP soft register
148
   (SOFT_Z_REGNUM   11)         ; Z soft register
149
   (SOFT_XY_REGNUM  12)         ; XY soft register
150
])
151
 
152
(include "predicates.md")
153
 
154
;;--------------------------------------------------------------------
155
;;-  Test
156
;;--------------------------------------------------------------------
157
;;
158
;; The test and compare insn must not accept a memory operand with
159
;; an auto-inc mode.  If we do this, the reload can emit move insns
160
;; after the test or compare.  Such move will set the flags and therefore
161
;; break the comparison.  This can happen if the auto-inc register
162
;; does not happen to be a hard register (i.e., reloading occurs).
163
;; An offsetable memory operand should be ok.  The 'tst_operand' and
164
;; 'cmp_operand' predicates take care of this rule.
165
;;
166
(define_expand "tstsi"
167
  [(set (cc0)
168
        (match_operand:SI 0 "tst_operand" ""))]
169
  ""
170
  "
171
{
172
  m68hc11_compare_op0 = operands[0];
173
  m68hc11_compare_op1 = const0_rtx;
174
  DONE;
175
}")
176
 
177
(define_expand "tsthi"
178
  [(set (cc0)
179
        (match_operand:HI 0 "tst_operand" ""))]
180
  ""
181
  "
182
{
183
  m68hc11_compare_op0 = operands[0];
184
  m68hc11_compare_op1 = const0_rtx;
185
  DONE;
186
}")
187
 
188
(define_insn "tsthi_1"
189
  [(set (cc0)
190
        (match_operand:HI 0 "tst_operand" "dx,*y"))]
191
  ""
192
  "*
193
{
194
   if (D_REG_P (operands[0]) && !TARGET_M6812)
195
     return \"std\\t%t0\";
196
   else
197
     return \"cp%0\\t#0\";
198
}")
199
 
200
(define_expand "tstqi"
201
  [(set (cc0)
202
        (match_operand:QI 0 "tst_operand" ""))]
203
  ""
204
  "
205
{
206
  m68hc11_compare_op0 = operands[0];
207
  m68hc11_compare_op1 = const0_rtx;
208
  DONE;
209
}")
210
 
211
;;
212
;; Split pattern for (tst:QI) on an address register.
213
;;
214
(define_split
215
  [(set (cc0)
216
        (match_operand:QI 0 "hard_addr_reg_operand" ""))]
217
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
218
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
219
              (set (match_dup 1) (reg:HI D_REGNUM))])
220
   (set (cc0) (reg:QI D_REGNUM))
221
   (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
222
              (set (match_dup 1) (reg:HI D_REGNUM))])]
223
  "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
224
 
225
(define_insn "tstqi_1"
226
  [(set (cc0)
227
        (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
228
  ""
229
  "*
230
{
231
  if (A_REG_P (operands[0]))
232
    return \"#\";
233
 
234
  else if (D_REG_P (operands[0]))
235
    return \"tstb\";
236
 
237
  else if (dead_register_here (insn, d_reg))
238
    return \"ldab\\t%b0\";
239
 
240
  else
241
    return \"tst\\t%b0\";
242
}")
243
 
244
;;
245
;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
246
;; during the Z register replacement.  They are used when an operand
247
;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
248
;; In that case, we have to preserve the values of the replacement
249
;; register (as well as the CC0 since the insns are compare insns).
250
;; To do this, the replacement register is pushed on the stack and
251
;; restored after the real compare.  A pattern+split is defined to
252
;; avoid problems with the flow+cse register pass which are made
253
;; after Z register replacement.
254
;;
255
(define_insn_and_split "tstqi_z_used"
256
  [(set (cc0)
257
        (match_operand:QI 0 "tst_operand" "m"))
258
   (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
259
   (use (reg:HI SOFT_Z_REGNUM))]
260
  ""
261
  "#"
262
  "z_replacement_completed == 2"
263
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
264
   (set (match_dup 1) (match_dup 2))
265
   (set (cc0) (match_dup 0))
266
   (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
267
  "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
268
 
269
 
270
;;--------------------------------------------------------------------
271
;;- Compare
272
;;--------------------------------------------------------------------
273
 
274
(define_expand "cmpsi"
275
  [(set (cc0)
276
        (compare (match_operand:SI 0 "tst_operand" "")
277
                 (match_operand:SI 1 "cmp_operand" "")))]
278
  ""
279
  "
280
{
281
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
282
    operands[0] = force_reg (SImode, operands[0]);
283
 
284
  m68hc11_compare_op0 = operands[0];
285
  m68hc11_compare_op1 = operands[1];
286
  DONE;
287
}")
288
 
289
;;
290
;; Comparison of a hard register with another one is provided because
291
;; it helps GCC to avoid to spill a pseudo hard register.
292
;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
293
;; (except that we loose the information that the value is saved in it).
294
;;
295
;; The split pattern transforms the comparison into a save of one hard
296
;; register and a comparison with the temporary.
297
;;
298
(define_split
299
  [(set (cc0)
300
        (compare (match_operand:HI 0 "hard_reg_operand" "")
301
                 (match_operand:HI 1 "hard_reg_operand" "")))]
302
  "TARGET_M6811
303
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
304
  [(set (match_dup 2) (match_dup 1))
305
   (set (cc0)
306
        (compare (match_dup 0) (match_dup 2)))]
307
  "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
308
 
309
(define_split
310
  [(set (cc0)
311
        (compare (match_operand:HI 0 "hard_reg_operand" "")
312
                 (match_operand:HI 1 "hard_reg_operand" "")))]
313
  "0 && TARGET_M6812
314
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
315
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
316
   (set (cc0)
317
        (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
318
  "")
319
 
320
(define_expand "cmphi"
321
  [(set (cc0)
322
        (compare (match_operand:HI 0 "tst_operand" "")
323
                 (match_operand:HI 1 "cmp_operand" "")))]
324
  ""
325
  "
326
{
327
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
328
    operands[0] = force_reg (HImode, operands[0]);
329
 
330
  m68hc11_compare_op0 = operands[0];
331
  m68hc11_compare_op1 = operands[1];
332
  DONE;
333
}")
334
 
335
(define_insn "cmphi_1_hc12"
336
  [(set (cc0)
337
        (compare (match_operand:HI 0 "tst_operand"
338
                                "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
339
                 (match_operand:HI 1 "general_operand"
340
                                "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
341
  "TARGET_M6812"
342
  "*
343
{
344
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
345
    {
346
      cc_status.flags |= CC_REVERSED;
347
      return \"cp%1\\t%0\";
348
    }
349
  else if (SP_REG_P (operands[1]))
350
    return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
351
  else if (H_REG_P (operands[1]))
352
    return \"psh%1\n\\tcp%0\\t2,sp+\";
353
  else
354
    return \"cp%0\\t%1\";
355
}")
356
 
357
(define_insn "cmphi_1_hc11"
358
  [(set (cc0)
359
        (compare (match_operand:HI 0 "tst_operand"
360
                                "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
361
                 (match_operand:HI 1 "cmp_operand"
362
                                "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
363
  "TARGET_M6811"
364
  "*
365
{
366
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
367
    {
368
      cc_status.flags |= CC_REVERSED;
369
      return \"cp%1\\t%0\";
370
    }
371
  else if (H_REG_P (operands[1]))
372
    return \"#\";
373
  else
374
    return \"cp%0\\t%1\";
375
}")
376
 
377
(define_insn_and_split "cmphi_z_used"
378
  [(set (cc0)
379
        (compare (match_operand:HI 0 "tst_operand" "dxy,m")
380
                 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
381
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
382
   (use (reg:HI SOFT_Z_REGNUM))]
383
  ""
384
  "#"
385
  "z_replacement_completed == 2"
386
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
387
   (set (match_dup 2) (match_dup 3))
388
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
389
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
390
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
391
 
392
;;
393
;; 8-bit comparison with address register.
394
;; There is no such comparison instruction, we have to temporarily switch
395
;; the address register and the D register and do the comparison with D.
396
;; The xgdx and xgdy instructions preserve the flags.
397
;;
398
(define_split
399
  [(set (cc0)
400
        (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
401
                 (match_operand:QI 1 "cmp_operand" "")))]
402
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
403
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
404
              (set (match_dup 3) (reg:HI D_REGNUM))])
405
   (set (cc0)
406
        (compare (reg:QI D_REGNUM) (match_dup 1)))
407
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
408
              (set (match_dup 3) (reg:HI D_REGNUM))])]
409
  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
410
 
411
(define_split
412
  [(set (cc0)
413
        (compare (match_operand:QI 0 "hard_reg_operand" "")
414
                 (match_operand:QI 1 "hard_reg_operand" "")))]
415
  "reload_completed"
416
  [(set (match_dup 3) (match_dup 4))
417
   (set (cc0)
418
        (compare (match_dup 0) (match_dup 2)))]
419
  "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
420
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
421
   operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
422
 
423
(define_expand "cmpqi"
424
  [(set (cc0)
425
        (compare (match_operand:QI 0 "tst_operand" "")
426
                 (match_operand:QI 1 "cmp_operand" "")))]
427
  ""
428
  "
429
{
430
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
431
    operands[0] = force_reg (QImode, operands[0]);
432
 
433
  m68hc11_compare_op0 = operands[0];
434
  m68hc11_compare_op1 = operands[1];
435
  DONE;
436
}")
437
 
438
(define_insn "bitcmpqi"
439
  [(set (cc0)
440
        (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
441
                (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
442
  ""
443
  "@
444
   bitb\\t%b1
445
   #
446
   bitb\\t%b1
447
   bitb\\t%b0
448
   bitb\\t%b0")
449
 
450
(define_split /* "bitcmpqi" */
451
  [(set (cc0)
452
        (and:QI (match_operand:QI 0 "tst_operand" "")
453
                (match_operand:QI 1 "hard_addr_reg_operand" "")))]
454
  "z_replacement_completed == 2"
455
  [(set (match_dup 3) (match_dup 2))
456
   (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
457
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
458
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
459
   operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
460
 
461
(define_insn_and_split "bitcmpqi_z_used"
462
  [(set (cc0)
463
        (and:QI (match_operand:QI 0 "tst_operand" "d,m")
464
                (match_operand:QI 1 "cmp_operand" "m,d")))
465
   (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
466
   (use (reg:HI SOFT_Z_REGNUM))]
467
  ""
468
  "#"
469
  "z_replacement_completed == 2"
470
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
471
   (set (match_dup 2) (match_dup 3))
472
   (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
473
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
474
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
475
 
476
(define_insn "bitcmphi"
477
  [(set (cc0)
478
        (and:HI (match_operand:HI 0 "tst_operand" "d")
479
                (match_operand:HI 1 "const_int_operand" "i")))]
480
  "(INTVAL (operands[1]) & 0x0ff) == 0
481
   || (INTVAL (operands[1]) & 0x0ff00) == 0"
482
  "*
483
{
484
   if ((INTVAL (operands[1]) & 0x0ff) == 0)
485
     return \"bita\\t%h1\";
486
   else
487
     return \"bitb\\t%1\";
488
}")
489
 
490
(define_insn "bitcmpqi_12"
491
  [(set (cc0)
492
        (zero_extract (match_operand:HI 0 "tst_operand" "d")
493
                      (match_operand:HI 1 "const_int_operand" "i")
494
                      (match_operand:HI 2 "const_int_operand" "i")))]
495
  "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
496
   || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
497
       && (unsigned) INTVAL (operands[2]) >= 8)"
498
  "*
499
{
500
   rtx ops[1];
501
   int mask;
502
   int startpos = INTVAL (operands[2]);
503
   int bitsize = INTVAL (operands[1]);
504
 
505
   if (startpos >= 8)
506
     {
507
       startpos -= 8;
508
       mask = (1 << (startpos + bitsize)) - 1;
509
       mask &= ~((1 << startpos) - 1);
510
 
511
       ops[0] = GEN_INT (mask);
512
       output_asm_insn (\"bita\\t%0\", ops);
513
     }
514
   else
515
     {
516
       mask = (1 << (startpos + bitsize)) - 1;
517
       mask &= ~((1 << startpos) - 1);
518
 
519
       ops[0] = GEN_INT (mask);
520
       output_asm_insn (\"bitb\\t%0\", ops);
521
     }
522
   return \"\";
523
}")
524
 
525
(define_insn "cmpqi_1"
526
  [(set (cc0)
527
        (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
528
                 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
529
  ""
530
  "*
531
{
532
   if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
533
     {
534
        return \"#\";
535
     }
536
   else if (D_REG_P (operands[0]))
537
     {
538
        return \"cmpb\\t%b1\";
539
     }
540
   cc_status.flags |= CC_REVERSED;
541
   return \"cmpb\\t%b0\";
542
}")
543
 
544
(define_insn_and_split "cmpqi_z_used"
545
  [(set (cc0)
546
        (compare (match_operand:QI 0 "tst_operand" "dxy,m")
547
                 (match_operand:QI 1 "cmp_operand" "m,dxy")))
548
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
549
   (use (reg:HI SOFT_Z_REGNUM))]
550
  ""
551
  "#"
552
  "z_replacement_completed == 2"
553
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
554
   (set (match_dup 2) (match_dup 3))
555
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
556
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
557
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
558
 
559
;;--------------------------------------------------------------------
560
;;-  Move strict_low_part
561
;;--------------------------------------------------------------------
562
;;
563
;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
564
;; The replacement must be made at the very end because we loose the
565
;; (strict_low_part ...) information.  This is correct for our machine
566
;; description but not for GCC optimization passes.
567
;;
568
(define_insn_and_split "movstrictsi"
569
  [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
570
        (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
571
  ""
572
  "#"
573
  "z_replacement_completed == 2"
574
  [(set (match_dup 0) (match_dup 1))]
575
  "")
576
 
577
(define_insn_and_split "movstricthi"
578
  [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
579
        (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
580
  ""
581
  "#"
582
  "z_replacement_completed == 2"
583
  [(set (match_dup 0) (match_dup 1))]
584
  "")
585
 
586
(define_insn_and_split "movstrictqi"
587
  [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
588
        (match_operand:QI 1 "general_operand" "d,imudA"))]
589
  ""
590
  "#"
591
  "z_replacement_completed == 2"
592
  [(set (match_dup 0) (match_dup 1))]
593
  "")
594
 
595
;;--------------------------------------------------------------------
596
;;- 64-bit Move Operations.
597
;; The movdi and movdf patterns are identical except for the mode.
598
;; They are also very similar to those for movsi and movsf.
599
;;
600
;; For 68HC11, we need a scratch register (either D, X, Y)
601
;; because there is no memory->memory moves.  It must be defined with
602
;; earlyclobber (&) so that it does not appear in the source or destination
603
;; address.  Providing patterns for movdi/movdf allows GCC to generate
604
;; better code.  [Until now, the scratch register is limited to D because
605
;; otherwise we can run out of registers in the A_REGS class for reload].
606
;;
607
;; For 68HC12, the scratch register is not necessary.  To use the same
608
;; pattern and same split, we use the 'v' constraint.  This tells the
609
;; reload to use the _.tmp register (which is not used at all).
610
;; The insn will be split in one or several memory moves (movw).
611
;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
612
;;--------------------------------------------------------------------
613
(define_expand "movdi"
614
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
615
                   (match_operand:DI 1 "general_operand" ""))
616
              (clobber (match_scratch:HI 2 ""))])]
617
  ""
618
  "
619
  /* For push/pop, emit a REG_INC note to make sure the reload
620
     inheritance and reload CSE pass notice the change of the stack
621
     pointer.  */
622
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
623
    {
624
      rtx insn;
625
 
626
      insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
627
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
628
                                          stack_pointer_rtx,
629
                                          REG_NOTES (insn));
630
      DONE;
631
    }
632
")
633
 
634
;; Separate push from normal moves to avoid reloading problems
635
;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
636
;; We can also accept more scratch registers.
637
(define_insn_and_split "*pushdi_internal"
638
  [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
639
        (match_operand:DI 1 "general_operand" "i,U,m,!u"))
640
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
641
  ""
642
  "#"
643
  "reload_completed"
644
  [(const_int 0)]
645
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
646
   DONE;")
647
 
648
(define_insn_and_split "movdi_internal"
649
  [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
650
        (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
651
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
652
  ""
653
  "#"
654
  "reload_completed"
655
  [(const_int 0)]
656
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
657
   DONE;")
658
 
659
(define_expand "movdf"
660
  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
661
                   (match_operand:DF 1 "general_operand" ""))
662
              (clobber (match_scratch:HI 2 ""))])]
663
  ""
664
  "/* For push/pop, emit a REG_INC note to make sure the reload
665
      inheritance and reload CSE pass notice the change of the stack
666
      pointer.  */
667
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
668
    {
669
      rtx insn;
670
 
671
      insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
672
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
673
                                          stack_pointer_rtx,
674
                                          REG_NOTES (insn));
675
      DONE;
676
    }
677
")
678
 
679
;; See pushdi_internal
680
(define_insn_and_split "*pushdf_internal"
681
  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
682
        (match_operand:DF 1 "general_operand" "i,U,m,!u"))
683
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
684
  ""
685
  "#"
686
  "reload_completed"
687
  [(const_int 0)]
688
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
689
   DONE;")
690
 
691
(define_insn_and_split "movdf_internal"
692
  [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
693
        (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
694
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
695
  ""
696
  "#"
697
  "reload_completed"
698
  [(const_int 0)]
699
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
700
   DONE;")
701
 
702
;;--------------------------------------------------------------------
703
;;- 32-bit Move Operations.
704
;; The movsi and movsf patterns are identical except for the mode.
705
;; When we move to/from a hard register (d+x), we don't need a scratch.
706
;; Otherwise, a scratch register is used as intermediate register for
707
;; the move.  The '&' constraint is necessary to make sure the reload
708
;; pass does not give us a register that dies in the insn and is used
709
;; for input/output operands.
710
;;--------------------------------------------------------------------
711
(define_expand "movsi"
712
  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
713
                   (match_operand:SI 1 "general_operand" ""))
714
              (clobber (match_scratch:HI 2 ""))])]
715
  ""
716
  "/* For push/pop, emit a REG_INC note to make sure the reload
717
      inheritance and reload CSE pass notice the change of the stack
718
      pointer.  */
719
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
720
    {
721
      rtx insn;
722
 
723
      insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
724
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
725
                                          stack_pointer_rtx,
726
                                          REG_NOTES (insn));
727
      DONE;
728
    }
729
")
730
 
731
(define_insn_and_split "*pushsi_internal"
732
  [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
733
        (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
734
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
735
  ""
736
  "#"
737
  "reload_completed"
738
  [(const_int 0)]
739
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
740
   DONE;")
741
 
742
(define_insn_and_split "movsi_internal"
743
  [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
744
        (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
745
   (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
746
  ""
747
  "#"
748
  "reload_completed"
749
  [(const_int 0)]
750
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
751
   DONE;")
752
 
753
(define_expand "movsf"
754
  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
755
                   (match_operand:SF 1 "general_operand" ""))
756
              (clobber (match_scratch:HI 2 ""))])]
757
  ""
758
  "/* For push/pop, emit a REG_INC note to make sure the reload
759
      inheritance and reload CSE pass notice the change of the stack
760
      pointer.  */
761
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
762
    {
763
      rtx insn;
764
 
765
      insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
766
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
767
                                          stack_pointer_rtx,
768
                                          REG_NOTES (insn));
769
      DONE;
770
    }
771
")
772
 
773
(define_insn_and_split "*pushsf_internal"
774
  [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
775
        (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
776
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
777
  ""
778
  "#"
779
  "reload_completed"
780
  [(const_int 0)]
781
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
782
   DONE;")
783
 
784
(define_insn_and_split "movsf_internal"
785
  [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
786
        (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
787
   (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
788
  ""
789
  "#"
790
  "reload_completed"
791
  [(const_int 0)]
792
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
793
   DONE;")
794
 
795
 
796
;;--------------------------------------------------------------------
797
;;- 16-bit Move Operations.
798
;; We don't need a scratch register.
799
;;--------------------------------------------------------------------
800
 
801
(define_insn "*movhi2_push"
802
  [(set (match_operand:HI 0 "push_operand" "=<,<,<")
803
        (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
804
  "TARGET_M6811 && !TARGET_M6812"
805
  "*
806
{
807
  cc_status = cc_prev_status;
808
  if (D_REG_P (operands[1]))
809
    {
810
      output_asm_insn (\"pshb\", operands);
811
      return \"psha\";
812
    }
813
  else if (X_REG_P (operands[1]))
814
    {
815
      return \"pshx\";
816
    }
817
  else if (Y_REG_P (operands[1]))
818
    {
819
      return \"pshy\";
820
    }
821
  fatal_insn (\"Invalid register in the instruction\", insn);
822
}")
823
 
824
(define_insn "*movhi2_pop"
825
  [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
826
        (match_operand:HI 1 "pop_operand" ">,>"))]
827
  "TARGET_M6811"
828
  "*
829
{
830
  cc_status = cc_prev_status;
831
  if (D_REG_P (operands[0]))
832
    {
833
      output_asm_insn (\"pula\", operands);
834
      return \"pulb\";
835
    }
836
  else if (X_REG_P (operands[0]))
837
    {
838
      return \"pulx\";
839
    }
840
  else if (Y_REG_P (operands[0]))
841
    {
842
      return \"puly\";
843
    }
844
  fatal_insn (\"Invalid register in the instruction\", insn);
845
}")
846
 
847
(define_expand "movhi"
848
  [(set (match_operand:HI 0 "nonimmediate_operand" "")
849
        (match_operand:HI 1 "general_operand" ""))]
850
  ""
851
  "
852
{
853
  if (reload_in_progress)
854
    {
855
      if (m68hc11_reload_operands (operands))
856
        {
857
          DONE;
858
        }
859
    }
860
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
861
    {
862
      if (GET_CODE (operands[0]) == MEM &&
863
          (GET_CODE (operands[1]) == MEM
864
           || GET_CODE (operands[1]) == CONST_INT))
865
        {
866
          operands[1] = force_reg (HImode, operands[1]);
867
        }
868
      else if (IS_STACK_PUSH (operands[0])
869
               && GET_CODE (operands[1]) != REG)
870
        {
871
          operands[1] = force_reg (HImode, operands[1]);
872
        }
873
    }
874
  /* For push/pop, emit a REG_INC note to make sure the reload
875
     inheritance and reload CSE pass notice the change of the stack
876
     pointer.  */
877
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
878
    {
879
      rtx insn;
880
 
881
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
882
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
883
                                          stack_pointer_rtx,
884
                                          REG_NOTES (insn));
885
      DONE;
886
    }
887
}")
888
 
889
(define_insn "*movhi_68hc12"
890
  [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
891
        (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
892
  "TARGET_M6812"
893
  "*
894
{
895
  m68hc11_gen_movhi (insn, operands);
896
  return \"\";
897
}")
898
 
899
(define_insn "movhi_const0"
900
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
901
        (const_int 0))]
902
  "TARGET_M6811"
903
  "@
904
   clra\\n\\tclrb
905
   ld%0\\t#0
906
   clr\\t%b0\\n\\tclr\\t%h0")
907
 
908
(define_insn "*movhi_m68hc11"
909
  [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
910
        (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
911
  "TARGET_M6811"
912
  "*
913
{
914
  m68hc11_gen_movhi (insn, operands);
915
  return \"\";
916
}")
917
 
918
;;--------------------------------------------------------------------
919
;;- 8-bit Move Operations.
920
;; We don't need a scratch register.
921
;;--------------------------------------------------------------------
922
;;
923
;; The *a alternative also clears the high part of the register.
924
;; This should be ok since this is not the (strict_low_part) set.
925
;;
926
(define_insn "movqi_const0"
927
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
928
        (const_int 0))]
929
  ""
930
  "@
931
   clrb
932
   clr\\t%b0
933
   clr\\t%b0
934
   ld%0\\t#0
935
   clr%0")
936
 
937
;;
938
;; 8-bit operations on address registers.
939
;;
940
;; Switch temporary to the D register and load the value in B.
941
;; This is possible as long as the address register does not
942
;; appear in the source operand.
943
;;
944
(define_split
945
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
946
        (match_operand:QI 1 "general_operand" ""))]
947
  "z_replacement_completed == 2
948
   && !reg_mentioned_p (operands[0], operands[1])
949
   && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
950
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
951
              (set (match_dup 2) (reg:HI D_REGNUM))])
952
   (set (reg:QI D_REGNUM) (match_dup 1))
953
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
954
              (set (match_dup 2) (reg:HI D_REGNUM))])]
955
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
956
 
957
;;
958
;; 8-bit operations on address registers.
959
;;
960
(define_split
961
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
962
        (match_operand:QI 1 "hard_addr_reg_operand" ""))]
963
  "z_replacement_completed == 2
964
   && !reg_mentioned_p (operands[1], operands[0])
965
   && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
966
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
967
              (set (match_dup 2) (reg:HI D_REGNUM))])
968
   (set (match_dup 0) (reg:QI D_REGNUM))
969
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
970
              (set (match_dup 2) (reg:HI D_REGNUM))])]
971
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
972
 
973
(define_insn "*movqi2_push"
974
  [(set (match_operand:QI 0 "push_operand" "=<,<")
975
        (match_operand:QI 1 "general_operand" "d,!*A"))]
976
  ""
977
  "*
978
{
979
  if (A_REG_P (operands[1]))
980
    return \"#\";
981
 
982
  cc_status = cc_prev_status;
983
  return \"pshb\";
984
}")
985
 
986
 
987
(define_expand "movqi"
988
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
989
        (match_operand:QI 1 "general_operand" ""))]
990
  ""
991
  "
992
{
993
  if (reload_in_progress)
994
    {
995
      if (m68hc11_reload_operands (operands))
996
        {
997
          DONE;
998
        }
999
    }
1000
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1001
    {
1002
      if (GET_CODE (operands[0]) == MEM
1003
          && (GET_CODE (operands[1]) == MEM
1004
              || GET_CODE (operands[1]) == CONST_INT))
1005
        {
1006
          operands[1] = force_reg (QImode, operands[1]);
1007
        }
1008
      else if (IS_STACK_PUSH (operands[0])
1009
               && GET_CODE (operands[1]) != REG)
1010
        {
1011
          operands[1] = force_reg (QImode, operands[1]);
1012
        }
1013
    }
1014
  /* For push/pop, emit a REG_INC note to make sure the reload
1015
     inheritance and reload CSE pass notice the change of the stack
1016
     pointer.  */
1017
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1018
    {
1019
      rtx insn;
1020
 
1021
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1022
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1023
                                          stack_pointer_rtx,
1024
                                          REG_NOTES (insn));
1025
      DONE;
1026
    }
1027
}")
1028
 
1029
(define_insn "*movqi_68hc12"
1030
  [(set (match_operand:QI 0 "nonimmediate_operand"
1031
                                "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1032
        (match_operand:QI 1 "general_operand"
1033
                                "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1034
  "TARGET_M6812"
1035
  "*
1036
{
1037
  m68hc11_gen_movqi (insn, operands);
1038
  return \"\";
1039
}")
1040
 
1041
(define_insn "*movqi_m68hc11"
1042
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1043
        (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1044
  "TARGET_M6811"
1045
  "*
1046
{
1047
  m68hc11_gen_movqi (insn, operands);
1048
  return \"\";
1049
}")
1050
 
1051
;;--------------------------------------------------------------------
1052
;;-  Swap registers
1053
;;--------------------------------------------------------------------
1054
;; Swapping registers is used for split patterns.
1055
(define_insn "swap_areg"
1056
   [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1057
         (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1058
    (set (match_dup 1) (match_dup 0))]
1059
   ""
1060
   "*
1061
{
1062
  m68hc11_output_swap (insn, operands);
1063
  return \"\";
1064
}")
1065
 
1066
;;--------------------------------------------------------------------
1067
;;-  Truncation insns.
1068
;;--------------------------------------------------------------------
1069
;;
1070
;; Truncation are not necessary because GCC knows how to truncate,
1071
;; specially when values lie in consecutive registers.
1072
;;
1073
 
1074
(define_expand "floatunssisf2"
1075
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
1076
        (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1077
  ""
1078
  "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1079
                         SFmode, SImode, 2, operands);
1080
   DONE;")
1081
 
1082
(define_expand "floatunssidf2"
1083
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
1084
        (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1085
  ""
1086
  "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1087
                         DFmode, SImode, 2, operands);
1088
   DONE;")
1089
 
1090
;;--------------------------------------------------------------------
1091
;;-  Zero extension insns.
1092
;;--------------------------------------------------------------------
1093
 
1094
;;
1095
;; 64-bit extend.  The insn will be split into 16-bit instructions just
1096
;; before the final pass.  We need a scratch register for the split.
1097
;; The final value can be generated on the stack directly.  This is more
1098
;; efficient and useful for conversions made during parameter passing rules.
1099
;;
1100
(define_insn "zero_extendqidi2"
1101
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1102
        (zero_extend:DI
1103
           (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1104
   (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1105
  ""
1106
  "#")
1107
 
1108
(define_split
1109
  [(set (match_operand:DI 0 "push_operand" "")
1110
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1111
   (clobber (match_scratch:HI 2 "=&dB"))]
1112
  "z_replacement_completed == 2"
1113
  [(const_int 0)]
1114
  "
1115
{
1116
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1117
  rtx push = m68hc11_gen_lowpart (HImode, low);
1118
  rtx src  = operands[1];
1119
 
1120
   /* Source operand must be in a hard register.  */
1121
   if (!H_REG_P (src))
1122
     {
1123
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
1124
       emit_move_insn (src, operands[1]);
1125
     }
1126
 
1127
   /* Source is in D, we can push B then one word of 0 and we do
1128
      a correction on the stack pointer.  */
1129
   if (D_REG_P (src))
1130
     {
1131
       emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1132
       emit_move_insn (operands[2], const0_rtx);
1133
       if (D_REG_P (operands[2]))
1134
         {
1135
           emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1136
         }
1137
       else
1138
         {
1139
           emit_move_insn (push, operands[2]);
1140
           emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1141
                                  gen_rtx_REG (HImode, HARD_SP_REGNUM),
1142
                                  const1_rtx));
1143
         }
1144
     }
1145
   else
1146
     {
1147
       /* Source is in X or Y.  It's better to push the 16-bit register
1148
          and then to some stack adjustment.  */
1149
       src = gen_rtx_REG (HImode, REGNO (src));
1150
       emit_move_insn (push, src);
1151
       emit_move_insn (operands[2], const0_rtx);
1152
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1153
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
1154
                              const1_rtx));
1155
       emit_move_insn (push, operands[2]);
1156
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1157
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
1158
                              const1_rtx));
1159
     }
1160
   emit_move_insn (push, operands[2]);
1161
   emit_move_insn (push, operands[2]);
1162
   emit_move_insn (push, operands[2]);
1163
   DONE;
1164
}")
1165
 
1166
(define_split
1167
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1168
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1169
   (clobber (match_scratch:HI 2 "=&dB"))]
1170
  "z_replacement_completed == 2"
1171
  [(const_int 0)]
1172
  "
1173
{
1174
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1175
  rtx low2 = m68hc11_gen_lowpart (HImode, low);
1176
  rtx src  = operands[1];
1177
 
1178
   /* Source operand must be in a hard register.  */
1179
   if (!H_REG_P (src))
1180
     {
1181
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
1182
       emit_move_insn (src, operands[1]);
1183
     }
1184
 
1185
   emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1186
   emit_move_insn (operands[2], const0_rtx);
1187
   src = gen_rtx_REG (QImode, REGNO (operands[2]));
1188
   emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1189
 
1190
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1191
   low = m68hc11_gen_highpart (SImode, operands[0]);
1192
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1193
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1194
   DONE;
1195
}")
1196
 
1197
(define_insn "zero_extendhidi2"
1198
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1199
        (zero_extend:DI
1200
            (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1201
   (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1202
  ""
1203
  "#")
1204
 
1205
(define_split
1206
  [(set (match_operand:DI 0 "non_push_operand" "")
1207
        (zero_extend:DI
1208
            (match_operand:HI 1 "nonimmediate_operand" "")))
1209
   (clobber (match_scratch:HI 2 ""))]
1210
  "z_replacement_completed == 2"
1211
  [(const_int 0)]
1212
  "
1213
{
1214
   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1215
   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1216
   rtx src  = operands[1];
1217
 
1218
   /* Make sure the source is in a hard register.  */
1219
   if (!H_REG_P (src))
1220
     {
1221
       src = operands[2];
1222
       emit_move_insn (src, operands[1]);
1223
     }
1224
 
1225
   /* Move the low part first for the push.  */
1226
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1227
 
1228
   /* Now, use the scratch register to fill in the zeros.  */
1229
   emit_move_insn (operands[2], const0_rtx);
1230
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1231
   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1232
   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1233
   DONE;
1234
}")
1235
 
1236
(define_insn "zero_extendsidi2"
1237
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1238
        (zero_extend:DI
1239
            (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1240
   (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1241
  ""
1242
  "#")
1243
 
1244
(define_split
1245
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1246
        (zero_extend:DI
1247
            (match_operand:SI 1 "nonimmediate_operand" "")))
1248
   (clobber (match_scratch:HI 2 ""))]
1249
  "z_replacement_completed == 2"
1250
  [(const_int 0)]
1251
  "
1252
{
1253
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1254
  rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1255
 
1256
  /* Move the low part first so that this is ok for a push.  */
1257
  m68hc11_split_move (low, operands[1], operands[2]);
1258
 
1259
  /* Use the scratch register to clear the high part of the destination.  */
1260
  emit_move_insn (operands[2], const0_rtx);
1261
  emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1262
  emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1263
  DONE;
1264
}")
1265
 
1266
;;
1267
;; For 16->32bit unsigned extension, we don't allow generation on the stack
1268
;; because it's less efficient.
1269
;;
1270
(define_insn "zero_extendhisi2"
1271
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1272
        (zero_extend:SI
1273
            (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1274
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1275
  ""
1276
  "#")
1277
 
1278
(define_split
1279
  [(set (match_operand:SI 0 "non_push_operand" "")
1280
        (zero_extend:SI
1281
            (match_operand:HI 1 "nonimmediate_operand" "")))
1282
   (clobber (match_scratch:HI 2 ""))]
1283
  "reload_completed"
1284
  [(const_int 0)]
1285
  "
1286
{
1287
  rtx src = operands[1];
1288
 
1289
  if (!H_REG_P (src) && !H_REG_P (operands[0]))
1290
    {
1291
      src = operands[2];
1292
      emit_move_insn (src, operands[1]);
1293
    }
1294
  emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1295
  emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1296
  DONE;
1297
}")
1298
 
1299
(define_insn "zero_extendqisi2"
1300
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1301
      (zero_extend:SI
1302
          (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1303
  ""
1304
  "#")
1305
 
1306
(define_split
1307
  [(set (match_operand:SI 0 "non_push_operand" "")
1308
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1309
  "reload_completed && !X_REG_P (operands[0])"
1310
  [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1311
   (set (match_dup 3) (const_int 0))]
1312
  "
1313
   operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1314
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1315
 
1316
(define_split
1317
  [(set (match_operand:SI 0 "hard_reg_operand" "")
1318
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1319
  "z_replacement_completed == 2 && X_REG_P (operands[0])"
1320
  [(set (match_dup 2) (match_dup 3))
1321
   (set (match_dup 4) (const_int 0))
1322
   (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1323
  "
1324
   if (X_REG_P (operands[1]))
1325
     {
1326
        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1327
                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
1328
        emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1329
                                         gen_rtx_REG (QImode, HARD_D_REGNUM)));
1330
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1331
                        const0_rtx);
1332
        DONE;
1333
     }
1334
 
1335
   if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1336
     {
1337
        emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1338
                                                              operands[0]),
1339
                                         operands[1]));
1340
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1341
        DONE;
1342
     }
1343
   operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1344
   operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1345
   if (A_REG_P (operands[1]))
1346
     {
1347
       operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1348
       operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1349
       operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1350
     }
1351
   else
1352
     {
1353
       operands[5] = operands[2] =
1354
       operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1355
       operands[6] = operands[1];
1356
     }
1357
")
1358
 
1359
(define_insn "zero_extendqihi2"
1360
  [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1361
        (zero_extend:HI
1362
            (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1363
  ""
1364
 "*
1365
{
1366
  if (A_REG_P (operands[0]))
1367
    return \"#\";
1368
 
1369
  if (H_REG_P (operands[0]))
1370
    {
1371
      output_asm_insn (\"clra\", operands);
1372
      if (operands[0] != operands[1]
1373
          && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1374
        {
1375
          if (X_REG_P (operands[1])
1376
              || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1377
            {
1378
              output_asm_insn (\"stx\\t%t1\", operands);
1379
              output_asm_insn (\"ldab\\t%T0\", operands);
1380
            }
1381
          else if (Y_REG_P (operands[1])
1382
                   || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1383
            {
1384
              output_asm_insn (\"sty\\t%t1\", operands);
1385
              output_asm_insn (\"ldab\\t%T0\", operands);
1386
            }
1387
          else
1388
            {
1389
              output_asm_insn (\"ldab\\t%b1\", operands);
1390
            }
1391
          cc_status.flags |= CC_NOT_NEGATIVE;
1392
        }
1393
      else
1394
        {
1395
          /* Status refers to the clra insn. Status is ok for others
1396
           * since we have loaded the value in B.
1397
           */
1398
          CC_STATUS_INIT;
1399
        }
1400
      return \"\";
1401
    }
1402
 
1403
  if (A_REG_P (operands[1]))
1404
    {
1405
      output_asm_insn (\"st%1\\t%0\", operands);
1406
      output_asm_insn (\"clr\\t%h0\", operands);
1407
      CC_STATUS_INIT;
1408
    }
1409
  else
1410
    {
1411
      output_asm_insn (\"clr\\t%h0\", operands);
1412
      output_asm_insn (\"stab\\t%b0\", operands);
1413
      cc_status.flags |= CC_NOT_NEGATIVE;
1414
    }
1415
 
1416
  return \"\";
1417
}")
1418
 
1419
 
1420
;;--------------------------------------------------------------------
1421
;;-  Sign extension insns.
1422
;;--------------------------------------------------------------------
1423
 
1424
(define_insn "extendqisi2"
1425
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1426
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1427
  ""
1428
  "*
1429
{
1430
  rtx ops[3];
1431
  int need_tst = 0;
1432
 
1433
  /* The 68HC12 has a sign-extension instruction.  Use it when the
1434
     destination is the register (X,D).  First sign-extend the low
1435
     part and fill X with the sign-extension of the high part.  */
1436
  if (TARGET_M6812 && X_REG_P (operands[0]))
1437
    {
1438
      if (!D_REG_P (operands[1]))
1439
        {
1440
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1441
          ops[1] = operands[1];
1442
          m68hc11_gen_movqi (insn, ops);
1443
        }
1444
      return \"sex\\tb,d\\n\\tsex\\ta,x\";
1445
    }
1446
 
1447
  ops[2] = gen_label_rtx ();
1448
 
1449
  if (X_REG_P (operands[1]))
1450
    {
1451
      output_asm_insn (\"xgdx\", operands);
1452
      need_tst = 1;
1453
    }
1454
  else if (X_REG_P (operands[0]))
1455
    {
1456
      /* X can be used as an indexed addressing in the source.
1457
         Get the value before clearing it.  */
1458
      if (reg_mentioned_p (ix_reg, operands[1]))
1459
        {
1460
          output_asm_insn (\"ldab\\t%b1\", operands);
1461
          need_tst = 1;
1462
        }
1463
      output_asm_insn (\"ldx\\t#0\", operands);
1464
    }
1465
 
1466
  output_asm_insn (\"clra\", operands);
1467
  if (!X_REG_P (operands[0]))
1468
    {
1469
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1470
      ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1471
 
1472
      if (IS_STACK_PUSH (operands[0]))
1473
        {
1474
          output_asm_insn (\"pshb\", ops);
1475
          output_asm_insn (\"tstb\", ops);
1476
        }
1477
      else
1478
        {
1479
          output_asm_insn (\"stab\\t%b1\", ops);
1480
        }
1481
    }
1482
  else if (D_REG_P (operands[1]) || need_tst)
1483
    {
1484
      output_asm_insn (\"tstb\", operands);
1485
    }
1486
  else
1487
    {
1488
      output_asm_insn (\"ldab\\t%b1\", operands);
1489
    }
1490
  output_asm_insn (\"bpl\\t%l2\", ops);
1491
  output_asm_insn (\"deca\", operands);
1492
  if (X_REG_P (operands[0]))
1493
    output_asm_insn (\"dex\", operands);
1494
 
1495
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1496
 
1497
  if (!X_REG_P (operands[0]))
1498
    {
1499
      if (IS_STACK_PUSH (operands[0]))
1500
        {
1501
          output_asm_insn (\"psha\", ops);
1502
          output_asm_insn (\"psha\", ops);
1503
          output_asm_insn (\"psha\", ops);
1504
        }
1505
      else
1506
        {
1507
          output_asm_insn (\"staa\\t%h0\", ops);
1508
 
1509
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1510
          if (dead_register_here (insn, d_reg))
1511
            {
1512
              output_asm_insn (\"tab\", ops);
1513
              output_asm_insn (\"std\\t%0\", ops);
1514
            }
1515
          else
1516
            {
1517
              output_asm_insn (\"staa\\t%b0\", ops);
1518
              output_asm_insn (\"staa\\t%h0\", ops);
1519
            }
1520
        }
1521
    }
1522
 
1523
  CC_STATUS_INIT;
1524
  return \"\";
1525
}")
1526
 
1527
 
1528
(define_insn "extendqihi2"
1529
  [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1530
        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1531
  ""
1532
  "*
1533
{
1534
  rtx ops[2];
1535
 
1536
  if (A_REG_P (operands[0]))
1537
    return \"#\";
1538
 
1539
  ops[0] = gen_label_rtx ();
1540
  if (D_REG_P (operands[0]))
1541
    {
1542
      if (TARGET_M6812)
1543
        {
1544
          if (!D_REG_P (operands[1]))
1545
            {
1546
              ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1547
              ops[1] = operands[1];
1548
              m68hc11_gen_movqi (insn, ops);
1549
            }
1550
          return \"sex\\tb,d\";
1551
        }
1552
      output_asm_insn (\"clra\", operands);
1553
      if (H_REG_P (operands[1]))
1554
        {
1555
          output_asm_insn (\"tstb\", operands);
1556
        }
1557
      else
1558
        {
1559
          output_asm_insn (\"ldab\\t%b1\", operands);
1560
        }
1561
      output_asm_insn (\"bpl\\t%l0\", ops);
1562
      output_asm_insn (\"deca\", operands);
1563
 
1564
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1565
                                 CODE_LABEL_NUMBER (ops[0]));
1566
    }
1567
   else
1568
    {
1569
      output_asm_insn (\"clr\\t%h0\", operands);
1570
      if (m68hc11_register_indirect_p (operands[1], HImode))
1571
        {
1572
          ops[1] = operands[1];
1573
          output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1574
          CC_STATUS_INIT;
1575
        }
1576
      else
1577
        {
1578
          output_asm_insn (\"tst\\t%b1\", operands);
1579
          output_asm_insn (\"bpl\\t%l0\", ops);
1580
        }
1581
      output_asm_insn (\"dec\\t%h0\", operands);
1582
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1583
                                 CODE_LABEL_NUMBER (ops[0]));
1584
    }
1585
 
1586
  return \"\";
1587
}")
1588
 
1589
;;
1590
;; Split the special case where the source of the sign extend is
1591
;; either Y or Z. In that case, we can't move the source in the D
1592
;; register directly. The movhi pattern handles this move by using
1593
;; a temporary scratch memory location.
1594
;;
1595
(define_split
1596
  [(set (match_operand:SI 0 "register_operand" "")
1597
        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1598
  "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1599
  [(set (reg:HI D_REGNUM) (match_dup 1))
1600
   (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1601
  "")
1602
 
1603
(define_insn "extendhisi2"
1604
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1605
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1606
  ""
1607
  "*
1608
{
1609
  rtx ops[2];
1610
  int x_reg_used;
1611
 
1612
  if (Y_REG_P (operands[1]))
1613
    return \"#\";
1614
 
1615
  if (X_REG_P (operands[1]))
1616
    {
1617
      output_asm_insn (\"xgdx\", operands);
1618
      x_reg_used = 1;
1619
    }
1620
  else
1621
    {
1622
      /* X can be used as an indexed addressing in the source.
1623
         Get the value before clearing it.  */
1624
      x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1625
      if (x_reg_used)
1626
        {
1627
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1628
          ops[1] = operands[1];
1629
          m68hc11_gen_movhi (insn, ops);
1630
        }
1631
    }
1632
 
1633
  CC_STATUS_INIT;
1634
  if (TARGET_M6812 && 0)
1635
    {
1636
      /* This sequence of code is larger than the one for 68HC11.
1637
         Don't use it; keep it for documentation.  */
1638
      if (!D_REG_P (operands[1]) && !x_reg_used)
1639
        {
1640
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1641
          ops[1] = operands[1];
1642
          m68hc11_gen_movhi (insn, ops);
1643
        }
1644
      output_asm_insn (\"sex\\ta,x\", operands);
1645
      output_asm_insn (\"xgdx\", operands);
1646
      output_asm_insn (\"sex\\ta,d\", operands);
1647
      return \"xgdx\";
1648
    }
1649
 
1650
  output_asm_insn (\"ldx\\t#0\", operands);
1651
  if (D_REG_P (operands[1]) || x_reg_used)
1652
    {
1653
      output_asm_insn (\"tsta\", operands);
1654
    }
1655
  else
1656
    {
1657
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1658
      ops[1] = operands[1];
1659
      m68hc11_gen_movhi (insn, ops);
1660
    }
1661
 
1662
  ops[0] = gen_label_rtx ();
1663
  output_asm_insn (\"bpl\\t%l0\", ops);
1664
  output_asm_insn (\"dex\", operands);
1665
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1666
 
1667
  return \"\";
1668
}")
1669
 
1670
 
1671
;;--------------------------------------------------------------------
1672
;;- Min and Max instructions (68HC12).
1673
;;--------------------------------------------------------------------
1674
(define_insn "uminqi3"
1675
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1676
        (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1677
                 (match_operand:QI 2 "general_operand" "m,d")))]
1678
  "TARGET_M6812 && TARGET_MIN_MAX"
1679
  "*
1680
{
1681
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
1682
     The mina/minm use A as the source or destination.  This is the
1683
     high part of D.  There is no way to express that in the pattern
1684
     so we must use 'exg a,b' to put the operand in the good register.  */
1685
  CC_STATUS_INIT;
1686
  if (D_REG_P (operands[0]))
1687
    {
1688
      return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1689
    }
1690
  else
1691
    {
1692
      return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1693
    }
1694
}")
1695
 
1696
(define_insn "umaxqi3"
1697
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1698
        (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1699
                 (match_operand:QI 2 "general_operand" "m,d")))]
1700
  "TARGET_M6812 && TARGET_MIN_MAX"
1701
  "*
1702
{
1703
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
1704
     The maxa/maxm use A as the source or destination.  This is the
1705
     high part of D.  There is no way to express that in the pattern
1706
     so we must use 'exg a,b' to put the operand in the good register.  */
1707
  CC_STATUS_INIT;
1708
  if (D_REG_P (operands[0]))
1709
    {
1710
      return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1711
    }
1712
  else
1713
    {
1714
      return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1715
    }
1716
}")
1717
 
1718
(define_insn "uminhi3"
1719
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1720
        (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1721
                 (match_operand:HI 2 "general_operand" "m,d")))]
1722
  "TARGET_M6812 && TARGET_MIN_MAX"
1723
  "*
1724
{
1725
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1726
  CC_STATUS_INIT;
1727
  if (D_REG_P (operands[0]))
1728
    {
1729
      return \"emind\\t%2\";
1730
    }
1731
  else
1732
    {
1733
      return \"eminm\\t%0\";
1734
    }
1735
}")
1736
 
1737
(define_insn "umaxhi3"
1738
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1739
        (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1740
                 (match_operand:HI 2 "general_operand" "m,d")))]
1741
  "TARGET_M6812 && TARGET_MIN_MAX"
1742
  "*
1743
{
1744
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1745
  CC_STATUS_INIT;
1746
  if (D_REG_P (operands[0]))
1747
    {
1748
      return \"emaxd\\t%2\";
1749
    }
1750
  else
1751
    {
1752
      return \"emaxm\\t%0\";
1753
    }
1754
}")
1755
 
1756
 
1757
;;--------------------------------------------------------------------
1758
;;- Add instructions.
1759
;;--------------------------------------------------------------------
1760
;; 64-bit: Use a library call because what GCC generates is huge.
1761
;;
1762
(define_expand "adddi3"
1763
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
1764
        (plus:DI (match_operand:DI 1 "general_operand" "")
1765
                 (match_operand:DI 2 "general_operand" "")))]
1766
  ""
1767
  "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1768
   DONE;")
1769
 
1770
;;
1771
;; - 32-bit Add.
1772
;;
1773
(define_expand "addsi3"
1774
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
1775
                     (plus:SI (match_operand:SI 1 "general_operand" "")
1776
                              (match_operand:SI 2 "general_operand" "")))
1777
              (clobber (match_scratch:HI 3 ""))])]
1778
  ""
1779
  "")
1780
 
1781
(define_insn "*addsi3_zero_extendhi"
1782
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1783
        (plus:SI (zero_extend:SI
1784
                 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1785
                 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1786
   (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1787
  ""
1788
  "*
1789
{
1790
  rtx ops[3];
1791
 
1792
  if (X_REG_P (operands[2]))
1793
    {
1794
      ops[0] = operands[1];
1795
    }
1796
  else
1797
    {
1798
      if (X_REG_P (operands[1]))
1799
        {
1800
          output_asm_insn (\"xgdx\", ops);
1801
        }
1802
      else if (!D_REG_P (operands[1]))
1803
        {
1804
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1805
          ops[1] = operands[1];
1806
          m68hc11_gen_movhi (insn, ops);
1807
        }
1808
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1809
      ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1810
    }
1811
  ops[2] = gen_label_rtx ();
1812
 
1813
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
1814
  output_asm_insn (\"addd\\t%0\", ops);
1815
  if (!X_REG_P (operands[2]))
1816
    output_asm_insn (\"ldx\\t%1\", ops);
1817
 
1818
  output_asm_insn (\"bcc\\t%l2\", ops);
1819
  output_asm_insn (\"inx\", ops);
1820
 
1821
  CC_STATUS_INIT;
1822
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1823
  return \"\";
1824
}")
1825
 
1826
 
1827
(define_split /* "*addsi3_zero_extendqi" */
1828
  [(set (match_operand:SI 0 "register_operand" "")
1829
        (plus:SI (zero_extend:SI
1830
                   (match_operand:QI 1 "general_operand" ""))
1831
                 (match_operand:SI 2 "memory_operand" "")))
1832
   (clobber (match_scratch:HI 3 "=X,X"))]
1833
  "reload_completed"
1834
  [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1835
   (parallel [(set (match_dup 0)
1836
                   (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1837
              (clobber (match_dup 3))])]
1838
  "")
1839
 
1840
(define_insn "*addsi3_zero_extendqi"
1841
  [(set (match_operand:SI 0 "register_operand" "=D,D")
1842
        (plus:SI (zero_extend:SI
1843
                   (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1844
                 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1845
   (clobber (match_scratch:HI 3 "=X,X"))]
1846
  ""
1847
  "*
1848
{
1849
  rtx ops[4];
1850
 
1851
  if (GET_CODE (operands[2]) == MEM)
1852
    return \"#\";
1853
 
1854
  if (X_REG_P (operands[2]))
1855
    {
1856
      if (H_REG_P (operands[1]))
1857
        {
1858
          ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1859
          ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1860
          m68hc11_gen_movhi (insn, ops);
1861
        }
1862
      else
1863
        {
1864
          ops[0] = operands[1];
1865
        }
1866
      ops[1] = const0_rtx;
1867
    }
1868
  else
1869
    {
1870
      if (X_REG_P (operands[1]))
1871
        {
1872
          output_asm_insn (\"xgdx\", ops);
1873
        }
1874
      else if (!D_REG_P (operands[1]))
1875
        {
1876
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1877
          ops[1] = operands[1];
1878
          m68hc11_gen_movqi (insn, ops);
1879
        }
1880
 
1881
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1882
      ops[1] = ops[0];
1883
      ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1884
      output_asm_insn (\"clra\", ops);
1885
    }
1886
 
1887
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
1888
  output_asm_insn (\"addb\\t%b0\", ops);
1889
  output_asm_insn (\"adca\\t%h1\", ops);
1890
  if (!X_REG_P (operands[2]))
1891
    output_asm_insn (\"ldx\\t%2\", ops);
1892
 
1893
  /* If the above adca was adding some constant, we don't need to propagate
1894
     the carry unless the constant was 0xff.  */
1895
  if (X_REG_P (operands[2])
1896
      || GET_CODE (ops[1]) != CONST_INT
1897
      || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1898
    {
1899
      ops[3] = gen_label_rtx ();
1900
 
1901
      output_asm_insn (\"bcc\\t%l3\", ops);
1902
      output_asm_insn (\"inx\", ops);
1903
 
1904
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1905
                                 CODE_LABEL_NUMBER (ops[3]));
1906
    }
1907
  CC_STATUS_INIT;
1908
  return \"\";
1909
}")
1910
 
1911
(define_insn "*addsi3"
1912
  [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1913
        (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1914
                 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1915
   (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1916
  ""
1917
  "*
1918
{
1919
  rtx   ops[3];
1920
  const char* add_insn;
1921
  const char* inc_insn;
1922
  const char* incb_mem;
1923
  const char* inch_mem;
1924
  HOST_WIDE_INT val;
1925
 
1926
  if (which_alternative > 2)
1927
    {
1928
      return \"#\";
1929
    }
1930
 
1931
  val = INTVAL (operands[2]);
1932
  if ((val & 0x0ffffL) == 0)
1933
    {
1934
      if (!H_REG_P (operands[0]))
1935
        {
1936
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1937
          ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1938
          output_asm_insn (\"ldd\\t%0\", ops);
1939
          output_asm_insn (\"addd\\t%1\", ops);
1940
          output_asm_insn (\"std\\t%0\", ops);
1941
          return \"\";
1942
        }
1943
      else if (val == 1)
1944
        {
1945
          return \"inx\";
1946
        }
1947
      else
1948
        {
1949
          return \"#\";
1950
        }
1951
    }
1952
  if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1953
    {
1954
      return \"#\";
1955
    }
1956
 
1957
  if (val >= 0)
1958
    {
1959
      ops[1]   = operands[2];
1960
      add_insn = \"addd\\t%1\";
1961
      inc_insn = \"inx\\t\";
1962
      incb_mem  = \"inc\\t%b1\";
1963
      inch_mem  = \"inc\\t%h1\";
1964
    }
1965
  else
1966
    {
1967
      ops[1] = GEN_INT (- val);
1968
      add_insn = \"subd\\t%1\";
1969
      inc_insn = \"dex\";
1970
      incb_mem  = \"dec\\t%b1\";
1971
      inch_mem  = \"dec\\t%h1\";
1972
    }
1973
 
1974
  ops[2] = gen_label_rtx ();
1975
  if (!H_REG_P (operands[0]))
1976
    {
1977
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1978
      output_asm_insn (\"ldd\\t%0\", ops);
1979
    }
1980
  output_asm_insn (add_insn, ops);
1981
  if (!H_REG_P (operands[0]))
1982
    {
1983
      output_asm_insn (\"std\\t%0\", ops);
1984
    }
1985
  output_asm_insn (\"bcc\\t%l2\", ops);
1986
  if (H_REG_P (operands[0]))
1987
    {
1988
      output_asm_insn (inc_insn, ops);
1989
    }
1990
  else
1991
    {
1992
      ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1993
      ops[1] = ops[0];
1994
      if (INTVAL (operands[2]) < 0)
1995
        {
1996
          output_asm_insn (\"ldd\\t%1\", ops);
1997
          output_asm_insn (\"addd\\t#-1\", ops);
1998
          output_asm_insn (\"std\\t%1\", ops);
1999
        }
2000
      else
2001
        {
2002
          output_asm_insn (incb_mem, ops);
2003
          output_asm_insn (\"bne\\t%l2\", ops);
2004
          output_asm_insn (inch_mem, ops);
2005
        }
2006
    }
2007
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2008
 
2009
  CC_STATUS_INIT;
2010
  return \"\";
2011
}")
2012
 
2013
(define_split
2014
  [(set (match_operand:SI 0 "register_operand" "")
2015
        (plus:SI (match_operand:SI 1 "register_operand" "")
2016
                 (match_operand:SI 2 "const_int_operand" "")))
2017
   (clobber (match_scratch:HI 3 ""))]
2018
  "reload_completed && z_replacement_completed == 2
2019
   && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2020
  [(set (match_dup 5) (match_dup 6))
2021
   (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2022
   (set (match_dup 6) (match_dup 5))]
2023
  "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2024
   if (X_REG_P (operands[0]))
2025
     {
2026
       operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2027
     }
2028
   else
2029
     {
2030
       operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2031
       operands[5] = operands[3];
2032
     }
2033
   ")
2034
 
2035
(define_split
2036
  [(set (match_operand:SI 0 "register_operand" "")
2037
        (plus:SI (match_operand:SI 1 "register_operand" "")
2038
                 (match_operand:SI 2 "general_operand" "")))
2039
   (clobber (match_scratch:HI 3 "=X"))]
2040
  "reload_completed && z_replacement_completed == 2
2041
   && (GET_CODE (operands[2]) != CONST_INT ||
2042
        (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2043
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2044
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2045
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2046
   (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2047
   (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2048
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2049
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2050
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2051
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2052
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2053
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2054
 
2055
;;
2056
;; Instruction generated to propagate the carry of a 16-bit add
2057
;; to the upper 16-bit part (in register X).
2058
;;
2059
(define_insn "*addsi_carry"
2060
  [(set (match_operand:HI 0 "register_operand" "=x")
2061
           (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2062
                             (const_int 0))
2063
                    (reg:HI CC_REGNUM)))]
2064
  ""
2065
  "*
2066
{
2067
  rtx ops[2];
2068
 
2069
  ops[0] = gen_label_rtx ();
2070
  output_asm_insn (\"bcc\\t%l0\", ops);
2071
  output_asm_insn (\"in%0\", operands);
2072
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2073
  CC_STATUS_INIT;
2074
  return \"\";
2075
}")
2076
 
2077
;;
2078
;; - 16-bit Add.
2079
;;
2080
(define_expand "addhi3"
2081
  [(set (match_operand:HI 0 "register_operand" "")
2082
           (plus:HI (match_operand:HI 1 "register_operand" "")
2083
                    (match_operand:HI 2 "general_operand" "")))]
2084
  ""
2085
  "
2086
{
2087
  if (TARGET_M6811 && SP_REG_P (operands[0]))
2088
    {
2089
      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2090
                         gen_rtx_SET (VOIDmode,
2091
                                  operand0,
2092
                                  gen_rtx_PLUS (HImode,
2093
                                           operand1, operand2)),
2094
                        gen_rtx_CLOBBER (VOIDmode,
2095
                                gen_rtx_SCRATCH (HImode)))));
2096
      DONE;
2097
    }
2098
}")
2099
 
2100
(define_insn "*addhi3_68hc12"
2101
  [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2102
        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2103
                 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2104
  "TARGET_M6812"
2105
  "*
2106
{
2107
  int val;
2108
  const char* insn_code;
2109
 
2110
  if (which_alternative >= 4)
2111
    {
2112
      if (A_REG_P (operands[2]))
2113
        {
2114
          CC_STATUS_INIT;
2115
          output_asm_insn (\"xgd%2\", operands);
2116
          output_asm_insn (\"lea%0 d,%0\", operands);
2117
          return \"xgd%2\";
2118
        }
2119
      return \"#\";
2120
    }
2121
 
2122
  if (D_REG_P (operands[0]))
2123
    {
2124
      if (X_REG_P (operands[2]))
2125
        {
2126
          m68hc11_notice_keep_cc (operands[0]);
2127
          output_asm_insn (\"xgdx\", operands);
2128
          output_asm_insn (\"leax\\td,%2\", operands);
2129
          return \"xgdx\";
2130
        }
2131
      else if (Y_REG_P (operands[2]))
2132
        {
2133
          m68hc11_notice_keep_cc (operands[0]);
2134
          output_asm_insn (\"xgdy\", operands);
2135
          output_asm_insn (\"leay\\td,%2\", operands);
2136
          return \"xgdy\";
2137
        }
2138
      else if (SP_REG_P (operands[2]))
2139
        {
2140
          output_asm_insn (\"sts\\t%t0\", operands);
2141
          return \"addd\\t%t0\";
2142
        }
2143
      return \"addd\\t%2\";
2144
    }
2145
 
2146
  if (GET_CODE (operands[2]) == CONST_INT)
2147
    val = INTVAL (operands[2]);
2148
  else
2149
    val = 1000;
2150
 
2151
  if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2152
    {
2153
      m68hc11_notice_keep_cc (operands[0]);
2154
      switch (REGNO (operands[0]))
2155
        {
2156
        case HARD_X_REGNUM:
2157
          return \"leax\\t%i2,%1\";
2158
 
2159
        case HARD_Y_REGNUM:
2160
          return \"leay\\t%i2,%1\";
2161
 
2162
        case HARD_SP_REGNUM:
2163
          return \"leas\\t%i2,%1\";
2164
 
2165
        default:
2166
          fatal_insn (\"Invalid operands in the instruction\", insn);
2167
        }
2168
    }
2169
  if (val > 0)
2170
    {
2171
      insn_code = X_REG_P (operands[0]) ? \"inx\"
2172
                : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2173
    }
2174
  else
2175
    {
2176
      val  = -val;
2177
      insn_code = X_REG_P (operands[0]) ? \"dex\"
2178
                : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2179
    }
2180
 
2181
  /* For X and Y increment, the flags are not complete. Only the Z flag
2182
     is updated. For SP increment, flags are not changed.  */
2183
  if (SP_REG_P (operands[0]))
2184
    {
2185
      cc_status = cc_prev_status;
2186
      if (INTVAL (operands[2]) < 0)
2187
        {
2188
          while (val > 2)
2189
            {
2190
              output_asm_insn (\"pshx\", operands);
2191
              val -= 2;
2192
            }
2193
          if (val == 0)
2194
            return \"\";
2195
        }
2196
    }
2197
  else
2198
    {
2199
      CC_STATUS_INIT;
2200
    }
2201
 
2202
  while (val)
2203
    {
2204
      output_asm_insn (insn_code, operands);
2205
      val--;
2206
    }
2207
  return \"\";
2208
}")
2209
 
2210
;;
2211
;; Specific pattern to add to the stack pointer.
2212
;; We also take care of the clobbering of the IY register.
2213
;;
2214
(define_insn "addhi_sp"
2215
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2216
          (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2217
                   (match_operand:HI 2 "general_operand" "P,im,u,im")))
2218
   (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2219
  "!TARGET_M6812"
2220
  "*
2221
{
2222
  HOST_WIDE_INT val;
2223
 
2224
  if (optimize && Y_REG_P (operands[3])
2225
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2226
    operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2227
 
2228
  if (GET_CODE (operands[2]) == CONST_INT
2229
      && (val = INTVAL (operands[2])) != 0
2230
      && (CONST_OK_FOR_LETTER_P (val, 'P')
2231
          || (val > 0 && val <= 8)))
2232
    {
2233
      while (val > 1 || val < -1)
2234
        {
2235
          if (val > 0)
2236
            {
2237
              if (!H_REG_P (operands[3]))
2238
                break;
2239
 
2240
              output_asm_insn (\"pul%3\", operands);
2241
              val -= 2;
2242
            }
2243
          else
2244
            {
2245
              output_asm_insn (\"pshx\", operands);
2246
              val += 2;
2247
            }
2248
        }
2249
      while (val != 0)
2250
        {
2251
          if (val > 0)
2252
            {
2253
              output_asm_insn (\"ins\", operands);
2254
              val--;
2255
            }
2256
          else
2257
            {
2258
              output_asm_insn (\"des\", operands);
2259
              val++;
2260
            }
2261
        }
2262
      cc_status = cc_prev_status;
2263
      return \"\";
2264
    }
2265
 
2266
  /* Need to transfer to SP to X/Y and then to D register.
2267
     Register X/Y is lost, this is specified by the (clobber) statement.  */
2268
  output_asm_insn (\"ts%3\", operands);
2269
  if (GET_CODE (operands[2]) == CONST_INT
2270
      && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2271
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2272
    {
2273
      output_asm_insn (\"ldab\\t%2\", operands);
2274
      output_asm_insn (\"ab%3\", operands);
2275
      CC_STATUS_INIT;
2276
    }
2277
  else
2278
    {
2279
      output_asm_insn (\"xgd%3\", operands);
2280
      output_asm_insn (\"addd\\t%2\", operands);
2281
      output_asm_insn (\"xgd%3\", operands);
2282
    }
2283
 
2284
   /* The status flags correspond to the addd.  xgdy and tys do not
2285
      modify the flags.  */
2286
  return \"t%3s\";
2287
}")
2288
 
2289
(define_insn "*addhi3"
2290
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2291
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2292
                 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2293
  "TARGET_M6811"
2294
  "*
2295
{
2296
  const char* insn_code;
2297
  int val;
2298
 
2299
  if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2300
    {
2301
      output_asm_insn (\"sts\\t%t0\", operands);
2302
      output_asm_insn (\"addd\\t%t0\", operands);
2303
      return \"addd\\t#1\";
2304
    }
2305
  if (GET_CODE (operands[2]) != CONST_INT)
2306
    {
2307
      /* Adding to an address register or with another/same register
2308
         is not possible. This must be replaced.  */
2309
      if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2310
        return \"#\";
2311
 
2312
      return \"addd\\t%2\";
2313
    }
2314
  val = INTVAL (operands[2]);
2315
  if (!SP_REG_P (operands[0]))
2316
    {
2317
      if (D_REG_P (operands[0]))
2318
        {
2319
          if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2320
            {
2321
              CC_STATUS_INIT;
2322
              return \"adda\\t%h2\";
2323
            }
2324
          else
2325
            {
2326
              return \"addd\\t%2\";
2327
            }
2328
        }
2329
      else if (GET_CODE (operands[2]) != CONST_INT
2330
               || INTVAL (operands[2]) < -4
2331
               || INTVAL (operands[2]) > 4)
2332
        return \"#\";
2333
    }
2334
  if (val > 0)
2335
    {
2336
      insn_code = X_REG_P (operands[0]) ? \"inx\"
2337
                    : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2338
    }
2339
  else
2340
    {
2341
      val  = -val;
2342
      insn_code = X_REG_P (operands[0]) ? \"dex\"
2343
                    : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2344
    }
2345
 
2346
  /* For X and Y increment, the flags are not complete.  Only the Z flag
2347
     is updated.  For SP increment, flags are not changed.  */
2348
  if (SP_REG_P (operands[0]))
2349
    {
2350
      cc_status = cc_prev_status;
2351
      if (INTVAL (operands[2]) < 0)
2352
        {
2353
          while (val >= 2)
2354
            {
2355
              output_asm_insn (\"pshx\", operands);
2356
              val -= 2;
2357
            }
2358
        }
2359
      else if (optimize && dead_register_here (insn, ix_reg))
2360
        {
2361
          while (val >= 2)
2362
            {
2363
              output_asm_insn (\"pulx\", operands);
2364
              val -= 2;
2365
            }
2366
        }
2367
    }
2368
  else
2369
    {
2370
      CC_STATUS_INIT;
2371
    }
2372
 
2373
  while (val)
2374
    {
2375
      output_asm_insn (insn_code, operands);
2376
      val--;
2377
    }
2378
  return \"\";
2379
}")
2380
 
2381
(define_insn "*addhi3_zext"
2382
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2383
        (plus:HI (zero_extend:HI
2384
                     (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2385
                 (match_operand:HI 2 "general_operand" "0,0")))]
2386
  ""
2387
  "*
2388
{
2389
  CC_STATUS_INIT;
2390
  if (A_REG_P (operands[0]))
2391
    return \"ab%0\";
2392
  else if (A_REG_P (operands[1]))
2393
    return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2394
  else
2395
    return \"addb\\t%b1\\n\\tadca\\t#0\";
2396
}")
2397
 
2398
;;
2399
;; Translate d = d + d into d = << 1
2400
;; We have to do this because adding a register to itself is not possible.
2401
;; ??? It's not clear whether this is really necessary.
2402
;;
2403
(define_split
2404
  [(set (match_operand:QI 0 "hard_reg_operand" "")
2405
        (plus:QI (match_dup 0)
2406
                 (match_dup 0)))]
2407
  "0 && reload_completed"
2408
  [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2409
  "")
2410
 
2411
(define_insn "addqi3"
2412
  [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2413
        (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2414
                 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2415
  ""
2416
  "*
2417
{
2418
  if (GET_CODE (operands[2]) == CONST_INT)
2419
    {
2420
      if (INTVAL (operands[2]) == 1)
2421
        {
2422
          if (DA_REG_P (operands[0]))
2423
            {
2424
              return \"inca\";
2425
            }
2426
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2427
           {
2428
             return \"incb\";
2429
 
2430
           }
2431
          else if (A_REG_P (operands[0]))
2432
           {
2433
             /* This applies on the 16-bit register.  This should be ok since
2434
                this is not a strict_low_part increment.  */
2435
             return \"in%0\";
2436
           }
2437
          else
2438
           {
2439
             return \"inc\\t%b0\";
2440
           }
2441
        }
2442
      else if (INTVAL (operands[2]) == -1)
2443
        {
2444
          if (DA_REG_P (operands[0]))
2445
            {
2446
              return \"deca\";
2447
            }
2448
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2449
            {
2450
              return \"decb\";
2451
            }
2452
          else if (A_REG_P (operands[0]))
2453
            {
2454
             /* This applies on the 16-bit register.  This should be ok since
2455
                this is not a strict_low_part decrement.  */
2456
              return \"de%0\";
2457
            }
2458
          else
2459
            {
2460
              return \"dec\\t%b0\";
2461
            }
2462
        }
2463
    }
2464
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2465
    return \"#\";
2466
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2467
    return \"addb\\t%b2\";
2468
  else
2469
    return \"adda\\t%b2\";
2470
}")
2471
 
2472
;;
2473
;; add with carry is used for 32-bit add.
2474
;;
2475
(define_insn "*adcq"
2476
  [(set (match_operand:QI 0 "register_operand" "=q")
2477
        (plus:QI (plus:QI (reg:QI CC_REGNUM)
2478
                          (match_operand:QI 1 "register_operand" "%0"))
2479
                 (match_operand:QI 2 "general_operand" "ium")))]
2480
  ""
2481
  "adc%0\\t%b2")
2482
 
2483
;;--------------------------------------------------------------------
2484
;;- Subtract instructions.
2485
;;--------------------------------------------------------------------
2486
 
2487
(define_expand "subdi3"
2488
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
2489
        (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2490
                  (match_operand:DI 2 "general_operand" "")))]
2491
  ""
2492
  "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2493
   DONE;")
2494
 
2495
;;
2496
;; 32-bit Subtract (see addsi3)
2497
;; Subtract with a constant are handled by addsi3.
2498
;;
2499
;;
2500
;; - 32-bit Add.
2501
;;
2502
(define_expand "subsi3"
2503
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
2504
                     (minus:SI (match_operand:SI 1 "register_operand" "")
2505
                              (match_operand:SI 2 "general_operand" "")))
2506
              (clobber (match_scratch:HI 3 ""))])]
2507
  ""
2508
  "")
2509
 
2510
(define_insn "*subsi3"
2511
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2512
        (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2513
                  (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2514
   (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2515
  ""
2516
  "#")
2517
 
2518
(define_insn "*subsi3_zero_extendhi"
2519
  [(set (match_operand:SI 0 "register_operand" "=D")
2520
        (minus:SI (match_operand:SI 1 "register_operand" "0")
2521
            (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2522
   (clobber (match_scratch:HI 3 "=X"))]
2523
  ""
2524
  "*
2525
{
2526
  rtx ops[2];
2527
 
2528
  if (A_REG_P (operands[2]))
2529
    {
2530
      if (TARGET_M6812)
2531
        ops[0] = gen_rtx_MEM (HImode,
2532
                          gen_rtx_PRE_DEC (HImode,
2533
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2534
      else
2535
        ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2536
 
2537
      ops[1] = operands[2];
2538
      m68hc11_gen_movhi (insn, ops);
2539
      if (TARGET_M6812)
2540
        operands[2] = gen_rtx_MEM (HImode,
2541
                               gen_rtx_POST_INC (HImode,
2542
                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2543
      else
2544
        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2545
    }
2546
  ops[0] = gen_label_rtx ();
2547
  output_asm_insn (\"subd\\t%2\", operands);
2548
  output_asm_insn (\"bcc\\t%l0\", ops);
2549
  output_asm_insn (\"dex\", ops);
2550
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2551
  CC_STATUS_INIT;
2552
  return \"\";
2553
}")
2554
 
2555
(define_insn "*subsi3_zero_extendqi"
2556
  [(set (match_operand:SI 0 "register_operand" "=D")
2557
        (minus:SI (match_operand:SI 1 "register_operand" "0")
2558
            (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2559
   (clobber (match_scratch:HI 3 "=X"))]
2560
  ""
2561
  "*
2562
{
2563
  rtx ops[2];
2564
 
2565
  if (A_REG_P (operands[2]))
2566
    {
2567
      ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2568
      ops[1] = operands[2];
2569
      m68hc11_gen_movhi (insn, ops);
2570
      operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2571
    }
2572
  ops[0] = gen_label_rtx ();
2573
  output_asm_insn (\"subb\\t%b2\", operands);
2574
  output_asm_insn (\"sbca\\t#0\", operands);
2575
  output_asm_insn (\"bcc\\t%l0\", ops);
2576
  output_asm_insn (\"dex\", ops);
2577
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2578
  CC_STATUS_INIT;
2579
  return \"\";
2580
}")
2581
 
2582
;;
2583
;; reg:HI 1 -> d        reg:QI 6 -> B
2584
;; reg:QI 7 -> ccr      reg:QI 5 -> A
2585
;;
2586
(define_split /* "*subsi3" */
2587
  [(set (match_operand:SI 0 "register_operand" "")
2588
        (minus:SI (match_operand:SI 1 "register_operand" "")
2589
                  (match_operand:SI 2 "general_operand" "")))
2590
   (clobber (match_scratch:HI 3 "=X"))]
2591
  "reload_completed && z_replacement_completed == 2
2592
   && X_REG_P (operands[1])"
2593
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2594
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2595
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2596
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2597
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2598
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2599
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2600
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2601
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2602
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2603
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2604
 
2605
(define_split /* "*subsi3" */
2606
  [(set (match_operand:SI 0 "register_operand" "")
2607
        (minus:SI (match_operand:SI 1 "general_operand" "")
2608
                  (match_operand:SI 2 "register_operand" "")))
2609
   (clobber (match_scratch:HI 3 "=X"))]
2610
  "reload_completed && z_replacement_completed == 2
2611
   && X_REG_P (operands[2])"
2612
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2613
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2614
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2615
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2616
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2617
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2618
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2619
   (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2620
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2621
   operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2622
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2623
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2624
 
2625
(define_split /* "*subsi3" */
2626
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
2627
        (minus:SI (match_operand:SI 1 "general_operand" "")
2628
                  (match_operand:SI 2 "general_operand" "")))
2629
   (clobber (match_scratch:HI 3 "=d"))]
2630
  "reload_completed && z_replacement_completed == 2
2631
   && !X_REG_P (operands[0])"
2632
  [(set (match_dup 3) (match_dup 4))
2633
   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2634
   (set (match_dup 4) (match_dup 3))
2635
   (set (match_dup 3) (match_dup 6))
2636
   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2637
   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2638
   (set (match_dup 6) (match_dup 3))]
2639
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2640
   operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2641
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2642
   operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2643
   operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2644
   operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2645
 
2646
;;
2647
;; - 16-bit Subtract.
2648
;;
2649
(define_expand "subhi3"
2650
  [(set (match_operand:HI 0 "register_operand" "=r")
2651
        (minus:HI (match_operand:HI 1 "register_operand" "0")
2652
                  (match_operand:HI 2 "general_operand" "g")))]
2653
  ""
2654
  "")
2655
 
2656
;;
2657
;; Subtract from stack. This is better if we provide a pattern.
2658
;;
2659
(define_insn "*subhi3_sp"
2660
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2661
        (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2662
                  (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2663
   (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2664
  ""
2665
  "*
2666
{
2667
  if (X_REG_P (operands[2]))
2668
    {
2669
      operands[2] = m68hc11_soft_tmp_reg;
2670
      output_asm_insn (\"stx\\t%2\", operands);
2671
    }
2672
  else if (Y_REG_P (operands[2]))
2673
    {
2674
      operands[2] = m68hc11_soft_tmp_reg;
2675
      output_asm_insn (\"sty\\t%2\", operands);
2676
    }
2677
  else if (D_REG_P (operands[2]))
2678
    {
2679
      operands[2] = m68hc11_soft_tmp_reg;
2680
      output_asm_insn (\"std\\t%2\", operands);
2681
    }
2682
 
2683
  if (D_REG_P (operands[3]))
2684
    {
2685
      int save_x;
2686
 
2687
      save_x = !dead_register_here (insn, ix_reg);
2688
      if (save_x)
2689
        output_asm_insn (\"xgdx\", operands);
2690
      output_asm_insn (\"tsx\", operands);
2691
      output_asm_insn (\"xgdx\", operands);
2692
      output_asm_insn (\"subd\\t%2\", operands);
2693
      output_asm_insn (\"xgdx\", operands);
2694
 
2695
      /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2696
         modify the flags.  */
2697
      output_asm_insn (\"txs\", operands);
2698
      if (save_x)
2699
        return \"xgdx\";
2700
      else
2701
        return \"\";
2702
    }
2703
 
2704
  /* Need to transfer to SP to X,Y and then to D register.
2705
     Register X,Y is lost, this is specified by the (clobber) statement.  */
2706
  output_asm_insn (\"ts%3\", operands);
2707
  output_asm_insn (\"xgd%3\", operands);
2708
  output_asm_insn (\"subd\\t%2\", operands);
2709
  output_asm_insn (\"xgd%3\", operands);
2710
 
2711
   /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2712
      modify the flags.  */
2713
  return \"t%3s\";
2714
}")
2715
 
2716
 
2717
(define_insn "*subhi3"
2718
  [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2719
        (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2720
                  (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2721
  ""
2722
  "*
2723
{
2724
  /* Adding to an address register or with another/same register
2725
     is not possible.  This must be replaced.  */
2726
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2727
    return \"#\";
2728
 
2729
  return \"subd\\t%2\";
2730
}")
2731
 
2732
(define_insn "*subhi3_zext"
2733
  [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2734
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2735
           (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2736
  ""
2737
  "*
2738
{
2739
  CC_STATUS_INIT;
2740
  if (A_REG_P (operands[2]))
2741
    {
2742
      rtx ops[2];
2743
 
2744
      ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2745
      ops[1] = operands[2];
2746
      m68hc11_gen_movqi (insn, ops);
2747
      return \"subb\\t%T0\\n\\tsbca\\t#0\";
2748
    }
2749
  return \"subb\\t%b2\\n\\tsbca\\t#0\";
2750
}")
2751
 
2752
(define_insn "subqi3"
2753
  [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2754
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2755
                  (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2756
  ""
2757
  "*
2758
{
2759
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2760
    return \"#\";
2761
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2762
    return \"subb\\t%b2\";
2763
  else
2764
    return \"suba\\t%b2\";
2765
}")
2766
 
2767
;;
2768
;; subtract with carry is used for 32-bit subtract.
2769
;;
2770
(define_insn "*subcq"
2771
  [(set (match_operand:QI 0 "register_operand" "=q")
2772
        (minus:QI (minus:QI (reg:QI CC_REGNUM)
2773
                            (match_operand:QI 1 "register_operand" "0"))
2774
                  (match_operand:QI 2 "general_operand" "ium")))]
2775
  ""
2776
  "sbc%0\\t%b2")
2777
 
2778
;;--------------------------------------------------------------------
2779
;;- Multiply instructions.
2780
;;--------------------------------------------------------------------
2781
;;
2782
;; 32 and 64-bit multiply are handled by the library
2783
;;
2784
 
2785
(define_expand "mulsi3"
2786
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
2787
        (mult:SI (match_operand:SI 1 "general_operand" "")
2788
                 (match_operand:SI 2 "general_operand" "")))]
2789
  ""
2790
  "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2791
   DONE;")
2792
 
2793
(define_expand "mulhi3"
2794
  [(parallel [(set (match_operand:HI 0 "register_operand" "")
2795
                       (mult:HI (match_operand:HI 1 "register_operand" "")
2796
                                (match_operand:HI 2 "register_operand" "")))
2797
              (clobber (match_scratch:HI 3 ""))])]
2798
  ""
2799
  "")
2800
 
2801
(define_insn "mulhi3_m68hc11"
2802
  [(set (match_operand:HI 0 "register_operand" "=d")
2803
        (mult:HI (match_operand:HI 1 "register_operand" "%0")
2804
                 (match_operand:HI 2 "register_operand" "x")))
2805
   (clobber (match_scratch:HI 3 "=X"))]
2806
  "TARGET_M6811"
2807
  "*
2808
{
2809
  CC_STATUS_INIT;
2810
  /* D * X -> D  (X and Y are preserved by this function call).  */
2811
  return \"jsr\\t___mulhi3\";
2812
}")
2813
 
2814
(define_insn "mulhi3_m68hc12"
2815
  [(set (match_operand:HI 0 "register_operand" "=d,d")
2816
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2817
                 (match_operand:HI 2 "register_operand" "y,x")))
2818
   (clobber (match_scratch:HI 3 "=2,2"))]
2819
  "TARGET_M6812"
2820
  "*
2821
{
2822
  CC_STATUS_INIT;
2823
  if (X_REG_P (operands[2]))
2824
    return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2825
  else
2826
    return \"emul\";
2827
}")
2828
 
2829
(define_insn "umulhisi3"
2830
  [(set (match_operand:SI 0 "register_operand" "=D,D")
2831
        (mult:SI (zero_extend:SI
2832
                     (match_operand:HI 1 "register_operand" "%d,d"))
2833
                 (zero_extend:SI
2834
                     (match_operand:HI 2 "register_operand" "y,x"))))
2835
   (clobber (match_scratch:HI 3 "=2,X"))]
2836
  "TARGET_M6812"
2837
  "*
2838
{
2839
  if (X_REG_P (operands [2]))
2840
    output_asm_insn (\"exg\\tx,y\", operands);
2841
 
2842
  /* Can't use the carry after that; other flags are ok when testing
2843
     the 32-bit result.  */
2844
  cc_status.flags |= CC_NO_OVERFLOW;
2845
  return \"emul\\n\\texg\\tx,y\";
2846
}")
2847
 
2848
(define_insn "mulhisi3"
2849
  [(set (match_operand:SI 0 "register_operand" "=D,D")
2850
        (mult:SI (sign_extend:SI
2851
                     (match_operand:HI 1 "register_operand" "%d,d"))
2852
                 (sign_extend:SI
2853
                     (match_operand:HI 2 "register_operand" "y,x"))))
2854
   (clobber (match_scratch:HI 3 "=2,X"))]
2855
  "TARGET_M6812"
2856
  "*
2857
{
2858
  if (X_REG_P (operands [2]))
2859
    output_asm_insn (\"exg\\tx,y\", operands);
2860
 
2861
  /* Can't use the carry after that; other flags are ok when testing
2862
     the 32-bit result.  */
2863
  cc_status.flags |= CC_NO_OVERFLOW;
2864
  return \"emuls\\n\\texg\\tx,y\";
2865
}")
2866
 
2867
(define_insn "umulqihi3"
2868
  [(set (match_operand:HI 0 "register_operand" "=d")
2869
        (mult:HI (zero_extend:HI
2870
                     (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2871
                 (zero_extend:HI
2872
                     (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2873
  ""
2874
  "*
2875
{
2876
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2877
    {
2878
      output_asm_insn (\"tba\", operands);
2879
    }
2880
  else
2881
    {
2882
      rtx ops[2];
2883
 
2884
      if (D_REG_P (operands[2]))
2885
        {
2886
          rtx temp = operands[2];
2887
          operands[2] = operands[1];
2888
          operands[1] = temp;
2889
        }
2890
 
2891
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2892
      ops[1] = operands[2];
2893
      m68hc11_gen_movqi (insn, ops);
2894
 
2895
      if (!D_REG_P (operands[1]))
2896
        {
2897
          output_asm_insn (\"ldab\\t%b1\", operands);
2898
        }
2899
    }
2900
 
2901
  CC_STATUS_INIT;
2902
  return \"mul\";
2903
}")
2904
 
2905
(define_insn "mulqi3"
2906
  [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2907
        (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2908
                 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2909
  ""
2910
  "*
2911
{
2912
  if (A_REG_P (operands[0]))
2913
    return \"#\";
2914
 
2915
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2916
    {
2917
      output_asm_insn (\"tba\", operands);
2918
    }
2919
  else
2920
    {
2921
      if (D_REG_P (operands[2]))
2922
        {
2923
          rtx temp = operands[2];
2924
          operands[2] = operands[1];
2925
          operands[1] = temp;
2926
        }
2927
 
2928
      output_asm_insn (\"ldaa\\t%b2\", operands);
2929
 
2930
      if (!D_REG_P (operands[1]))
2931
        {
2932
          output_asm_insn (\"ldab\\t%b1\", operands);
2933
        }
2934
    }
2935
 
2936
  CC_STATUS_INIT;
2937
  return \"mul\";
2938
}")
2939
 
2940
(define_split
2941
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2942
        (mult:QI (match_operand:QI 1 "general_operand" "")
2943
                 (match_operand:QI 2 "general_operand" "")))]
2944
  "z_replacement_completed == 2"
2945
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2946
              (set (match_dup 3) (reg:HI D_REGNUM))])
2947
   (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2948
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2949
              (set (match_dup 3) (reg:HI D_REGNUM))])]
2950
  "
2951
   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2952
   if (A_REG_P (operands[1]))
2953
     operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2954
   else
2955
     operands[5] = operands[1];
2956
   if (A_REG_P (operands[2]))
2957
     operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2958
   else
2959
     operands[6] = operands[2];
2960
  ")
2961
 
2962
(define_insn "mulqihi3"
2963
  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2964
        (mult:HI (sign_extend:HI
2965
                        (match_operand:QI 1 "register_operand" "%0,0,0"))
2966
                 (sign_extend:HI
2967
                        (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2968
  ""
2969
  "*
2970
{
2971
  CC_STATUS_INIT;
2972
 
2973
  /* Special case when multiplying the register with itself.  */
2974
  if (D_REG_P (operands[2]))
2975
    {
2976
      output_asm_insn (\"tba\", operands);
2977
      return \"mul\";
2978
    }
2979
 
2980
  if (!H_REG_P (operands[2]))
2981
    {
2982
      output_asm_insn (\"ldaa\\t%b2\", operands);
2983
    }
2984
  else
2985
    {
2986
      rtx ops[2];
2987
 
2988
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2989
      ops[1] = operands[2];
2990
      m68hc11_gen_movqi (insn, ops);
2991
    }
2992
  return \"jsr\\t___mulqi3\";
2993
}")
2994
 
2995
;;--------------------------------------------------------------------
2996
;;- Divide instructions.
2997
;;--------------------------------------------------------------------
2998
 
2999
(define_insn "divmodhi4"
3000
  [(set (match_operand:HI 0 "register_operand" "=d,d")
3001
          (div:HI (match_operand:HI 1 "register_operand" "0,0")
3002
                  (match_operand:HI 2 "general_operand" "A,ium")))
3003
   (set (match_operand:HI 3 "register_operand" "=&x,&x")
3004
        (mod:HI (match_dup 1) (match_dup 2)))]
3005
  ""
3006
  "*
3007
{
3008
  if (!X_REG_P (operands[2]))
3009
    {
3010
      if (Y_REG_P (operands[2]))
3011
        {
3012
          output_asm_insn (\"sty\\t%t1\", operands);
3013
          output_asm_insn (\"ldx\\t%t1\", operands);
3014
        }
3015
      else
3016
        {
3017
          output_asm_insn (\"ldx\\t%2\", operands);
3018
        }
3019
    }
3020
  if (TARGET_M6812)
3021
    {
3022
      /* Flags are ok after that.  */
3023
      return \"idivs\\n\\txgdx\";
3024
    }
3025
  else
3026
    {
3027
      CC_STATUS_INIT;
3028
      return \"bsr\\t__divmodhi4\";
3029
    }
3030
}")
3031
 
3032
(define_insn "udivmodhi4"
3033
  [(set (match_operand:HI 0 "register_operand" "=d,d")
3034
          (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3035
                   (match_operand:HI 2 "general_operand" "A,ium")))
3036
   (set (match_operand:HI 3 "register_operand" "=x,x")
3037
        (umod:HI (match_dup 1) (match_dup 2)))]
3038
  ""
3039
  "*
3040
{
3041
  if (!X_REG_P (operands[2]))
3042
    {
3043
      if (Y_REG_P (operands[2]))
3044
        {
3045
          output_asm_insn (\"sty\\t%t1\", operands);
3046
          output_asm_insn (\"ldx\\t%t1\", operands);
3047
        }
3048
      else
3049
        {
3050
          output_asm_insn (\"ldx\\t%2\", operands);
3051
        }
3052
    }
3053
 
3054
  /* Z V and C flags are set but N is unchanged.
3055
     Since this is an unsigned divide, we can probably keep the flags
3056
     and indicate this.  */
3057
  cc_status.flags |= CC_NOT_NEGATIVE;
3058
  return \"idiv\\n\\txgdx\";
3059
}")
3060
 
3061
;;--------------------------------------------------------------------
3062
;;- and instructions.
3063
;;--------------------------------------------------------------------
3064
 
3065
(define_insn_and_split "anddi3"
3066
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3067
        (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3068
                (match_operand:DI 2 "general_operand" "imu,imu")))
3069
   (clobber (match_scratch:HI 3 "=d,d"))]
3070
  ""
3071
  "#"
3072
  "reload_completed"
3073
  [(const_int 0)]
3074
  "m68hc11_split_logical (SImode, AND, operands);
3075
   DONE;")
3076
 
3077
(define_insn_and_split "andsi3"
3078
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
3079
        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3080
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
3081
   (clobber (match_scratch:HI 3 "=X,d"))]
3082
  ""
3083
  "#"
3084
  "reload_completed"
3085
  [(const_int 0)]
3086
  "m68hc11_split_logical (HImode, AND, operands);
3087
   DONE;")
3088
 
3089
(define_expand "andhi3"
3090
  [(set (match_operand:HI 0 "register_operand" "")
3091
        (and:HI (match_operand:HI 1 "register_operand" "")
3092
                (match_operand:HI 2 "general_operand" "")))]
3093
  ""
3094
  "")
3095
 
3096
(define_insn "*andhi3_mem"
3097
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3098
        (and:HI (match_dup 0)
3099
                (match_operand:HI 1 "immediate_operand" "i,i")))
3100
   (clobber (match_scratch:HI 2 "=X,xy"))]
3101
  "TARGET_RELAX && !TARGET_M6812"
3102
  "*
3103
{
3104
  int val = INTVAL (operands[1]) & 0x0FFFF;
3105
 
3106
  if (val == 0x0ffff)
3107
    {
3108
      cc_status = cc_prev_status;
3109
      return \"\";
3110
    }
3111
 
3112
  CC_STATUS_INIT;
3113
 
3114
  /* The bclr instruction uses an inverted mask.  */
3115
  operands[1] = GEN_INT ((~val) & 0x0FFFF);
3116
 
3117
  /* When destination is a global variable, generate a .relax instruction
3118
     and load the address in the clobber register.  That load can be
3119
     eliminated by the linker if the address is in page0.  */
3120
  if (which_alternative == 1)
3121
    {
3122
      rtx ops[3];
3123
 
3124
      ops[0] = operands[2];
3125
      ops[1] = XEXP (operands[0], 0);
3126
      ops[2] = gen_label_rtx ();
3127
      output_asm_insn (\".relax\\t%l2\", ops);
3128
      m68hc11_gen_movhi (insn, ops);
3129
      if ((val & 0x0FF) != 0x0FF)
3130
        output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3131
 
3132
      if ((val & 0x0FF00) != 0x0FF00)
3133
        output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3134
 
3135
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3136
                                 CODE_LABEL_NUMBER (ops[2]));
3137
      return \"\";
3138
    }
3139
 
3140
  if ((val & 0x0FF) != 0x0FF)
3141
    output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3142
 
3143
  if ((val & 0x0FF00) != 0x0FF00)
3144
    output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3145
 
3146
  return \"\";
3147
}")
3148
 
3149
(define_insn "*andhi3_const"
3150
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3151
        (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3152
                (match_operand:HI 2 "const_int_operand" "")))]
3153
  ""
3154
  "*
3155
{
3156
  int val = INTVAL (operands[2]) & 0x0FFFF;
3157
  int lowpart_zero = 0;
3158
  int highpart_zero = 0;
3159
  int lowpart_unknown = 0;
3160
  int highpart_unknown = 0;
3161
 
3162
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3163
    return \"#\";
3164
 
3165
  if (val == 0x0ffff)
3166
    {
3167
      cc_status = cc_prev_status;
3168
      return \"\";
3169
    }
3170
 
3171
  /* First, try to clear the low and high part.
3172
     If that's possible, the second 'and' will give
3173
     the good status flags and we can avoid a tsthi.  */
3174
  if ((val & 0x0FF) == 0)
3175
    {
3176
      if (D_REG_P (operands[0]))
3177
        output_asm_insn (\"clrb\", operands);
3178
      else
3179
        output_asm_insn (\"clr\\t%b0\", operands);
3180
      lowpart_zero = 1;
3181
    }
3182
  if ((val & 0x0FF00) == 0)
3183
    {
3184
      if (D_REG_P (operands[0]))
3185
        output_asm_insn (\"clra\", operands);
3186
      else
3187
        output_asm_insn (\"clr\\t%h0\", operands);
3188
      highpart_zero = 1;
3189
    }
3190
 
3191
  if ((val & 0x0FF) == 0x0FF)
3192
    {
3193
      lowpart_unknown = 1;
3194
    }
3195
  else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3196
    {
3197
      rtx ops[2];
3198
 
3199
      ops[0] = operands[0];
3200
      ops[1] = GEN_INT ((~val) & 0x0FF);
3201
      output_asm_insn (\"bclr\\t%b0, %1\", ops);
3202
    }
3203
  else if ((val & 0x0FF) != 0)
3204
    {
3205
      output_asm_insn (\"andb\\t%b2\", operands);
3206
    }
3207
 
3208
  if ((val & 0x0FF00) == 0x0FF00)
3209
    {
3210
      highpart_unknown = 1;
3211
    }
3212
  else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3213
    {
3214
      rtx ops[2];
3215
 
3216
      ops[0] = operands[0];
3217
      ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3218
      output_asm_insn (\"bclr\\t%h0, %1\", ops);
3219
    }
3220
  else if ((val & 0x0FF00) != 0)
3221
    {
3222
      output_asm_insn (\"anda\\t%h2\", operands);
3223
    }
3224
 
3225
  if (highpart_unknown || lowpart_unknown)
3226
     CC_STATUS_INIT;
3227
  else if (highpart_zero == 0 && lowpart_zero == 0)
3228
     CC_STATUS_INIT;
3229
 
3230
  return \"\";
3231
}")
3232
 
3233
(define_insn "*andhi3_gen"
3234
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3235
        (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3236
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3237
  ""
3238
  "*
3239
{
3240
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3241
    return \"#\";
3242
 
3243
  CC_STATUS_INIT;
3244
  return \"anda\\t%h2\\n\\tandb\\t%b2\";
3245
}")
3246
 
3247
(define_expand "andqi3"
3248
  [(set (match_operand:QI 0 "register_operand" "")
3249
        (and:QI (match_operand:QI 1 "register_operand" "")
3250
                (match_operand:QI 2 "general_operand" "")))]
3251
  ""
3252
  "")
3253
 
3254
(define_insn "*andqi3_mem"
3255
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3256
        (and:QI (match_dup 0)
3257
                (match_operand:QI 1 "const_int_operand" "i,i")))
3258
   (clobber (match_scratch:HI 2 "=X,xy"))]
3259
  "TARGET_RELAX && !TARGET_M6812"
3260
  "*
3261
{
3262
  int val = INTVAL (operands[1]) & 0x0FF;
3263
 
3264
  if (val == 0x0ff)
3265
    {
3266
      cc_status = cc_prev_status;
3267
      return \"\";
3268
    }
3269
 
3270
  /* The bclr instruction uses an inverted mask.  */
3271
  operands[1] = GEN_INT ((~val) & 0x0FF);
3272
 
3273
  /* When destination is a global variable, generate a .relax instruction
3274
     and load the address in the clobber register.  That load can be
3275
     eliminated by the linker if the address is in page0.  */
3276
  if (which_alternative == 1)
3277
    {
3278
      rtx ops[3];
3279
 
3280
      ops[0] = operands[2];
3281
      ops[1] = XEXP (operands[0], 0);
3282
      ops[2] = gen_label_rtx ();
3283
      output_asm_insn (\".relax\\t%l2\", ops);
3284
      m68hc11_gen_movhi (insn, ops);
3285
      output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3286
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3287
                                 CODE_LABEL_NUMBER (ops[2]));
3288
      return \"\";
3289
    }
3290
  return \"bclr\\t%b0, %1\";
3291
}")
3292
 
3293
(define_insn "*andqi3_const"
3294
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3295
        (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3296
                (match_operand:QI 2 "const_int_operand" "")))]
3297
  ""
3298
  "*
3299
{
3300
  int val = INTVAL (operands[2]) & 0x0FF;
3301
 
3302
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3303
    return \"#\";
3304
 
3305
  if (val == 0x0ff)
3306
    {
3307
      cc_status = cc_prev_status;
3308
      return \"\";
3309
    }
3310
  if (!H_REG_P (operands[0]))
3311
    {
3312
      rtx ops[2];
3313
 
3314
      ops[0] = operands[0];
3315
      ops[1] = GEN_INT ((~val) & 0x0FF);
3316
      output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3317
      return \"\";
3318
    }
3319
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3320
    return \"andb\\t%b2\";
3321
  else if (DA_REG_P (operands[0]))
3322
    return \"anda\\t%b2\";
3323
  else
3324
    fatal_insn (\"Invalid operand in the instruction\", insn);
3325
}")
3326
 
3327
(define_insn "*andqi3_gen"
3328
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3329
        (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3330
             (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3331
  ""
3332
  "*
3333
{
3334
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3335
    return \"#\";
3336
 
3337
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3338
    return \"andb\\t%b2\";
3339
  else if (DA_REG_P (operands[0]))
3340
    return \"anda\\t%b2\";
3341
  else
3342
    fatal_insn (\"Invalid operand in the instruction\", insn);
3343
}")
3344
 
3345
;;--------------------------------------------------------------------
3346
;;- Bit set or instructions.
3347
;;--------------------------------------------------------------------
3348
 
3349
(define_insn_and_split "iordi3"
3350
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3351
        (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3352
                (match_operand:DI 2 "general_operand" "imu,imu")))
3353
   (clobber (match_scratch:HI 3 "=d,d"))]
3354
  ""
3355
  "#"
3356
  "reload_completed"
3357
  [(const_int 0)]
3358
  "m68hc11_split_logical (SImode, IOR, operands);
3359
   DONE;")
3360
 
3361
(define_insn_and_split "iorsi3"
3362
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
3363
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3364
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
3365
   (clobber (match_scratch:HI 3 "=X,d"))]
3366
  ""
3367
  "#"
3368
  "reload_completed"
3369
  [(const_int 0)]
3370
  "m68hc11_split_logical (HImode, IOR, operands);
3371
   DONE;")
3372
 
3373
(define_expand "iorhi3"
3374
  [(set (match_operand:HI 0 "register_operand" "")
3375
        (ior:HI (match_operand:HI 1 "register_operand" "")
3376
                (match_operand:HI 2 "splitable_operand" "")))]
3377
  ""
3378
  "")
3379
 
3380
(define_insn "*iorhi3_mem"
3381
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3382
        (ior:HI (match_dup 0)
3383
                (match_operand:HI 1 "const_int_operand" "")))
3384
   (clobber (match_scratch:HI 2 "=X,xy"))]
3385
  "TARGET_RELAX && !TARGET_M6812"
3386
  "*
3387
{
3388
  int val = INTVAL (operands[1]) & 0x0FFFF;
3389
 
3390
  if (val == 0)
3391
    {
3392
      cc_status = cc_prev_status;
3393
      return \"\";
3394
    }
3395
  CC_STATUS_INIT;
3396
  if (which_alternative == 1)
3397
    {
3398
      rtx ops[3];
3399
 
3400
      ops[0] = operands[2];
3401
      ops[1] = XEXP (operands[0], 0);
3402
      ops[2] = gen_label_rtx ();
3403
      output_asm_insn (\".relax\\t%l2\", ops);
3404
      m68hc11_gen_movhi (insn, ops);
3405
      if ((val & 0x0FF) != 0)
3406
        output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3407
 
3408
      if ((val & 0x0FF00) != 0)
3409
        output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3410
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3411
                                 CODE_LABEL_NUMBER (ops[2]));
3412
      return \"\";
3413
    }
3414
 
3415
  if ((val & 0x0FF) != 0)
3416
    output_asm_insn (\"bset\\t%b0, %b1\", operands);
3417
 
3418
  if ((val & 0x0FF00) != 0)
3419
    output_asm_insn (\"bset\\t%h0, %h1\", operands);
3420
 
3421
  return \"\";
3422
}")
3423
 
3424
(define_insn "*iorhi3_const"
3425
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3426
        (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3427
                (match_operand:HI 2 "const_int_operand" "")))]
3428
  ""
3429
  "*
3430
{
3431
  int val = INTVAL (operands[2]) & 0x0FFFF;
3432
 
3433
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3434
    return \"#\";
3435
 
3436
  if (val == 0)
3437
    {
3438
      cc_status = cc_prev_status;
3439
      return \"\";
3440
    }
3441
 
3442
  if ((val & 0x0FF) != 0)
3443
    {
3444
      if (!H_REG_P (operands[0]))
3445
        output_asm_insn (\"bset\\t%b0, %b2\", operands);
3446
      else
3447
        output_asm_insn (\"orab\\t%b2\", operands);
3448
    }
3449
 
3450
  if ((val & 0x0FF00) != 0)
3451
    {
3452
      if (!H_REG_P (operands[0]))
3453
         output_asm_insn (\"bset\\t%h0, %h2\", operands);
3454
      else
3455
         output_asm_insn (\"oraa\\t%h2\", operands);
3456
    }
3457
 
3458
  CC_STATUS_INIT;
3459
  return \"\";
3460
}")
3461
 
3462
(define_insn "*iorhi3_gen"
3463
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3464
        (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3465
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3466
  ""
3467
  "*
3468
{
3469
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3470
    return \"#\";
3471
 
3472
  CC_STATUS_INIT;
3473
  return \"oraa\\t%h2\\n\\torab\\t%b2\";
3474
}")
3475
 
3476
(define_expand "iorqi3"
3477
  [(set (match_operand:QI 0 "register_operand" "")
3478
        (ior:QI (match_operand:QI 1 "register_operand" "")
3479
                (match_operand:QI 2 "general_operand" "")))]
3480
  ""
3481
  "")
3482
 
3483
(define_insn "*iorqi3_mem"
3484
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3485
        (ior:QI (match_dup 0)
3486
                (match_operand:QI 1 "const_int_operand" "")))
3487
   (clobber (match_scratch:HI 2 "=X,xy"))]
3488
  "TARGET_RELAX && !TARGET_M6812"
3489
  "*
3490
{
3491
  int val = INTVAL (operands[1]) & 0x0FF;
3492
 
3493
  if (val == 0)
3494
    {
3495
      cc_status = cc_prev_status;
3496
      return \"\";
3497
    }
3498
  if (which_alternative == 1)
3499
    {
3500
      rtx ops[3];
3501
 
3502
      ops[0] = operands[2];
3503
      ops[1] = XEXP (operands[0], 0);
3504
      ops[2] = gen_label_rtx ();
3505
      output_asm_insn (\".relax\\t%l2\", ops);
3506
      m68hc11_gen_movhi (insn, ops);
3507
      output_asm_insn (\"bset\\t0,%2, %1\", operands);
3508
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3509
                                 CODE_LABEL_NUMBER (ops[2]));
3510
      return \"\";
3511
    }
3512
  return \"bset\\t%b0, %1\";
3513
}")
3514
 
3515
(define_insn "*iorqi3_const"
3516
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3517
        (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3518
                (match_operand:QI 2 "const_int_operand" "")))]
3519
  ""
3520
  "*
3521
{
3522
  int val = INTVAL (operands[2]) & 0x0FF;
3523
 
3524
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3525
    return \"#\";
3526
 
3527
  if (val == 0)
3528
    {
3529
      cc_status = cc_prev_status;
3530
      return \"\";
3531
    }
3532
  if (!H_REG_P (operands[0]))
3533
    {
3534
      return \"bset\\t%b0, %2\";
3535
    }
3536
 
3537
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3538
    return \"orab\\t%b2\";
3539
  else if (DA_REG_P (operands[0]))
3540
    return \"oraa\\t%b2\";
3541
  else
3542
    fatal_insn (\"Invalid operand in the instruction\", insn);
3543
}")
3544
 
3545
(define_insn "*iorqi3_gen"
3546
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3547
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3548
             (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3549
  ""
3550
  "*
3551
{
3552
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3553
    return \"#\";
3554
 
3555
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3556
    return \"orab\\t%b2\";
3557
  else if (DA_REG_P (operands[0]))
3558
    return \"oraa\\t%b2\";
3559
  else
3560
    fatal_insn (\"Invalid operand in the instruction\", insn);
3561
}")
3562
 
3563
 
3564
;;--------------------------------------------------------------------
3565
;;- xor instructions.
3566
;;--------------------------------------------------------------------
3567
 
3568
(define_insn_and_split "xordi3"
3569
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3570
        (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3571
                (match_operand:DI 2 "general_operand" "imu,imu")))
3572
   (clobber (match_scratch:HI 3 "=d,d"))]
3573
  ""
3574
  "#"
3575
  "reload_completed"
3576
  [(const_int 0)]
3577
  "m68hc11_split_logical (SImode, XOR, operands);
3578
   DONE;")
3579
 
3580
(define_insn_and_split "xorsi3"
3581
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
3582
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3583
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
3584
   (clobber (match_scratch:HI 3 "=X,d"))]
3585
  ""
3586
  "#"
3587
  "reload_completed"
3588
  [(const_int 0)]
3589
  "m68hc11_split_logical (HImode, XOR, operands);
3590
   DONE;")
3591
 
3592
(define_insn "xorhi3"
3593
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3594
        (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3595
                (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3596
  ""
3597
  "*
3598
{
3599
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3600
    return \"#\";
3601
 
3602
  if (GET_CODE (operands[2]) == CONST_INT)
3603
    {
3604
      int val = INTVAL (operands[2]) & 0x0FFFF;
3605
 
3606
      if (val == 0)
3607
        {
3608
          cc_status = cc_prev_status;
3609
          return \"\";
3610
        }
3611
      if ((val & 0x0FF) != 0)
3612
        {
3613
          output_asm_insn (\"eorb\\t%b2\", operands);
3614
        }
3615
      else if ((val & 0x0FF) == 0x0FF)
3616
        {
3617
          output_asm_insn (\"comb\", operands);
3618
        }
3619
 
3620
      if ((val & 0x0FF00) != 0)
3621
        {
3622
          output_asm_insn (\"eora\\t%h2\", operands);
3623
        }
3624
      else if ((val & 0x0FF00) == 0x0FF00)
3625
        {
3626
          output_asm_insn (\"coma\", operands);
3627
        }
3628
 
3629
      CC_STATUS_INIT;
3630
      return \"\";
3631
    }
3632
 
3633
  CC_STATUS_INIT;
3634
  return \"eora\\t%h2\\n\\teorb\\t%b2\";
3635
}")
3636
 
3637
(define_insn "xorqi3"
3638
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3639
        (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3640
             (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3641
  ""
3642
  "*
3643
{
3644
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3645
    return \"#\";
3646
 
3647
  if (GET_CODE (operands[2]) == CONST_INT)
3648
    {
3649
      int val = INTVAL (operands[2]) & 0x0FF;
3650
 
3651
      if (val == 0)
3652
        {
3653
          cc_status = cc_prev_status;
3654
          return \"\";
3655
        }
3656
      if (val == 0x0FF)
3657
        {
3658
          if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3659
            return \"comb\";
3660
          else
3661
            return \"coma\";
3662
        }
3663
    }
3664
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3665
    return \"eorb\\t%b2\";
3666
  else if (DA_REG_P (operands[0]))
3667
    return \"eora\\t%b2\";
3668
  else
3669
    fatal_insn (\"Invalid operand in the instruction\", insn);
3670
}")
3671
 
3672
;;--------------------------------------------------------------------
3673
;;- Bit set or instructions.
3674
;;--------------------------------------------------------------------
3675
 
3676
(define_insn_and_split "*logicalsi3_zexthi"
3677
  [(set (match_operand:SI 0 "register_operand" "=D")
3678
        (match_operator:SI 3 "m68hc11_logical_operator"
3679
                [(zero_extend:SI
3680
                     (match_operand:HI 1 "general_operand" "imudA"))
3681
                 (match_operand:SI 2 "general_operand" "Dimu")]))]
3682
  ""
3683
  "#"
3684
  "reload_completed"
3685
  [(set (reg:HI D_REGNUM) (match_dup 4))
3686
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3687
   (set (reg:HI X_REGNUM) (match_dup 6))]
3688
  "PUT_MODE (operands[3], HImode);
3689
   if (X_REG_P (operands[2]))
3690
     {
3691
       operands[5] = operands[1];
3692
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3693
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3694
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3695
     }
3696
   else
3697
     {
3698
       operands[4] = operands[1];
3699
       operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3700
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3701
     }
3702
   /* For an AND, make sure the high 16-bit part is cleared.  */
3703
   if (GET_CODE (operands[3]) == AND)
3704
     {
3705
       operands[6] = const0_rtx;
3706
     }
3707
   ")
3708
 
3709
(define_insn_and_split "*logicalsi3_zextqi"
3710
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3711
        (match_operator:SI 3 "m68hc11_logical_operator"
3712
                [(zero_extend:SI
3713
                     (match_operand:QI 1 "general_operand" "d,*A,imu"))
3714
                 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3715
  ""
3716
  "#"
3717
  "z_replacement_completed == 2"
3718
  [(set (reg:QI A_REGNUM) (match_dup 4))
3719
   (set (reg:QI D_REGNUM) (match_dup 7))
3720
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3721
   (set (reg:HI X_REGNUM) (match_dup 6))]
3722
  "PUT_MODE (operands[3], QImode);
3723
   if (X_REG_P (operands[2]))
3724
     {
3725
       operands[5] = operands[1];
3726
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3727
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3728
       operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3729
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3730
     }
3731
   else
3732
     {
3733
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3734
       operands[7] = operands[1];
3735
       operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3736
       operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3737
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3738
     }
3739
   /* For an AND, make sure the high 24-bit part is cleared.  */
3740
   if (GET_CODE (operands[3]) == AND)
3741
     {
3742
       operands[4] = const0_rtx;
3743
       operands[6] = const0_rtx;
3744
     }
3745
   ")
3746
 
3747
(define_insn_and_split "*logicalhi3_zexthi_ashift8"
3748
  [(set (match_operand:HI 0 "register_operand" "=d")
3749
        (match_operator:HI 3 "m68hc11_logical_operator"
3750
                [(zero_extend:HI
3751
                     (match_operand:QI 1 "general_operand" "imud*A"))
3752
                 (ashift:HI
3753
                     (match_operand:HI 2 "general_operand" "imud*A")
3754
                     (const_int 8))]))]
3755
  ""
3756
  "#"
3757
  "z_replacement_completed == 2"
3758
  [(set (reg:QI A_REGNUM) (match_dup 4))
3759
   (set (reg:QI B_REGNUM) (match_dup 5))]
3760
  "
3761
   if (GET_CODE (operands[3]) == AND)
3762
     {
3763
       emit_insn (gen_movhi (operands[0], const0_rtx));
3764
       DONE;
3765
     }
3766
   else
3767
     {
3768
       operands[5] = operands[1];
3769
       if (D_REG_P (operands[2]))
3770
         {
3771
           operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3772
         }
3773
       else
3774
         {
3775
           operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3776
         }
3777
     }
3778
  ")
3779
 
3780
(define_insn_and_split "*logicalhi3_zexthi"
3781
  [(set (match_operand:HI 0 "register_operand" "=d,d")
3782
        (match_operator:HI 3 "m68hc11_logical_operator"
3783
                [(zero_extend:HI
3784
                     (match_operand:QI 1 "general_operand" "imd*A,?u"))
3785
                 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3786
  ""
3787
  "#"
3788
  "z_replacement_completed == 2"
3789
  [(set (reg:QI B_REGNUM) (match_dup 6))
3790
   (set (reg:QI A_REGNUM) (match_dup 4))
3791
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3792
  "
3793
   PUT_MODE (operands[3], QImode);
3794
   if (D_REG_P (operands[2]))
3795
     {
3796
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3797
       operands[5] = operands[1];
3798
       operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3799
     }
3800
   else
3801
     {
3802
       operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3803
       operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3804
       if (D_REG_P (operands[1]))
3805
         operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3806
       else
3807
         operands[6] = operands[1];
3808
     }
3809
   /* For an AND, make sure the high 8-bit part is cleared.  */
3810
   if (GET_CODE (operands[3]) == AND)
3811
     {
3812
       operands[4] = const0_rtx;
3813
     }
3814
  ")
3815
 
3816
 
3817
(define_insn_and_split "*logicalsi3_silshr16"
3818
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3819
          (match_operator:SI 3 "m68hc11_logical_operator"
3820
              [(lshiftrt:SI
3821
                   (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3822
                   (const_int 16))
3823
                (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3824
  ""
3825
  "#"
3826
  "reload_completed"
3827
  [(set (reg:HI D_REGNUM) (match_dup 4))
3828
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3829
   (set (reg:HI X_REGNUM) (match_dup 6))]
3830
  "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3831
   if (X_REG_P (operands[2]))
3832
     {
3833
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3834
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3835
     }
3836
   else
3837
     {
3838
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3839
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3840
     }
3841
   PUT_MODE (operands[3], HImode);
3842
 
3843
   /* For an AND, make sure the high 16-bit part is cleared.  */
3844
   if (GET_CODE (operands[3]) == AND)
3845
     {
3846
       operands[6] = const0_rtx;
3847
     }
3848
")
3849
 
3850
(define_insn_and_split "*logicalsi3_silshl16"
3851
  [(set (match_operand:SI 0 "register_operand" "=D,D")
3852
          (match_operator:SI 3 "m68hc11_logical_operator"
3853
              [(ashift:SI
3854
                   (match_operand:SI 1 "general_operand" "uim,?D")
3855
                   (const_int 16))
3856
                (match_operand:SI 2 "general_operand" "0,0")]))]
3857
  ""
3858
  "#"
3859
  "z_replacement_completed == 2"
3860
  [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3861
   (set (reg:HI D_REGNUM) (match_dup 5))]
3862
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3863
   PUT_MODE (operands[3], HImode);
3864
 
3865
   if (GET_CODE (operands[3]) == AND)
3866
     operands[5] = const0_rtx;
3867
   else
3868
     operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3869
   ")
3870
 
3871
(define_insn_and_split "*logicalsi3_silshl16_zext"
3872
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3873
          (match_operator:SI 3 "m68hc11_logical_operator"
3874
              [(ashift:SI
3875
                  (zero_extend:SI
3876
                     (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3877
                  (const_int 16))
3878
            (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3879
  ""
3880
  "#"
3881
  ;; Must split before z register replacement
3882
  "reload_completed"
3883
  [(set (match_dup 4) (match_dup 5))
3884
   (set (match_dup 6) (match_dup 7))]
3885
  "
3886
    /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3887
   if (GET_CODE (operands[1]) == HARD_D_REGNUM
3888
       && GET_CODE (operands[3]) != AND)
3889
     {
3890
       /* This particular case is too early to be split before
3891
          Z register replacement because the cse-reg pass we do
3892
          does not recognize the 'swap_areg'.  It is ok to handle
3893
          this case after.  */
3894
       if (z_replacement_completed != 2)
3895
         {
3896
           FAIL;
3897
         }
3898
       emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3899
       emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3900
                                 gen_rtx_REG (HImode, HARD_X_REGNUM)));
3901
     }
3902
   operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3903
   operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3904
   operands[5] = operands[2];
3905
   operands[7] = operands[1];
3906
 
3907
   if (GET_CODE (operands[3]) == AND)
3908
     operands[5] = operands[7] = const0_rtx;
3909
   ")
3910
 
3911
;;--------------------------------------------------------------------
3912
;; 16-bit Arithmetic and logical operations on X and Y:
3913
;;
3914
;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3915
;;
3916
;; Operations on X or Y registers are split here.  Instructions are
3917
;; changed into:
3918
;;   - xgdx/xgdy instruction pattern,
3919
;;   - The same operation on register D,
3920
;;   - xgdx/xgdy instruction pattern.
3921
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3922
;; We also handle the case were the address register is used in both source
3923
;; operands, such as:
3924
;;
3925
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3926
;; or
3927
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3928
;;
3929
;;
3930
(define_split
3931
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3932
        (match_operator:HI 3 "m68hc11_arith_operator"
3933
            [(match_operand:HI 1 "hard_addr_reg_operand" "")
3934
             (match_operand:HI 2 "general_operand" "")]))]
3935
  "z_replacement_completed == 2
3936
   /* If we are adding a small constant to X or Y, it's
3937
     better to use one or several inx/iny instructions.  */
3938
   && !(GET_CODE (operands[3]) == PLUS
3939
        && ((TARGET_M6812
3940
             && (immediate_operand (operands[2], HImode)
3941
                 || hard_reg_operand (operands[2], HImode)))
3942
            || (GET_CODE (operands[2]) == CONST_INT
3943
                && INTVAL (operands[2]) >= -4
3944
                && INTVAL (operands[2]) <= 4)))"
3945
  [(set (match_dup 9) (match_dup 0))
3946
   (set (match_dup 4) (match_dup 5))
3947
   (set (match_dup 8) (match_dup 7))
3948
   (set (match_dup 0) (match_dup 1))
3949
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3950
              (set (match_dup 0) (reg:HI D_REGNUM))])
3951
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3952
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3953
              (set (match_dup 0) (reg:HI D_REGNUM))])]
3954
  "
3955
   operands[9] = operands[0];
3956
   /* For 68HC12, push the value on the stack and do the operation
3957
      with a pop.  */
3958
   if (TARGET_M6812
3959
       && m68hc11_non_shift_operator (operands[3], HImode)
3960
       && (H_REG_P (operands[2])
3961
           || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3962
               && reg_mentioned_p (operands[0], operands[2]))))
3963
     {
3964
       operands[4] = gen_rtx_MEM (HImode,
3965
                              gen_rtx_PRE_DEC (HImode,
3966
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3967
       operands[6] = gen_rtx_MEM (HImode,
3968
                              gen_rtx_POST_INC (HImode,
3969
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3970
       operands[5] = operands[2];
3971
       operands[8] = operands[7] = operands[0];
3972
     }
3973
   /* Save the operand2 in a temporary location and use it.  */
3974
   else if ((H_REG_P (operands[2])
3975
             || reg_mentioned_p  (operands[0], operands[2]))
3976
            && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3977
     {
3978
       if (GET_CODE (operands[3]) == MINUS
3979
           && reg_mentioned_p (operands[0], operands[2]))
3980
         {
3981
           operands[9] = gen_rtx_MEM (HImode,
3982
                              gen_rtx_PRE_DEC (HImode,
3983
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3984
           operands[1] = gen_rtx_MEM (HImode,
3985
                              gen_rtx_POST_INC (HImode,
3986
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3987
           operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3988
           operands[4] = operands[7] = operands[0];
3989
           operands[6] = operands[8];
3990
           operands[5] = operands[2];
3991
         }
3992
       else
3993
         {
3994
       operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3995
       operands[6] = operands[4];
3996
       if (!H_REG_P (operands[2]))
3997
         {
3998
           operands[5] = operands[0];
3999
           operands[7] = operands[2];
4000
           operands[8] = operands[0];
4001
         }
4002
       else
4003
         {
4004
           operands[5] = operands[2];
4005
           operands[8] = operands[7] = operands[0];
4006
         }
4007
         }
4008
     }
4009
   else
4010
     {
4011
       operands[4] = operands[5] = operands[0];
4012
       operands[6] = operands[2];
4013
       operands[8] = operands[7] = operands[0];
4014
     }
4015
   ")
4016
 
4017
(define_split
4018
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4019
        (match_operator:HI 3 "m68hc11_arith_operator"
4020
            [(match_operand:HI 1 "general_operand" "")
4021
             (match_operand:HI 2 "general_operand" "")]))]
4022
  "z_replacement_completed == 2
4023
   /* If we are adding a small constant to X or Y, it's
4024
     better to use one or several inx/iny instructions.  */
4025
   && !(GET_CODE (operands[3]) == PLUS
4026
        && ((TARGET_M6812
4027
            && (immediate_operand (operands[2], HImode)
4028
                || hard_reg_operand (operands[2], HImode)))
4029
            || (GET_CODE (operands[2]) == CONST_INT
4030
                && INTVAL (operands[2]) >= -4
4031
                && INTVAL (operands[2]) <= 4)))"
4032
  [(set (match_dup 0) (match_dup 1))
4033
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4034
              (set (match_dup 0) (reg:HI D_REGNUM))])
4035
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4036
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4037
              (set (match_dup 0) (reg:HI D_REGNUM))])]
4038
  "
4039
   ")
4040
 
4041
;;
4042
;; Next split handles the logical operations on D register with
4043
;; another hard register for the second operand.  For this, we
4044
;; have to save the second operand in a scratch location and use
4045
;; it instead.  This must be supported because in some (rare) cases
4046
;; the second operand can come in a hard register and the reload
4047
;; pass doesn't know how to reload it in a memory location.
4048
;;
4049
;;      PLUS MINUS AND IOR XOR
4050
;;
4051
;; The shift operators are special and must not appear here.
4052
;;
4053
(define_split
4054
  [(set (match_operand:HI 0 "d_register_operand" "")
4055
        (match_operator:HI 3 "m68hc11_non_shift_operator"
4056
            [(match_operand:HI 1 "d_register_operand" "")
4057
             (match_operand:HI 2 "hard_reg_operand" "")]))]
4058
  "TARGET_M6811
4059
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4060
  [(set (match_dup 4) (match_dup 2))
4061
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4062
  "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4063
 
4064
;;
4065
;; For 68HC12, push the operand[2] value on the stack and do the
4066
;; logical/arithmetic operation with a pop.
4067
;;
4068
(define_split
4069
  [(set (match_operand:HI 0 "d_register_operand" "")
4070
        (match_operator:HI 3 "m68hc11_non_shift_operator"
4071
            [(match_operand:HI 1 "d_register_operand" "")
4072
             (match_operand:HI 2 "hard_reg_operand" "")]))]
4073
  "TARGET_M6812
4074
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4075
  [(set (match_dup 4) (match_dup 2))
4076
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4077
  "operands[4] = gen_rtx_MEM (HImode,
4078
                          gen_rtx_PRE_DEC (HImode,
4079
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4080
   operands[5] = gen_rtx_MEM (HImode,
4081
                          gen_rtx_POST_INC (HImode,
4082
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4083
   ")
4084
 
4085
;;--------------------------------------------------------------------
4086
;; 16-bit Unary operations on X and Y:
4087
;;
4088
;;              NOT NEG
4089
;;
4090
;; Operations on X or Y registers are split here.  Instructions are
4091
;; changed into:
4092
;;   - xgdx/xgdy instruction pattern,
4093
;;   - The same operation on register D,
4094
;;   - xgdx/xgdy instruction pattern.
4095
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4096
;; We also handle the case were the address register is used in both source
4097
;; operands, such as:
4098
;;
4099
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4100
;; or
4101
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4102
;;
4103
(define_split
4104
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4105
        (match_operator:HI 2 "m68hc11_unary_operator"
4106
            [(match_operand 1 "general_operand" "")]))]
4107
  "z_replacement_completed == 2"
4108
  [(set (match_dup 4) (match_dup 5))
4109
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4110
              (set (match_dup 0) (reg:HI D_REGNUM))])
4111
   (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4112
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4113
              (set (match_dup 0) (reg:HI D_REGNUM))])]
4114
  "
4115
{
4116
  if ((H_REG_P (operands[1])
4117
       && !rtx_equal_p (operands[0], operands[1]))
4118
      || reg_mentioned_p (operands[0], operands[1]))
4119
    {
4120
      /* Move to the destination register, before the xgdx.  */
4121
      operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
4122
                             REGNO (operands[0]));
4123
      operands[5] = operands[1];
4124
 
4125
      /* Apply the operation on D.  */
4126
      operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4127
    }
4128
  else
4129
    {
4130
      /* Generate a copy to same register (nop).  */
4131
      operands[4] = operands[5] = operands[0];
4132
      operands[3] = operands[1];
4133
    }
4134
}")
4135
 
4136
;;
4137
;; 8-bit operations on address registers.
4138
;;
4139
;; We have to take care that the address register is not used for the
4140
;; source of operand2. If operand2 is the D register, we have to save
4141
;; that register in a temporary location.
4142
;;
4143
;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4144
;;
4145
(define_split
4146
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4147
        (match_operator:QI 3 "m68hc11_arith_operator"
4148
            [(match_operand:QI 1 "hard_addr_reg_operand" "")
4149
             (match_operand:QI 2 "general_operand" "")]))]
4150
  "z_replacement_completed == 2
4151
   /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4152
      incqi pattern generates a better code.  */
4153
   && !(GET_CODE (operands[3]) == PLUS
4154
        && GET_CODE (operands[2]) == CONST_INT
4155
        && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4156
  [(set (match_dup 5) (match_dup 6))
4157
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4158
              (set (match_dup 4) (reg:HI D_REGNUM))])
4159
   (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4160
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4161
              (set (match_dup 4) (reg:HI D_REGNUM))])]
4162
  "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4163
 
4164
   /* For the second operand is a hard register or if the address
4165
      register appears in the source, we have to save the operand[2]
4166
      value in a temporary location and then use that temp.
4167
      Otherwise, it's ok and we generate a (set (D) (D)) that
4168
      will result in a nop.  */
4169
   if (H_REG_P (operands[2]))
4170
     {
4171
       operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4172
       operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4173
       operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4174
     }
4175
   else if (reg_mentioned_p (operands[0], operands[2]))
4176
     {
4177
       operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4178
       operands[6] = operands[2];
4179
       operands[7] = operands[5];
4180
     }
4181
   else
4182
     {
4183
       operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4184
       operands[7] = operands[2];
4185
     }
4186
  ")
4187
 
4188
;;
4189
;; Next split handles the logical operations on D register with
4190
;; another hard register for the second operand.  For this, we
4191
;; have to save the second operand in a scratch location and use
4192
;; it instead.  This must be supported because in some (rare) cases
4193
;; the second operand can come in a hard register and the reload
4194
;; pass doesn't know how to reload it in a memory location.
4195
;;
4196
;;      PLUS MINUS AND IOR XOR
4197
;;
4198
;; The shift operators are special and must not appear here.
4199
;;
4200
(define_split
4201
  [(set (match_operand:QI 0 "d_register_operand" "")
4202
        (match_operator:QI 3 "m68hc11_non_shift_operator"
4203
            [(match_operand:QI 1 "d_register_operand" "")
4204
             (match_operand:QI 2 "hard_reg_operand" "")]))]
4205
  "reload_completed"
4206
  [(set (match_dup 5) (match_dup 6))
4207
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4208
  "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4209
   operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4210
   operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4211
 
4212
;;--------------------------------------------------------------------
4213
;; 8-bit Unary operations on X and Y:
4214
;;
4215
;;              NOT NEG
4216
;;
4217
;; Operations on X or Y registers are split here.  Instructions are
4218
;; changed into:
4219
;;   - xgdx/xgdy instruction pattern,
4220
;;   - The same operation on register D,
4221
;;   - xgdx/xgdy instruction pattern.
4222
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4223
;; We also handle the case were the address register is used in both source
4224
;; operands, such as:
4225
;;
4226
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4227
;; or
4228
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4229
;;
4230
(define_split
4231
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4232
        (match_operator:QI 2 "m68hc11_unary_operator"
4233
            [(match_operand:QI 1 "general_operand" "")]))]
4234
  "z_replacement_completed == 2"
4235
  [(set (match_dup 4) (match_dup 5))
4236
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4237
              (set (match_dup 3) (reg:HI D_REGNUM))])
4238
   (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4239
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4240
              (set (match_dup 3) (reg:HI D_REGNUM))])]
4241
  "
4242
{
4243
  operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4244
  if ((H_REG_P (operands[1])
4245
       && !rtx_equal_p (operands[0], operands[1]))
4246
      || reg_mentioned_p (operands[0], operands[1]))
4247
    {
4248
      /* Move to the destination register, before the xgdx.  */
4249
      operands[4] = operands[0];
4250
      operands[5] = operands[1];
4251
 
4252
      /* Apply the operation on D.  */
4253
      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4254
    }
4255
  else
4256
    {
4257
      operands[4] = operands[5] = operands[0];
4258
      operands[6] = operands[1];
4259
    }
4260
}")
4261
 
4262
 
4263
;;--------------------------------------------------------------------
4264
;;-  Complements
4265
;;--------------------------------------------------------------------
4266
 
4267
(define_expand "negdi2"
4268
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
4269
        (neg:DI (match_operand:DI 1 "general_operand" "")))]
4270
  ""
4271
  "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4272
   DONE;")
4273
 
4274
 
4275
(define_insn "negsi2"
4276
  [(set (match_operand:SI 0 "register_operand" "=D")
4277
        (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4278
  ""
4279
  "*
4280
{
4281
  rtx ops[1];
4282
 
4283
  CC_STATUS_INIT;
4284
 
4285
  /* With -Os or without -O, use a special library call.  */
4286
  if (optimize_size || optimize == 0)
4287
    return \"bsr\\t___negsi2\";
4288
 
4289
  ops[0] = gen_label_rtx ();
4290
 
4291
  /* 32-bit complement and add 1.  */
4292
  output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4293
  output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4294
  output_asm_insn (\"bne\\t%l0\", ops);
4295
  output_asm_insn (\"inx\", operands);
4296
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4297
  return \"\";
4298
}")
4299
 
4300
(define_insn "neghi2"
4301
  [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4302
        (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4303
  ""
4304
  "@
4305
   coma\\n\\tcomb\\n\\taddd\\t#1
4306
   clra\\n\\tclrb\\n\\tsubd\\t%1
4307
   xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4308
 
4309
(define_insn "negqi2"
4310
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4311
        (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4312
  ""
4313
  "@
4314
   negb
4315
   neg\\t%b0
4316
   neg\\t%b0
4317
   #")
4318
 
4319
;;
4320
;; - 32-bit complement.  GCC knows how to translate them but providing a
4321
;; pattern generates better/smaller code.
4322
;;
4323
(define_expand "one_cmpldi2"
4324
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
4325
        (not:DI (match_operand:DI 1 "general_operand" "")))]
4326
  ""
4327
  "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4328
   DONE;")
4329
 
4330
(define_insn "one_cmplsi2"
4331
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4332
        (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4333
   (clobber (match_scratch:HI 2 "=X,d,X"))]
4334
  ""
4335
  "@
4336
   bsr\\t___one_cmplsi2
4337
   #
4338
   #")
4339
 
4340
(define_insn "one_cmplhi2"
4341
  [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4342
        (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4343
  ""
4344
  "@
4345
   comb\\n\\tcoma
4346
   com\\t%b0\\n\\tcom\\t%h0
4347
   #
4348
   com\\t%b0\\n\\tcom\\t%h0")
4349
 
4350
(define_insn "one_cmplqi2"
4351
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4352
        (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4353
  ""
4354
  "@
4355
   comb
4356
   com\\t%b0
4357
   #
4358
   com\\t%b0")
4359
 
4360
(define_split /* "*one_cmplsi2" */
4361
  [(set (match_operand:SI 0 "non_push_operand" "")
4362
        (not:SI (match_dup 0)))
4363
   (clobber (match_scratch:HI 1 ""))]
4364
  "z_replacement_completed == 2
4365
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4366
  [(set (match_dup 2) (not:HI (match_dup 2)))
4367
   (set (match_dup 3) (not:HI (match_dup 3)))]
4368
  "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4369
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4370
 
4371
(define_split /* "*one_cmplsi2" */
4372
  [(set (match_operand:SI 0 "non_push_operand" "")
4373
        (not:SI (match_operand:SI 1 "non_push_operand" "")))
4374
   (clobber (match_operand:HI 2 "d_register_operand" ""))]
4375
  "z_replacement_completed == 2
4376
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4377
  [(set (match_dup 2) (match_dup 3))
4378
   (set (match_dup 2) (not:HI (match_dup 2)))
4379
   (set (match_dup 4) (match_dup 2))
4380
   (set (match_dup 2) (match_dup 5))
4381
   (set (match_dup 2) (not:HI (match_dup 2)))
4382
   (set (match_dup 6) (match_dup 2))]
4383
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4384
   operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4385
   operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4386
   operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4387
 
4388
;;--------------------------------------------------------------------
4389
;;- arithmetic shifts
4390
;;--------------------------------------------------------------------
4391
;;
4392
;; Provide some 64-bit shift patterns.
4393
(define_expand "ashldi3"
4394
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4395
                     (ashift:DI (match_operand:DI 1 "general_operand" "")
4396
                                (match_operand:HI 2 "general_operand" "")))
4397
              (clobber (match_scratch:HI 3 ""))])]
4398
   ""
4399
   "
4400
{
4401
  if (GET_CODE (operands[2]) != CONST_INT
4402
      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4403
    {
4404
      FAIL;
4405
    }
4406
}")
4407
 
4408
(define_insn_and_split "*ashldi3_const32"
4409
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4410
        (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4411
                   (const_int 32)))
4412
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
4413
   ""
4414
   "#"
4415
   "reload_completed"
4416
   [(const_int 0)]
4417
   "/* Move the lowpart in the highpart first in case the shift
4418
       is applied on the source.  */
4419
    if (IS_STACK_PUSH (operands[0]))
4420
      {
4421
         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4422
                             const0_rtx, operands[2]);
4423
 
4424
         /* Adjust first operand if it uses SP so that we take into
4425
            account the above push.  Can occur only for 68HC12.  */
4426
         if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4427
                              operands[1]))
4428
           operands[1] = adjust_address (operands[1],
4429
                                         GET_MODE (operands[0]), 4);
4430
      }
4431
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4432
                        m68hc11_gen_lowpart (SImode, operands[1]),
4433
                        operands[2]);
4434
    if (!IS_STACK_PUSH (operands[0]))
4435
      {
4436
        m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4437
                            const0_rtx, operands[2]);
4438
      }
4439
    DONE;")
4440
 
4441
(define_insn_and_split "*ashldi3_const1"
4442
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4443
        (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4444
                   (const_int 1)))
4445
   (clobber (match_scratch:HI 2 "=d,d,d"))]
4446
   ""
4447
   "#"
4448
   "z_replacement_completed == 2"
4449
   [(set (match_dup 2) (match_dup 3))
4450
    (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4451
    (set (match_dup 4) (match_dup 2))
4452
 
4453
    (set (match_dup 2) (match_dup 5))
4454
    (parallel [(set (match_dup 2)
4455
                       (rotate:HI (match_dup 2) (const_int 1)))
4456
               (clobber (reg:HI CC_REGNUM))])
4457
    (set (match_dup 6) (match_dup 2))
4458
 
4459
    (set (match_dup 2) (match_dup 7))
4460
    (parallel [(set (match_dup 2)
4461
                       (rotate:HI (match_dup 2) (const_int 1)))
4462
               (clobber (reg:HI CC_REGNUM))])
4463
    (set (match_dup 8) (match_dup 2))
4464
 
4465
    (set (match_dup 2) (match_dup 9))
4466
    (parallel [(set (match_dup 2)
4467
                       (rotate:HI (match_dup 2) (const_int 1)))
4468
               (clobber (reg:HI CC_REGNUM))])
4469
    (set (match_dup 10) (match_dup 2))]
4470
   "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4471
    operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4472
    operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4473
 
4474
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4475
    operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4476
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4477
 
4478
    operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4479
    operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4480
    operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4481
 
4482
    operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4483
    operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4484
    operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4485
 
4486
(define_insn "addsi_silshr16"
4487
  [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4488
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4489
                                (const_int 16))
4490
                   (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4491
  ""
4492
  "#")
4493
 
4494
(define_split
4495
  [(set (match_operand:SI 0 "register_operand" "")
4496
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4497
                                (const_int 16))
4498
                   (match_operand:SI 2 "general_operand" "")))]
4499
  "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4500
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4501
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4502
                                            (const_int 0))
4503
                                   (reg:HI CC_REGNUM)))]
4504
  "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4505
 
4506
(define_split
4507
  [(set (match_operand:SI 0 "register_operand" "")
4508
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4509
                                (const_int 16))
4510
                   (match_operand:SI 2 "general_operand" "")))]
4511
  "z_replacement_completed == 2 && X_REG_P (operands[1])"
4512
  [(set (reg:HI D_REGNUM) (match_dup 5))
4513
   (set (reg:HI X_REGNUM) (match_dup 3))
4514
   (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4515
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4516
                                            (const_int 0))
4517
                                   (reg:HI CC_REGNUM)))]
4518
  "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4519
   if (X_REG_P (operands[2]))
4520
     {
4521
       operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4522
       operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4523
     }
4524
   else
4525
     {
4526
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4527
       operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4528
     }
4529
")
4530
 
4531
(define_insn "addsi_ashift16"
4532
  [(set (match_operand:SI 0 "register_operand" "=D")
4533
          (plus:SI
4534
                   (mult:SI (match_operand:SI 2 "general_operand" "uim")
4535
                            (const_int 65536))
4536
                (match_operand:SI 1 "general_operand" "0")))
4537
   (clobber (match_scratch:HI 3 "=X"))]
4538
  "0"
4539
  "#")
4540
 
4541
(define_split
4542
  [(set (match_operand:SI 0 "register_operand" "")
4543
          (plus:SI
4544
                   (mult:SI (match_operand:SI 2 "general_operand" "")
4545
                            (const_int 65536))
4546
                   (match_operand:SI 1 "general_operand" "")))
4547
   (clobber (match_scratch:HI 3 "=X"))]
4548
  "0 && reload_completed && z_replacement_completed == 2"
4549
  [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4550
  "
4551
{
4552
  operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4553
}")
4554
 
4555
(define_insn_and_split "addsi_andshr16"
4556
  [(set (match_operand:SI 0 "register_operand" "=D")
4557
          (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4558
                           (const_int 65535))
4559
                   (match_operand:SI 2 "general_operand" "0")))]
4560
  ""
4561
  "#"
4562
  "z_replacement_completed == 2"
4563
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4564
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4565
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4566
 
4567
;;
4568
;; 32-bit shifts are made by a small library routine that uses
4569
;; a specific passing convention for parameters (for efficiency reasons).
4570
;;
4571
;; [D + X] -> Value to be shifted
4572
;; Y       -> Shift count
4573
;;
4574
;; The shift count is clobbered by the routine.
4575
;;
4576
(define_expand "ashlsi3"
4577
  [(parallel
4578
       [(set (match_operand:SI 0 "register_operand" "")
4579
             (match_operand:SI 1 "general_operand" ""))
4580
        (clobber (scratch:HI))])
4581
   (parallel
4582
     [(set (match_dup 0) (ashift:SI (match_dup 0)
4583
                         (match_operand:HI 2 "nonmemory_operand" "")))
4584
      (clobber (scratch:HI))])]
4585
   ""
4586
   "")
4587
 
4588
(define_split
4589
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
4590
        (ashift:SI (match_operand:SI 1 "general_operand" "")
4591
                   (const_int 16)))
4592
   (clobber (match_scratch:HI 3 ""))]
4593
   ""
4594
  [(set (match_dup 2) (match_dup 3))
4595
   (set (match_dup 4) (const_int 0))]
4596
   "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4597
    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4598
    operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4599
 
4600
(define_insn "*ashlsi3_const16"
4601
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4602
        (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4603
                   (const_int 16)))
4604
   (clobber (match_scratch:HI 2 "=X,X,X"))]
4605
   ""
4606
   "#")
4607
 
4608
(define_insn_and_split "*ashlsi3_const16_zexthi"
4609
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4610
        (ashift:SI (zero_extend:HI
4611
                        (match_operand:HI 1 "general_operand" "duim*A"))
4612
                   (const_int 16)))
4613
   (clobber (match_scratch:HI 2 "=X"))]
4614
   ""
4615
   "#"
4616
   "reload_completed"
4617
   [(set (reg:HI X_REGNUM) (match_dup 1))
4618
    (set (reg:HI D_REGNUM) (const_int 0))]
4619
   "")
4620
 
4621
(define_insn "*ashlsi3_const1"
4622
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4623
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4624
                   (const_int 1)))
4625
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4626
   ""
4627
   "*
4628
{
4629
  CC_STATUS_INIT;
4630
  if (X_REG_P (operands[1]))
4631
    {
4632
      return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4633
    }
4634
  else
4635
    {
4636
      rtx ops[2];
4637
 
4638
      ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4639
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4640
      m68hc11_gen_movhi (insn, ops);
4641
      output_asm_insn (\"lsld\", ops);
4642
      if (!X_REG_P (operands[0]))
4643
        {
4644
          ops[1] = ops[0];
4645
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4646
          m68hc11_gen_movhi (insn, ops);
4647
          ops[0] = ops[1];
4648
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4649
          m68hc11_gen_movhi (insn, ops);
4650
        }
4651
      else
4652
        {
4653
          /* Load the high part in X in case the source operand
4654
             uses X as a memory pointer.  */
4655
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4656
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4657
          m68hc11_gen_movhi (insn, ops);
4658
          output_asm_insn (\"xgdx\", ops);
4659
        }
4660
      output_asm_insn (\"rolb\", ops);
4661
      output_asm_insn (\"rola\", ops);
4662
      if (!X_REG_P (operands[0]))
4663
        {
4664
          ops[1] = ops[0];
4665
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4666
          m68hc11_gen_movhi (insn, ops);
4667
        }
4668
      else
4669
        {
4670
          output_asm_insn (\"xgdx\", ops);
4671
        }
4672
      return \"\";
4673
    }
4674
}")
4675
 
4676
(define_insn "*ashlsi3_const"
4677
  [(set (match_operand:SI 0 "register_operand" "+D")
4678
        (ashift:SI (match_dup 0)
4679
                   (match_operand:HI 1 "const_int_operand" "")))
4680
   (clobber (match_scratch:HI 2 "=y"))]
4681
   "TARGET_M6811 /* See *ashlsi3 note.  */"
4682
   "*
4683
{
4684
  CC_STATUS_INIT;
4685
  return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4686
}")
4687
 
4688
(define_insn "*ashlsi3"
4689
  [(set (match_operand:SI 0 "register_operand" "+D,D")
4690
        (ashift:SI (match_dup 0)
4691
                   (match_operand:HI 1 "general_operand" "y,mi")))
4692
   (clobber (match_scratch:HI 2 "=1,X"))]
4693
   ""
4694
   "*
4695
{
4696
  CC_STATUS_INIT;
4697
 
4698
  /* There is a reload problem if we don't accept 'm' for the shift value.
4699
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4700
     and this conflicts with all reloads.  Since X, Y, Z are used there
4701
     is not enough register in class A_REGS.
4702
 
4703
     Assuming that 'operands[1]' does not refer to the stack (which
4704
     is true for 68hc11 only, we save temporary the value of Y.
4705
 
4706
     For 68HC12 we must also accept a constant because Z register is
4707
     disabled when compiling with -fomit-frame-pointer.  We can come up
4708
     with a reload problem and the *lshrsi3_const pattern was disabled
4709
     for that reason.  */
4710
  if (!Y_REG_P (operands[2]))
4711
    {
4712
      rtx ops[1];
4713
      int y_dead = dead_register_here (insn, iy_reg);
4714
 
4715
      ops[0] = operands[1];
4716
      if (y_dead == 0)
4717
        {
4718
          output_asm_insn (\"pshy\", operands);
4719
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4720
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4721
        }
4722
      output_asm_insn (\"ldy\\t%0\", ops);
4723
      output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4724
      return y_dead == 0 ? \"puly\" : \"\";
4725
    }
4726
  return \"bsr\\t___ashlsi3\";
4727
}")
4728
 
4729
(define_expand "ashlhi3"
4730
  [(set (match_operand:HI 0 "register_operand" "")
4731
        (ashift:HI (match_operand:HI 1 "register_operand" "")
4732
                   (match_operand:HI 2 "general_operand" "")))]
4733
   ""
4734
   "
4735
{
4736
  if (GET_CODE (operands[2]) != CONST_INT)
4737
    {
4738
      rtx scratch = gen_reg_rtx (HImode);
4739
      emit_move_insn (scratch, operands[2]);
4740
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
4741
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4742
                            operand0,
4743
                            gen_rtx_ASHIFT (HImode,
4744
                                        operand1, scratch)),
4745
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
4746
      DONE;
4747
    }
4748
}")
4749
 
4750
(define_insn "*ashlhi3_const1"
4751
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4752
        (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4753
                   (const_int 1)))]
4754
  ""
4755
  "*
4756
{
4757
  if (A_REG_P (operands[0]))
4758
    return \"#\";
4759
 
4760
  if (D_REG_P (operands[0]))
4761
    {
4762
      return \"asld\";
4763
    }
4764
 
4765
  output_asm_insn (\"asl\\t%b0\", operands);
4766
  output_asm_insn (\"rol\\t%h0\", operands);
4767
  CC_STATUS_INIT;
4768
  return \"\";
4769
}")
4770
 
4771
 
4772
(define_insn "*ashlhi3_2"
4773
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
4774
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4775
                   (match_operand:HI 2 "register_operand" "+x,+d")))
4776
   (clobber (match_dup 2))]
4777
  ""
4778
  "*
4779
{
4780
  if (A_REG_P (operands[0]))
4781
    return \"#\";
4782
 
4783
  CC_STATUS_INIT;
4784
  return \"bsr\\t___lshlhi3\";
4785
}")
4786
 
4787
(define_insn "*ashlhi3"
4788
  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4789
        (ashift:HI (match_dup 0)
4790
                   (match_operand:HI 1 "register_operand" "+x")))
4791
   (clobber (match_dup 1))]
4792
  ""
4793
  "*
4794
{
4795
  CC_STATUS_INIT;
4796
  return \"bsr\\t___lshlhi3\";
4797
}")
4798
 
4799
(define_insn "*ashlhi3"
4800
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4801
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4802
                   (match_operand:HI 2 "const_int_operand" "")))]
4803
  ""
4804
  "*
4805
{
4806
  int   i;
4807
 
4808
  if (A_REG_P (operands[0]))
4809
    return \"#\";
4810
 
4811
  i = INTVAL (operands[2]);
4812
  if (i >= 8)
4813
    {
4814
      CC_STATUS_INIT;
4815
      output_asm_insn (\"tba\", operands);
4816
      if (i == 15)
4817
        {
4818
          output_asm_insn (\"rora\", operands);
4819
          output_asm_insn (\"anda\\t#0\", operands);
4820
          output_asm_insn (\"rora\", operands);
4821
        }
4822
      else
4823
        while (i != 8 )
4824
          {
4825
            output_asm_insn (\"asla\", operands);
4826
            i--;
4827
          }
4828
      return \"clrb\";
4829
    }
4830
  for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4831
    {
4832
      output_asm_insn (\"asld\", operands);
4833
    }
4834
  return \"asld\";
4835
}")
4836
 
4837
(define_expand "ashlqi3"
4838
  [(set (match_operand:QI 0 "register_operand" "")
4839
        (ashift:QI (match_operand:QI 1 "register_operand" "")
4840
                   (match_operand:QI 2 "general_operand" "")))]
4841
   ""
4842
   "")
4843
 
4844
(define_insn "*ashlqi3_const1"
4845
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4846
        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4847
                   (const_int 1)))]
4848
  ""
4849
  "@
4850
   aslb
4851
   asl\\t%b0
4852
   asl\\t%b0
4853
   asl%0
4854
   #")
4855
 
4856
(define_insn "*ashlqi3_const"
4857
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4858
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4859
                   (match_operand:QI 2 "const_int_operand" "")))]
4860
  ""
4861
  "*
4862
{
4863
  int i;
4864
  const char* insn_code;
4865
 
4866
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4867
    insn_code = \"aslb\";
4868
  else if (DA_REG_P (operands[0]))
4869
    insn_code = \"asla\";
4870
  else
4871
    return \"#\";
4872
 
4873
  i = INTVAL (operands[2]);
4874
  if (i >= 8)
4875
    {
4876
      if (DA_REG_P (operands[0]))
4877
        return \"clra\";
4878
      else
4879
        return \"clrb\";
4880
    }
4881
  else if (i == 7)
4882
    {
4883
      if (DA_REG_P (operands[0]))
4884
        {
4885
          output_asm_insn (\"rora\", operands);
4886
          output_asm_insn (\"ldaa\\t#0\", operands);
4887
          return \"rora\";
4888
        }
4889
      else
4890
        {
4891
          output_asm_insn (\"rorb\", operands);
4892
          output_asm_insn (\"ldab\\t#0\", operands);
4893
          return \"rorb\";
4894
        }
4895
    }
4896
  else if (i == 6)
4897
    {
4898
      if (DA_REG_P (operands[0]))
4899
        {
4900
          output_asm_insn (\"rora\", operands);
4901
          output_asm_insn (\"rora\", operands);
4902
          output_asm_insn (\"rora\", operands);
4903
          return \"anda\\t#0xC0\";
4904
        }
4905
      else
4906
        {
4907
          output_asm_insn (\"rorb\", operands);
4908
          output_asm_insn (\"rorb\", operands);
4909
          output_asm_insn (\"rorb\", operands);
4910
          return \"andb\\t#0xC0\";
4911
        }
4912
    }
4913
  while (--i >= 0)
4914
    {
4915
      output_asm_insn (insn_code, operands);
4916
    }
4917
  return \"\";
4918
}")
4919
 
4920
(define_insn "*ashlqi3"
4921
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4922
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4923
                     (match_operand:QI 2 "nonimmediate_operand"
4924
                                         "m*u*d*A,m*u*d*A,m*u")))]
4925
  ""
4926
  "*
4927
{
4928
  rtx ops[2];
4929
 
4930
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4931
    return \"#\";
4932
 
4933
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4934
  ops[1] = operands[2];
4935
  m68hc11_gen_movqi (insn, ops);
4936
 
4937
  CC_STATUS_INIT;
4938
  return \"bsr\\t___lshlqi3\";
4939
}")
4940
 
4941
(define_expand "ashrhi3"
4942
  [(set (match_operand:HI 0 "register_operand" "")
4943
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4944
                     (match_operand:HI 2 "general_operand" "")))]
4945
   ""
4946
   "
4947
{
4948
  if (GET_CODE (operands[2]) != CONST_INT)
4949
    {
4950
      rtx scratch = gen_reg_rtx (HImode);
4951
 
4952
      emit_move_insn (scratch, operands[2]);
4953
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
4954
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4955
                                operand0,
4956
                                gen_rtx_ASHIFTRT (HImode,
4957
                                        operand1, scratch)),
4958
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
4959
       DONE;
4960
    }
4961
}")
4962
 
4963
(define_insn "*ashrhi3_const1"
4964
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4965
        (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4966
                     (const_int 1)))]
4967
  ""
4968
  "*
4969
{
4970
  if (A_REG_P (operands[0]))
4971
    return \"#\";
4972
 
4973
  CC_STATUS_INIT;
4974
  if (D_REG_P (operands[0]))
4975
    {
4976
      return \"asra\\n\\trorb\";
4977
    }
4978
 
4979
  output_asm_insn (\"asr\\t%h0\", operands);
4980
  output_asm_insn (\"ror\\t%b0\", operands);
4981
  return \"\";
4982
}")
4983
 
4984
 
4985
(define_insn "*ashrhi3_const"
4986
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4987
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4988
                     (match_operand:HI 2 "const_int_operand" "")))]
4989
  ""
4990
  "*
4991
{
4992
  rtx ops[2];
4993
  int val = INTVAL (operands[2]);
4994
 
4995
  if (A_REG_P (operands[0]))
4996
    return \"#\";
4997
 
4998
  if (val >= 15)
4999
    {
5000
      ops[0] = gen_label_rtx ();
5001
 
5002
      output_asm_insn (\"clrb\", operands);
5003
      output_asm_insn (\"rola\", operands);
5004
 
5005
        /* Clear A without clearing the carry flag.  */
5006
      output_asm_insn (\"tba\", operands);
5007
      output_asm_insn (\"bcc\\t%l0\", ops);
5008
      output_asm_insn (\"coma\", operands);
5009
      output_asm_insn (\"comb\", operands);
5010
 
5011
      CC_STATUS_INIT;
5012
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5013
                                 CODE_LABEL_NUMBER (ops[0]));
5014
      return \"\";
5015
    }
5016
  if (val >= 8)
5017
    {
5018
      ops[0] = gen_label_rtx ();
5019
 
5020
      output_asm_insn (\"tab\", operands);
5021
      output_asm_insn (\"clra\", operands);
5022
      output_asm_insn (\"tstb\", operands);
5023
      output_asm_insn (\"bge\\t%l0\", ops);
5024
      output_asm_insn (\"deca\", operands);
5025
 
5026
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5027
                                 CODE_LABEL_NUMBER (ops[0]));
5028
 
5029
      val -= 8;
5030
 
5031
      while (val > 0)
5032
        {
5033
          output_asm_insn (\"asrb\", operands);
5034
          val--;
5035
        }
5036
        /* Status is ok.  */
5037
      return \"\";
5038
    }
5039
  if (val == 7)
5040
    {
5041
      ops[0] = gen_label_rtx ();
5042
      output_asm_insn (\"rolb\", operands);
5043
      output_asm_insn (\"rola\", operands);
5044
      output_asm_insn (\"tab\", operands);
5045
      output_asm_insn (\"anda\\t#0\", operands);
5046
      output_asm_insn (\"bcc\\t%l0\", ops);
5047
      output_asm_insn (\"coma\", ops);
5048
 
5049
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5050
                                 CODE_LABEL_NUMBER (ops[0]));
5051
      return \"\";
5052
    }
5053
  while (val > 0)
5054
    {
5055
      output_asm_insn (\"asra\", operands);
5056
      output_asm_insn (\"rorb\", operands);
5057
      val--;
5058
    }
5059
  CC_STATUS_INIT;
5060
 
5061
  return \"\";
5062
}")
5063
 
5064
(define_insn "*ashrhi3"
5065
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
5066
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5067
                     (match_operand:HI 2 "register_operand" "+x,+d")))
5068
   (clobber (match_dup 2))]
5069
  ""
5070
  "*
5071
{
5072
  if (A_REG_P (operands[0]))
5073
    return \"#\";
5074
 
5075
  output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5076
  return \"\";
5077
}")
5078
 
5079
(define_expand "ashrsi3"
5080
  [(parallel
5081
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5082
        (clobber (scratch:HI))])
5083
   (parallel
5084
       [(set (match_operand:SI 0 "register_operand" "")
5085
                (ashiftrt:SI (match_dup 0)
5086
                             (match_operand:HI 2 "general_operand" "")))
5087
        (clobber (scratch:HI))])]
5088
   ""
5089
   "")
5090
 
5091
(define_insn "*ashrsi3_const"
5092
  [(set (match_operand:SI 0 "register_operand" "+D")
5093
        (ashiftrt:SI (match_dup 0)
5094
                     (match_operand:HI 1 "const_int_operand" "")))
5095
   (clobber (match_scratch:HI 2 "=y"))]
5096
   "TARGET_M6811 /* See *ashrsi3 note.  */"
5097
   "*
5098
{
5099
  CC_STATUS_INIT;
5100
  return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5101
}")
5102
 
5103
(define_insn "*ashrsi3"
5104
  [(set (match_operand:SI 0 "register_operand" "+D,D")
5105
        (ashiftrt:SI (match_dup 0)
5106
                     (match_operand:HI 1 "general_operand" "y,mi")))
5107
   (clobber (match_scratch:HI 2 "=1,X"))]
5108
   ""
5109
   "*
5110
{
5111
  CC_STATUS_INIT;
5112
  /* There is a reload problem if we don't accept 'm' for the shift value.
5113
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5114
     and this conflicts with all reloads.  Since X, Y, Z are used there
5115
     is not enough register in class A_REGS.
5116
 
5117
     Assuming that 'operands[1]' does not refer to the stack (which
5118
     is true for 68hc11 only, we save temporary the value of Y.
5119
 
5120
     For 68HC12 we must also accept a constant because Z register is
5121
     disabled when compiling with -fomit-frame-pointer.  We can come up
5122
     with a reload problem and the *lshrsi3_const pattern was disabled
5123
     for that reason.  */
5124
  if (!Y_REG_P (operands[2]))
5125
    {
5126
      rtx ops[1];
5127
      int y_dead = dead_register_here (insn, iy_reg);
5128
 
5129
      ops[0] = operands[1];
5130
      if (y_dead == 0)
5131
        {
5132
          output_asm_insn (\"pshy\", operands);
5133
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5134
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5135
        }
5136
      output_asm_insn (\"ldy\\t%0\", ops);
5137
      output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5138
      return y_dead == 0 ? \"puly\" : \"\";
5139
    }
5140
  return \"bsr\\t___ashrsi3\";
5141
}")
5142
 
5143
(define_expand "ashrqi3"
5144
  [(set (match_operand:QI 0 "register_operand" "")
5145
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5146
                     (match_operand:QI 2 "general_operand" "")))]
5147
   ""
5148
   "")
5149
 
5150
(define_insn "*ashrqi3_const1"
5151
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5152
        (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5153
                     (const_int 1)))]
5154
  ""
5155
  "@
5156
   asrb
5157
   asr\\t%b0
5158
   asr\\t%b0
5159
   asr%0
5160
   #")
5161
 
5162
(define_insn "*ashrqi3_const"
5163
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5164
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5165
                     (match_operand:QI 2 "const_int_operand" "")))]
5166
  ""
5167
  "*
5168
{
5169
  int i;
5170
  const char* insn_code;
5171
 
5172
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5173
    insn_code = \"asrb\";
5174
  else if (DA_REG_P (operands[0]))
5175
    insn_code = \"asra\";
5176
  else
5177
    return \"#\";
5178
 
5179
  i = INTVAL (operands[2]);
5180
  if (i > 8)
5181
    i = 8;
5182
  while (--i >= 0)
5183
    {
5184
      output_asm_insn (insn_code, operands);
5185
    }
5186
  return \"\";
5187
}")
5188
 
5189
(define_insn "*ashrqi3"
5190
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5191
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5192
                     (match_operand:QI 2 "nonimmediate_operand"
5193
                                         "m*u*d*A,m*u*d*A,m*u")))]
5194
  ""
5195
  "*
5196
{
5197
  rtx ops[2];
5198
 
5199
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5200
    return \"#\";
5201
 
5202
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5203
  ops[1] = operands[2];
5204
  m68hc11_gen_movqi (insn, ops);
5205
 
5206
  CC_STATUS_INIT;
5207
  return \"bsr\\t___ashrqi3\";
5208
}")
5209
 
5210
;;--------------------------------------------------------------------
5211
;; logical shift instructions
5212
;;--------------------------------------------------------------------
5213
(define_expand "lshrdi3"
5214
  [(parallel [(set (match_operand:DI 0 "general_operand" "")
5215
                     (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5216
                                  (match_operand:HI 2 "general_operand" "")))
5217
              (clobber (match_scratch:HI 3 ""))])]
5218
   ""
5219
   "
5220
{
5221
  if (GET_CODE (operands[2]) != CONST_INT
5222
     || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5223
         && INTVAL (operands[2]) != 1))
5224
    {
5225
      FAIL;
5226
    }
5227
}")
5228
 
5229
(define_insn_and_split "*lshrdi3_const32"
5230
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5231
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5232
                     (const_int 32)))
5233
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
5234
   ""
5235
   "#"
5236
   "reload_completed"
5237
   [(const_int 0)]
5238
   "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5239
                        m68hc11_gen_highpart (SImode, operands[1]),
5240
                        operands[2]);
5241
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5242
                        const0_rtx, operands[2]);
5243
    DONE;")
5244
 
5245
(define_insn "*lshrdi3_const63"
5246
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5247
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5248
                     (match_operand:DI 2 "const_int_operand" "")))
5249
   (clobber (match_scratch:HI 3 "=d,d"))]
5250
   "INTVAL (operands[2]) >= 48"
5251
   "#")
5252
 
5253
(define_split
5254
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
5255
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5256
                     (match_operand:DI 2 "const_int_operand" "")))
5257
   (clobber (match_scratch:HI 3 "=d"))]
5258
   "z_replacement_completed && INTVAL (operands[2]) >= 56"
5259
   [(set (reg:QI D_REGNUM) (match_dup 9))
5260
    (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5261
    (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5262
    (set (match_dup 4) (reg:HI D_REGNUM))
5263
    (set (reg:QI D_REGNUM) (const_int 0))
5264
    (set (match_dup 5) (reg:HI D_REGNUM))
5265
    (set (match_dup 6) (reg:HI D_REGNUM))
5266
    (set (match_dup 7) (reg:HI D_REGNUM))]
5267
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5268
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5269
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5270
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5271
 
5272
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5273
    operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5274
    operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5275
 
5276
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5277
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5278
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5279
 
5280
(define_split
5281
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
5282
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5283
                     (match_operand:DI 2 "const_int_operand" "")))
5284
   (clobber (match_scratch:HI 3 "=d"))]
5285
   "z_replacement_completed && INTVAL (operands[2]) >= 48
5286
    && INTVAL (operands[2]) < 56"
5287
   [(set (reg:HI D_REGNUM) (match_dup 9))
5288
    (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5289
    (set (match_dup 4) (reg:HI D_REGNUM))
5290
    (set (reg:HI D_REGNUM) (const_int 0))
5291
    (set (match_dup 5) (reg:HI D_REGNUM))
5292
    (set (match_dup 6) (reg:HI D_REGNUM))
5293
    (set (match_dup 7) (reg:HI D_REGNUM))]
5294
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5295
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5296
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5297
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5298
 
5299
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5300
    operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5301
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5302
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5303
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5304
 
5305
(define_insn_and_split "*lshrdi_const1"
5306
  [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5307
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5308
                     (const_int 1)))
5309
   (clobber (match_scratch:HI 2 "=d,d"))]
5310
   ""
5311
   "#"
5312
   "z_replacement_completed == 2"
5313
   [(set (match_dup 2) (match_dup 3))
5314
    (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5315
    (set (match_dup 4) (match_dup 2))
5316
 
5317
    (set (match_dup 2) (match_dup 5))
5318
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5319
               (clobber (reg:HI CC_REGNUM))])
5320
    (set (match_dup 6) (match_dup 2))
5321
 
5322
    (set (match_dup 2) (match_dup 7))
5323
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5324
               (clobber (reg:HI CC_REGNUM))])
5325
    (set (match_dup 8) (match_dup 2))
5326
 
5327
    (set (match_dup 2) (match_dup 9))
5328
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5329
               (clobber (reg:HI CC_REGNUM))])
5330
    (set (match_dup 10) (match_dup 2))]
5331
   "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5332
    operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5333
    operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5334
 
5335
    operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5336
    operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5337
    operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5338
 
5339
    operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5340
    operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5341
    operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5342
 
5343
    operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5344
    operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5345
    operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5346
 
5347
(define_expand "lshrsi3"
5348
  [(parallel
5349
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5350
        (clobber (scratch:HI))])
5351
   (parallel
5352
       [(set (match_operand:SI 0 "register_operand" "")
5353
             (lshiftrt:SI (match_dup 0)
5354
                          (match_operand:HI 2 "general_operand" "")))
5355
        (clobber (scratch:HI))])]
5356
   ""
5357
   "")
5358
 
5359
(define_split
5360
  [(set (match_operand:SI 0 "non_push_operand" "")
5361
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5362
                     (const_int 16)))
5363
   (clobber (match_scratch:HI 3 ""))]
5364
   "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5365
  [(set (match_dup 2) (match_dup 3))
5366
   (set (match_dup 4) (const_int 0))]
5367
   "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5368
    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5369
    operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5370
 
5371
(define_insn "*lshrsi3_const16"
5372
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5373
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5374
                     (const_int 16)))
5375
   (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5376
   ""
5377
   "@
5378
    #
5379
    xgdx\\n\\tldx\\t#0
5380
    #
5381
    #")
5382
 
5383
(define_insn "*lshrsi3_const1"
5384
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5385
        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5386
                     (const_int 1)))
5387
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5388
   ""
5389
   "*
5390
{
5391
  CC_STATUS_INIT;
5392
  if (X_REG_P (operands[1]))
5393
    {
5394
      return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5395
    }
5396
  else
5397
    {
5398
      rtx ops[2];
5399
 
5400
      ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5401
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5402
      m68hc11_gen_movhi (insn, ops);
5403
      output_asm_insn (\"lsrd\", ops);
5404
      if (!X_REG_P (operands[0]))
5405
        {
5406
          ops[1] = ops[0];
5407
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5408
          m68hc11_gen_movhi (insn, ops);
5409
          ops[0] = ops[1];
5410
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5411
          m68hc11_gen_movhi (insn, ops);
5412
        }
5413
      else
5414
        {
5415
          /* Load the lowpart in X in case the operands is some N,x.  */
5416
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5417
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5418
          m68hc11_gen_movhi (insn, ops);
5419
          output_asm_insn (\"xgdx\", ops);
5420
        }
5421
      output_asm_insn (\"rora\", ops);
5422
      output_asm_insn (\"rorb\", ops);
5423
      if (!X_REG_P (operands[0]))
5424
        {
5425
          ops[1] = ops[0];
5426
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5427
          m68hc11_gen_movhi (insn, ops);
5428
        }
5429
      return \"\";
5430
    }
5431
}")
5432
 
5433
(define_insn "*lshrsi3_const"
5434
  [(set (match_operand:SI 0 "register_operand" "+D")
5435
        (lshiftrt:SI (match_dup 0)
5436
                     (match_operand:HI 1 "const_int_operand" "")))
5437
   (clobber (match_scratch:HI 2 "=y"))]
5438
   "TARGET_M6811 /* See *lshrsi3 note.  */"
5439
   "*
5440
{
5441
  CC_STATUS_INIT;
5442
  return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5443
}")
5444
 
5445
(define_insn "*lshrsi3"
5446
  [(set (match_operand:SI 0 "register_operand" "+D,D")
5447
        (lshiftrt:SI (match_dup 0)
5448
                     (match_operand:HI 1 "general_operand" "y,mi")))
5449
   (clobber (match_scratch:HI 2 "=1,X"))]
5450
   ""
5451
   "*
5452
{
5453
  CC_STATUS_INIT;
5454
  /* There is a reload problem if we don't accept 'm' for the shift value.
5455
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5456
     and this conflicts with all reloads.  Since X, Y, Z are used there
5457
     is not enough register in class A_REGS.
5458
 
5459
     Assuming that 'operands[1]' does not refer to the stack (which
5460
     is true for 68hc11 only, we save temporary the value of Y.
5461
 
5462
     For 68HC12 we must also accept a constant because Z register is
5463
     disabled when compiling with -fomit-frame-pointer.  We can come up
5464
     with a reload problem and the *lshrsi3_const pattern was disabled
5465
     for that reason.  */
5466
  if (!Y_REG_P (operands[2]))
5467
    {
5468
      rtx ops[1];
5469
      int y_dead = dead_register_here (insn, iy_reg);
5470
 
5471
      ops[0] = operands[1];
5472
      if (y_dead == 0)
5473
        {
5474
          output_asm_insn (\"pshy\", operands);
5475
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5476
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5477
        }
5478
      output_asm_insn (\"ldy\\t%0\", ops);
5479
      output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5480
      return y_dead == 0 ? \"puly\" : \"\";
5481
    }
5482
  return \"bsr\\t___lshrsi3\";
5483
}")
5484
 
5485
(define_expand "lshrhi3"
5486
  [(set (match_operand:HI 0 "register_operand" "")
5487
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5488
                     (match_operand:HI 2 "general_operand" "")))]
5489
   ""
5490
   "
5491
{
5492
  if (GET_CODE (operands[2]) != CONST_INT)
5493
    {
5494
      rtx scratch = gen_reg_rtx (HImode);
5495
      operand1 = force_reg (HImode, operand1);
5496
 
5497
      emit_move_insn (scratch, operands[2]);
5498
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
5499
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5500
                                        operand0,
5501
                                        gen_rtx_LSHIFTRT (HImode,
5502
                                                operand1, scratch)),
5503
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
5504
     DONE;
5505
  }
5506
}")
5507
 
5508
(define_insn "lshrhi3_const1"
5509
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5510
        (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5511
                     (const_int 1)))]
5512
  ""
5513
  "*
5514
{
5515
  if (A_REG_P (operands[0]))
5516
    return \"#\";
5517
 
5518
  if (D_REG_P (operands[0]))
5519
    return \"lsrd\";
5520
 
5521
  CC_STATUS_INIT;
5522
  return \"lsr\\t%h0\\n\\tror\\t%b0\";
5523
}")
5524
 
5525
(define_insn "lshrhi3_const"
5526
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5527
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5528
                     (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5529
  ""
5530
  "*
5531
{
5532
  int val = INTVAL (operands[2]);
5533
 
5534
  if (A_REG_P (operands[0]))
5535
    return \"#\";
5536
 
5537
  if (val >= 8)
5538
    {
5539
      if (val == 8)
5540
        CC_STATUS_INIT;
5541
 
5542
      if (!H_REG_P (operands[1]))
5543
        {
5544
          output_asm_insn (\"clra\", operands);
5545
          output_asm_insn (\"ldab\\t%h1\", operands);
5546
        }
5547
      else if (A_REG_P (operands[1]))
5548
        {
5549
          output_asm_insn (\"st%1\\t%t0\", operands);
5550
          output_asm_insn (\"ldab\\t%t0\", operands);
5551
          output_asm_insn (\"clra\", operands);
5552
        }
5553
      else
5554
        {
5555
          output_asm_insn (\"tab\", operands);
5556
          output_asm_insn (\"clra\", operands);
5557
        }
5558
      val -= 8;
5559
      switch (val)
5560
        {
5561
        case 7:
5562
          output_asm_insn (\"rolb\", operands);
5563
          output_asm_insn (\"tab\", operands);
5564
          output_asm_insn (\"rolb\", operands);
5565
          break;
5566
 
5567
        case 6:
5568
          output_asm_insn (\"rolb\", operands);
5569
          output_asm_insn (\"rolb\", operands);
5570
          output_asm_insn (\"rolb\", operands);
5571
          output_asm_insn (\"andb\\t#3\", operands);
5572
          break;
5573
 
5574
        default:
5575
           while (val > 0)
5576
             {
5577
                val --;
5578
                output_asm_insn (\"lsrb\", operands);
5579
             }
5580
           break;
5581
        }
5582
      return \"\";
5583
    }
5584
 
5585
  if (!D_REG_P (operands[1]))
5586
    m68hc11_gen_movhi (insn, operands);
5587
  switch (val)
5588
    {
5589
    case 7:
5590
      output_asm_insn (\"rolb\", operands);
5591
      output_asm_insn (\"tab\", operands);
5592
      output_asm_insn (\"rolb\", operands);
5593
      output_asm_insn (\"rola\", operands);
5594
      output_asm_insn (\"rola\", operands);
5595
      output_asm_insn (\"anda\\t#1\", operands);
5596
      CC_STATUS_INIT;
5597
      break;
5598
 
5599
    default:
5600
      while (val > 0)
5601
        {
5602
          val --;
5603
          output_asm_insn (\"lsrd\", operands);
5604
        }
5605
     }
5606
  return \"\";
5607
}")
5608
 
5609
(define_insn "*lshrhi3"
5610
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
5611
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5612
                     (match_operand:HI 2 "register_operand" "+x,+d")))
5613
   (clobber (match_dup 2))]
5614
  ""
5615
  "*
5616
{
5617
  if (A_REG_P (operands[0]))
5618
    return \"#\";
5619
 
5620
  return \"bsr\\t___lshrhi3\";
5621
}")
5622
 
5623
(define_expand "lshrqi3"
5624
  [(set (match_operand:QI 0 "register_operand" "")
5625
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5626
                     (match_operand:QI 2 "general_operand" "")))]
5627
   ""
5628
   "")
5629
 
5630
(define_insn "*lshrqi3_const1"
5631
  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5632
        (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5633
                     (const_int 1)))]
5634
  ""
5635
  "@
5636
   lsr\\t%b0
5637
   lsrb
5638
   lsr\\t%b0
5639
   lsr%0
5640
   #")
5641
 
5642
(define_insn "*lshrqi3_const"
5643
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5644
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5645
                     (match_operand:QI 2 "const_int_operand" "")))]
5646
  ""
5647
  "*
5648
{
5649
  int i;
5650
  const char* insn_code;
5651
 
5652
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5653
    insn_code = \"lsrb\";
5654
  else if (DA_REG_P (operands[0]))
5655
    insn_code = \"lsra\";
5656
  else
5657
    return \"#\";
5658
 
5659
  i = INTVAL (operands[2]);
5660
  if (i >= 8)
5661
    {
5662
      if (DA_REG_P (operands[0]))
5663
        return \"clra\";
5664
      else
5665
        return \"clrb\";
5666
    }
5667
  else if (i == 7)
5668
    {
5669
      if (DA_REG_P (operands[0]))
5670
        {
5671
          output_asm_insn (\"rola\", operands);
5672
          output_asm_insn (\"ldaa\\t#0\", operands);
5673
          return \"rola\";
5674
        }
5675
      else
5676
        {
5677
          output_asm_insn (\"rolb\", operands);
5678
          output_asm_insn (\"ldab\\t#0\", operands);
5679
          return \"rolb\";
5680
        }
5681
    }
5682
  else if (i == 6)
5683
    {
5684
      if (DA_REG_P (operands[0]))
5685
        {
5686
          output_asm_insn (\"rola\", operands);
5687
          output_asm_insn (\"rola\", operands);
5688
          output_asm_insn (\"rola\", operands);
5689
          return \"anda\\t#3\";
5690
        }
5691
      else
5692
        {
5693
          output_asm_insn (\"rolb\", operands);
5694
          output_asm_insn (\"rolb\", operands);
5695
          output_asm_insn (\"rolb\", operands);
5696
          return \"andb\\t#3\";
5697
        }
5698
    }
5699
  while (--i >= 0)
5700
    {
5701
      output_asm_insn (insn_code, operands);
5702
    }
5703
  return \"\";
5704
}")
5705
 
5706
(define_insn "*lshrqi3"
5707
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5708
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5709
                     (match_operand:QI 2 "nonimmediate_operand"
5710
                                         "m*u*d*A,m*u*d*A,m*u")))]
5711
  ""
5712
  "*
5713
{
5714
  rtx ops[2];
5715
 
5716
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5717
    return \"#\";
5718
 
5719
  CC_STATUS_INIT;
5720
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5721
  ops[1] = operands[2];
5722
  m68hc11_gen_movqi (insn, ops);
5723
 
5724
  if (!optimize || optimize_size)
5725
    {
5726
      return \"bsr\\t___lshrqi3\";
5727
    }
5728
 
5729
  ops[0] = gen_label_rtx ();
5730
  ops[1] = gen_label_rtx ();
5731
  output_asm_insn (\"ble\\t%l1\", ops);
5732
 
5733
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5734
                             CODE_LABEL_NUMBER (ops[0]));
5735
 
5736
  output_asm_insn (\"lsrb\", operands);
5737
  output_asm_insn (\"deca\", operands);
5738
  output_asm_insn (\"bne\\t%l0\", ops);
5739
 
5740
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5741
                             CODE_LABEL_NUMBER (ops[1]));
5742
  return \"\";
5743
}")
5744
 
5745
(define_insn "*rotlqi3_with_carry"
5746
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
5747
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5748
                   (reg:QI CC_REGNUM)))]
5749
  ""
5750
  "*
5751
{
5752
  if (DA_REG_P (operands[0]))
5753
    return \"rola\";
5754
  else
5755
    return \"rolb\";
5756
}")
5757
 
5758
(define_insn "*rotlhi3_with_carry"
5759
  [(set (match_operand:HI 0 "register_operand" "=d")
5760
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
5761
                   (const_int 1)))
5762
   (clobber (reg:HI CC_REGNUM))]
5763
  ""
5764
  "*
5765
{
5766
  CC_STATUS_INIT;
5767
  return \"rolb\\n\\trola\";
5768
}")
5769
 
5770
(define_insn "*rotrhi3_with_carry"
5771
  [(set (match_operand:HI 0 "register_operand" "=d")
5772
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5773
                     (const_int 1)))
5774
   (clobber (reg:HI CC_REGNUM))]
5775
  ""
5776
  "*
5777
{
5778
  CC_STATUS_INIT;
5779
  return \"rora\\n\\trorb\";
5780
}")
5781
 
5782
(define_insn "rotlqi3"
5783
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
5784
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5785
                   (match_operand:QI 2 "const_int_operand" "i,i")))]
5786
  ""
5787
  "*
5788
{
5789
  m68hc11_gen_rotate (ROTATE, insn, operands);
5790
  return \"\";
5791
}")
5792
 
5793
(define_insn "rotrqi3"
5794
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
5795
        (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5796
                     (match_operand:QI 2 "const_int_operand" "i,i")))]
5797
  ""
5798
  "*
5799
{
5800
  m68hc11_gen_rotate (ROTATERT, insn, operands);
5801
  return \"\";
5802
}")
5803
 
5804
(define_expand "rotlhi3"
5805
  [(set (match_operand:HI 0 "register_operand" "")
5806
        (rotate:HI (match_operand:HI 1 "register_operand" "")
5807
                   (match_operand:HI 2 "general_operand" "")))]
5808
   ""
5809
   "
5810
{
5811
  if (GET_CODE (operands[2]) != CONST_INT)
5812
    {
5813
      rtx scratch = gen_reg_rtx (HImode);
5814
      operand1 = force_reg (HImode, operand1);
5815
 
5816
      emit_move_insn (scratch, operands[2]);
5817
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
5818
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5819
                                        operand0,
5820
                                        gen_rtx_ROTATE (HImode,
5821
                                                operand1, scratch)),
5822
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
5823
      DONE;
5824
    }
5825
}")
5826
 
5827
(define_insn "rotlhi3_const"
5828
  [(set (match_operand:HI 0 "register_operand" "=d")
5829
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
5830
                   (match_operand:HI 2 "const_int_operand" "i")))]
5831
  ""
5832
  "*
5833
{
5834
  m68hc11_gen_rotate (ROTATE, insn, operands);
5835
  return \"\";
5836
}")
5837
 
5838
(define_insn "*rotlhi3"
5839
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
5840
        (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5841
                   (match_operand:HI 2 "general_operand" "+x,+d")))
5842
   (clobber (match_dup 2))]
5843
  ""
5844
  "*
5845
{
5846
  if (A_REG_P (operands[0]))
5847
    return \"#\";
5848
 
5849
  return \"bsr\\t___rotlhi3\";
5850
}")
5851
 
5852
(define_expand "rotrhi3"
5853
  [(set (match_operand:HI 0 "register_operand" "")
5854
        (rotatert:HI (match_operand:HI 1 "general_operand" "")
5855
                     (match_operand:HI 2 "general_operand" "")))]
5856
   ""
5857
   "
5858
{
5859
  if (GET_CODE (operands[2]) != CONST_INT)
5860
    {
5861
      rtx scratch = gen_reg_rtx (HImode);
5862
      operand1 = force_reg (HImode, operand1);
5863
 
5864
      emit_move_insn (scratch, operands[2]);
5865
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
5866
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5867
                                        operand0,
5868
                                        gen_rtx_ROTATERT (HImode,
5869
                                                operand1, scratch)),
5870
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
5871
      DONE;
5872
    }
5873
}")
5874
 
5875
(define_insn "rotrhi3_const"
5876
  [(set (match_operand:HI 0 "register_operand" "=d")
5877
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5878
                     (match_operand:HI 2 "const_int_operand" "i")))]
5879
  ""
5880
  "*
5881
{
5882
  m68hc11_gen_rotate (ROTATERT, insn, operands);
5883
  return \"\";
5884
}")
5885
 
5886
(define_insn "*rotrhi3"
5887
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
5888
        (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5889
                     (match_operand:HI 2 "general_operand" "+x,+d")))
5890
   (clobber (match_dup 2))]
5891
  ""
5892
  "*
5893
{
5894
  if (A_REG_P (operands[0]))
5895
    return \"#\";
5896
 
5897
  return \"bsr\\t___rotrhi3\";
5898
}")
5899
 
5900
;; Split a shift operation on an address register in a shift
5901
;; on D_REGNUM.
5902
(define_split /* "*rotrhi3_addr" */
5903
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5904
        (match_operator:HI 3 "m68hc11_shift_operator"
5905
            [(match_operand:HI 1 "register_operand" "")
5906
             (match_operand:HI 2 "register_operand" "")]))
5907
   (clobber (match_dup 2))]
5908
  "z_replacement_completed == 2"
5909
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5910
              (set (match_dup 0) (reg:HI D_REGNUM))])
5911
   (parallel [(set (reg:HI D_REGNUM)
5912
                   (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5913
              (clobber (match_dup 0))])
5914
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5915
              (set (match_dup 0) (reg:HI D_REGNUM))])]
5916
  "")
5917
 
5918
;;--------------------------------------------------------------------
5919
;;-  68HC12 Decrement/Increment and branch
5920
;;--------------------------------------------------------------------
5921
;; These patterns are used by loop optimization as well as peephole2
5922
;; They must handle reloading themselves and the scratch register
5923
;; is used for that.  Even if we accept memory operand, we must not
5924
;; accept them on the predicate because it might create too many reloads.
5925
;; (specially on HC12 due to its auto-incdec addressing modes).
5926
;;
5927
(define_expand "decrement_and_branch_until_zero"
5928
  [(parallel [(set (pc)
5929
                   (if_then_else
5930
                    (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5931
                                 (const_int 0))
5932
                        (const_int 1))
5933
                    (label_ref (match_operand 1 "" ""))
5934
                    (pc)))
5935
              (set (match_dup 0)
5936
                   (plus:HI (match_dup 0)
5937
                            (const_int -1)))
5938
              (clobber (match_scratch:HI 2 ""))])]
5939
  "TARGET_M6812"
5940
  "")
5941
 
5942
(define_expand "doloop_end"
5943
  [(use (match_operand 0 "" ""))        ; loop pseudo
5944
   (use (match_operand 1 "" ""))        ; iterations; zero if unknown
5945
   (use (match_operand 2 "" ""))        ; max iterations
5946
   (use (match_operand 3 "" ""))        ; loop level
5947
   (use (match_operand 4 "" ""))]       ; label
5948
  "TARGET_M6812"
5949
  "
5950
{
5951
  /* Reject non-constant loops as it generates bigger code due to
5952
     the handling of the loop register.  We can do better by using
5953
     the peephole2 dbcc/ibcc patterns.  */
5954
  if (INTVAL (operands[1]) == 0)
5955
    {
5956
      FAIL;
5957
    }
5958
 
5959
  /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5960
     the operator and its operands are not relevant.  */
5961
  if (GET_MODE (operands[0]) == HImode)
5962
    {
5963
      emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5964
                                               gen_rtx_NE (HImode,
5965
                                                           operands[0],
5966
                                                           const1_rtx),
5967
                                               operands[4]));
5968
      DONE;
5969
    }
5970
  if (GET_MODE (operands[0]) == QImode)
5971
    {
5972
      emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5973
                                               gen_rtx_NE (QImode,
5974
                                                           operands[0],
5975
                                                           const1_rtx),
5976
                                               operands[4]));
5977
      DONE;
5978
    }
5979
 
5980
  FAIL;
5981
}")
5982
 
5983
;; Decrement-and-branch insns.
5984
(define_insn "m68hc12_dbcc_dec_hi"
5985
  [(set (pc)
5986
        (if_then_else
5987
          (match_operator 1 "m68hc11_eq_compare_operator"
5988
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5989
              (const_int 1)])
5990
         (label_ref (match_operand 2 "" ""))
5991
         (pc)))
5992
   (set (match_dup 0)
5993
        (plus:HI (match_dup 0) (const_int -1)))
5994
   (clobber (match_scratch:HI 3 "=X,dxy"))]
5995
  "TARGET_M6812"
5996
  "*
5997
{
5998
  if (!H_REG_P (operands[0]))
5999
    return \"#\";
6000
 
6001
  CC_STATUS_INIT;
6002
  if (GET_CODE (operands[1]) == EQ)
6003
    return \"dbeq\\t%0,%l2\";
6004
  else
6005
    return \"dbne\\t%0,%l2\";
6006
}")
6007
 
6008
;; Decrement-and-branch insns.
6009
(define_insn "m68hc12_dbcc_inc_hi"
6010
  [(set (pc)
6011
        (if_then_else
6012
          (match_operator 1 "m68hc11_eq_compare_operator"
6013
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6014
              (const_int -1)])
6015
         (label_ref (match_operand 2 "" ""))
6016
         (pc)))
6017
   (set (match_dup 0)
6018
        (plus:HI (match_dup 0) (const_int 1)))
6019
   (clobber (match_scratch:HI 3 "=X,dxy"))]
6020
  "TARGET_M6812"
6021
  "*
6022
{
6023
  if (!H_REG_P (operands[0]))
6024
    return \"#\";
6025
 
6026
  CC_STATUS_INIT;
6027
  if (GET_CODE (operands[1]) == EQ)
6028
    return \"ibeq\\t%0,%l2\";
6029
  else
6030
    return \"ibeq\\t%0,%l2\";
6031
}")
6032
 
6033
;; Decrement-and-branch (QImode).
6034
(define_insn "m68hc12_dbcc_dec_qi"
6035
  [(set (pc)
6036
        (if_then_else
6037
          (match_operator 1 "m68hc11_eq_compare_operator"
6038
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6039
              (const_int 1)])
6040
         (label_ref (match_operand 2 "" ""))
6041
         (pc)))
6042
   (set (match_dup 0)
6043
        (plus:QI (match_dup 0) (const_int -1)))
6044
   (clobber (match_scratch:QI 3 "=X,d"))]
6045
  "TARGET_M6812"
6046
  "*
6047
{
6048
  if (!D_REG_P (operands[0]))
6049
    return \"#\";
6050
 
6051
  CC_STATUS_INIT;
6052
  if (GET_CODE (operands[1]) == EQ)
6053
    return \"dbeq\\tb,%l2\";
6054
  else
6055
    return \"dbne\\tb,%l2\";
6056
}")
6057
 
6058
;; Increment-and-branch (QImode).
6059
(define_insn "m68hc12_dbcc_inc_qi"
6060
  [(set (pc)
6061
        (if_then_else
6062
          (match_operator 1 "m68hc11_eq_compare_operator"
6063
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6064
              (const_int -1)])
6065
         (label_ref (match_operand 2 "" ""))
6066
         (pc)))
6067
   (set (match_dup 0)
6068
        (plus:QI (match_dup 0) (const_int 1)))
6069
   (clobber (match_scratch:QI 3 "=X,d"))]
6070
  "TARGET_M6812"
6071
  "*
6072
{
6073
  if (!D_REG_P (operands[0]))
6074
    return \"#\";
6075
 
6076
  CC_STATUS_INIT;
6077
  if (GET_CODE (operands[1]) == EQ)
6078
    return \"ibeq\\tb,%l2\";
6079
  else
6080
    return \"ibeq\\tb,%l2\";
6081
}")
6082
 
6083
;; Split the above to handle the case where operand 0 is in memory
6084
;; (a register that couldn't get a hard register)
6085
(define_split
6086
  [(set (pc)
6087
        (if_then_else
6088
          (match_operator 3 "m68hc11_eq_compare_operator"
6089
             [(match_operand:HI 0 "general_operand" "")
6090
              (match_operand:HI 1 "const_int_operand" "")])
6091
         (label_ref (match_operand 4 "" ""))
6092
         (pc)))
6093
   (set (match_dup 0)
6094
        (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6095
   (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6096
  "TARGET_M6812 && reload_completed"
6097
  [(set (match_dup 5) (match_dup 0))
6098
   (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6099
   (set (match_dup 0) (match_dup 5))
6100
   (set (pc)
6101
        (if_then_else (match_op_dup 3
6102
                            [(match_dup 5) (const_int 0)])
6103
                      (label_ref (match_dup 4)) (pc)))]
6104
  "")
6105
 
6106
;; Split the above to handle the case where operand 0 is in memory
6107
;; (a register that couldn't get a hard register)
6108
(define_split
6109
  [(set (pc)
6110
        (if_then_else
6111
          (match_operator 3 "m68hc11_eq_compare_operator"
6112
             [(match_operand:QI 0 "general_operand" "")
6113
              (match_operand:QI 1 "const_int_operand" "")])
6114
         (label_ref (match_operand 4 "" ""))
6115
         (pc)))
6116
   (set (match_dup 0)
6117
        (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6118
   (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6119
  "TARGET_M6812 && reload_completed"
6120
  [(set (match_dup 5) (match_dup 0))
6121
   (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6122
   (set (match_dup 0) (match_dup 5))
6123
   (set (pc)
6124
        (if_then_else (match_op_dup 3
6125
                            [(match_dup 5) (const_int 0)])
6126
                      (label_ref (match_dup 4)) (pc)))]
6127
  "")
6128
 
6129
;;--------------------------------------------------------------------
6130
;;-  Jumps and transfers
6131
;;--------------------------------------------------------------------
6132
(define_insn "jump"
6133
  [(set (pc)
6134
        (label_ref (match_operand 0 "" "")))]
6135
  ""
6136
  "bra\\t%l0")
6137
 
6138
(define_expand "beq"
6139
  [(set (pc)
6140
        (if_then_else (eq (cc0)
6141
                          (const_int 0))
6142
                      (label_ref (match_operand 0 "" ""))
6143
                      (pc)))]
6144
  ""
6145
  "
6146
{
6147
  m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6148
                                     m68hc11_compare_op1,
6149
                                     operands[0]);
6150
  DONE;
6151
}")
6152
 
6153
(define_expand "bne"
6154
  [(set (pc)
6155
        (if_then_else (ne (cc0)
6156
                          (const_int 0))
6157
                      (label_ref (match_operand 0 "" ""))
6158
                      (pc)))]
6159
  ""
6160
  "
6161
{
6162
  m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6163
                                     m68hc11_compare_op1,
6164
                                     operands[0]);
6165
  DONE;
6166
}")
6167
 
6168
(define_expand "bgt"
6169
  [(set (pc)
6170
        (if_then_else (gt (cc0)
6171
                          (const_int 0))
6172
                      (label_ref (match_operand 0 "" ""))
6173
                      (pc)))]
6174
  ""
6175
  "
6176
{
6177
  m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6178
                                     m68hc11_compare_op1,
6179
                                     operands[0]);
6180
  DONE;
6181
}")
6182
 
6183
(define_expand "bgtu"
6184
  [(set (pc)
6185
        (if_then_else (gtu (cc0)
6186
                           (const_int 0))
6187
                      (label_ref (match_operand 0 "" ""))
6188
                      (pc)))]
6189
  ""
6190
  "
6191
{
6192
  m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6193
                                     m68hc11_compare_op1,
6194
                                     operands[0]);
6195
  DONE;
6196
}")
6197
 
6198
(define_expand "blt"
6199
  [(set (pc)
6200
        (if_then_else (lt (cc0)
6201
                          (const_int 0))
6202
                      (label_ref (match_operand 0 "" ""))
6203
                      (pc)))]
6204
  ""
6205
  "
6206
{
6207
  m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6208
                                     m68hc11_compare_op1,
6209
                                     operands[0]);
6210
  DONE;
6211
}")
6212
 
6213
(define_expand "bltu"
6214
  [(set (pc)
6215
        (if_then_else (ltu (cc0)
6216
                           (const_int 0))
6217
                      (label_ref (match_operand 0 "" ""))
6218
                      (pc)))]
6219
  ""
6220
  "
6221
{
6222
  m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6223
                                     m68hc11_compare_op1,
6224
                                     operands[0]);
6225
  DONE;
6226
}")
6227
 
6228
(define_expand "bge"
6229
  [(set (pc)
6230
        (if_then_else (ge (cc0)
6231
                           (const_int 0))
6232
                      (label_ref (match_operand 0 "" ""))
6233
                      (pc)))]
6234
  ""
6235
  "
6236
{
6237
  m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6238
                                     m68hc11_compare_op1,
6239
                                     operands[0]);
6240
  DONE;
6241
}")
6242
 
6243
(define_expand "bgeu"
6244
  [(set (pc)
6245
        (if_then_else (geu (cc0)
6246
                           (const_int 0))
6247
                      (label_ref (match_operand 0 "" ""))
6248
                      (pc)))]
6249
  ""
6250
  "
6251
{
6252
  m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6253
                                     m68hc11_compare_op1,
6254
                                     operands[0]);
6255
  DONE;
6256
}")
6257
 
6258
(define_expand "ble"
6259
  [(set (pc)
6260
        (if_then_else (le (cc0)
6261
                           (const_int 0))
6262
                      (label_ref (match_operand 0 "" ""))
6263
                      (pc)))]
6264
  ""
6265
  "
6266
{
6267
  m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6268
                                     m68hc11_compare_op1,
6269
                                     operands[0]);
6270
  DONE;
6271
}")
6272
 
6273
(define_expand "bleu"
6274
  [(set (pc)
6275
        (if_then_else (leu (cc0)
6276
                           (const_int 0))
6277
                      (label_ref (match_operand 0 "" ""))
6278
                      (pc)))]
6279
  ""
6280
  "
6281
{
6282
  m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6283
                                     m68hc11_compare_op1,
6284
                                     operands[0]);
6285
  DONE;
6286
}")
6287
 
6288
;;
6289
;; Test and branch instructions for 68HC12 for EQ and NE.
6290
;; 'z' must not appear in the constraints because the z replacement
6291
;; pass does not know how to restore the replacement register.
6292
;;
6293
(define_insn "*tbeq"
6294
  [(set (pc)
6295
        (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6296
                          (const_int 0))
6297
                      (label_ref (match_operand 1 "" ""))
6298
                      (pc)))]
6299
  "TARGET_M6812"
6300
  "*
6301
{
6302
   /* If the flags are already set correctly, use 'bne/beq' which are
6303
      smaller and a little bit faster.  This happens quite often due
6304
      to reloading of operands[0].  In that case, flags are set correctly
6305
      due to the load instruction.  */
6306
  if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6307
      || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6308
    return \"beq\\t%l1\";
6309
  else
6310
    return \"tbeq\\t%0,%l1\";
6311
}")
6312
 
6313
(define_insn "*tbne"
6314
  [(set (pc)
6315
        (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6316
                          (const_int 0))
6317
                      (label_ref (match_operand 1 "" ""))
6318
                      (pc)))]
6319
  "TARGET_M6812"
6320
  "*
6321
{
6322
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6323
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6324
     return \"bne\\t%l1\";
6325
   else
6326
     return \"tbne\\t%0,%l1\";
6327
}")
6328
 
6329
;;
6330
;; Test and branch with 8-bit register.  Register must be B (or A).
6331
;;
6332
(define_insn "*tbeq8"
6333
  [(set (pc)
6334
        (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6335
                          (const_int 0))
6336
                      (label_ref (match_operand 1 "" ""))
6337
                      (pc)))]
6338
  "TARGET_M6812"
6339
  "*
6340
{
6341
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6342
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6343
     return \"beq\\t%l1\";
6344
   else
6345
     return \"tbeq\\tb,%l1\";
6346
}")
6347
 
6348
(define_insn "*tbne8"
6349
  [(set (pc)
6350
        (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6351
                          (const_int 0))
6352
                      (label_ref (match_operand 1 "" ""))
6353
                      (pc)))]
6354
  "TARGET_M6812"
6355
  "*
6356
{
6357
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6358
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6359
     return \"bne\\t%l1\";
6360
   else
6361
     return \"tbne\\tb,%l1\";
6362
}")
6363
 
6364
(define_insn "*beq"
6365
  [(set (pc)
6366
        (if_then_else (eq (cc0)
6367
                          (const_int 0))
6368
                      (label_ref (match_operand 0 "" ""))
6369
                      (pc)))]
6370
  ""
6371
  "beq\\t%l0")
6372
 
6373
(define_insn "*bne"
6374
  [(set (pc)
6375
        (if_then_else (ne (cc0)
6376
                          (const_int 0))
6377
                      (label_ref (match_operand 0 "" ""))
6378
                      (pc)))]
6379
  ""
6380
  "bne\\t%l0")
6381
 
6382
(define_insn "*bgt"
6383
  [(set (pc)
6384
        (if_then_else (gt (cc0)
6385
                          (const_int 0))
6386
                      (label_ref (match_operand 0 "" ""))
6387
                      (pc)))]
6388
  ""
6389
  "bgt\\t%l0")
6390
 
6391
(define_insn "*bgtu"
6392
  [(set (pc)
6393
        (if_then_else (gtu (cc0)
6394
                           (const_int 0))
6395
                      (label_ref (match_operand 0 "" ""))
6396
                      (pc)))]
6397
  ""
6398
  "bhi\\t%l0")
6399
 
6400
(define_insn "*blt"
6401
  [(set (pc)
6402
        (if_then_else (lt (cc0)
6403
                          (const_int 0))
6404
                      (label_ref (match_operand 0 "" ""))
6405
                      (pc)))]
6406
  ""
6407
  "*
6408
{
6409
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6410
    return \"bmi\\t%l0\";
6411
  else
6412
    return \"blt\\t%l0\";
6413
}")
6414
 
6415
(define_insn "*bltu"
6416
  [(set (pc)
6417
        (if_then_else (ltu (cc0)
6418
                           (const_int 0))
6419
                      (label_ref (match_operand 0 "" ""))
6420
                      (pc)))]
6421
  ""
6422
  "blo\\t%l0")
6423
 
6424
(define_insn "*bge"
6425
  [(set (pc)
6426
        (if_then_else (ge (cc0)
6427
                          (const_int 0))
6428
                      (label_ref (match_operand 0 "" ""))
6429
                      (pc)))]
6430
  ""
6431
  "*
6432
{
6433
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6434
    return \"bpl\\t%l0\";
6435
  else
6436
    return \"bge\\t%l0\";
6437
}")
6438
 
6439
(define_insn "*bgeu"
6440
  [(set (pc)
6441
        (if_then_else (geu (cc0)
6442
                           (const_int 0))
6443
                      (label_ref (match_operand 0 "" ""))
6444
                      (pc)))]
6445
  ""
6446
  "bhs\\t%l0")
6447
 
6448
(define_insn "*ble"
6449
  [(set (pc)
6450
        (if_then_else (le (cc0)
6451
                          (const_int 0))
6452
                      (label_ref (match_operand 0 "" ""))
6453
                      (pc)))]
6454
  ""
6455
  "*
6456
{
6457
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6458
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6459
  else
6460
    return \"ble\\t%l0\";
6461
}")
6462
 
6463
(define_insn "*bleu"
6464
  [(set (pc)
6465
        (if_then_else (leu (cc0)
6466
                           (const_int 0))
6467
                      (label_ref (match_operand 0 "" ""))
6468
                      (pc)))]
6469
  ""
6470
  "bls\\t%l0")
6471
 
6472
;;--------------------------------------------------------------------
6473
;;- Negative test and branch
6474
;;--------------------------------------------------------------------
6475
(define_insn ""
6476
  [(set (pc)
6477
        (if_then_else (eq (cc0)
6478
                          (const_int 0))
6479
                      (pc)
6480
                      (label_ref (match_operand 0 "" ""))))]
6481
  ""
6482
  "bne\\t%l0")
6483
 
6484
(define_insn ""
6485
  [(set (pc)
6486
        (if_then_else (ne (cc0)
6487
                          (const_int 0))
6488
                      (pc)
6489
                      (label_ref (match_operand 0 "" ""))))]
6490
  ""
6491
  "beq\\t%l0")
6492
 
6493
(define_insn ""
6494
  [(set (pc)
6495
        (if_then_else (gt (cc0)
6496
                          (const_int 0))
6497
                      (pc)
6498
                      (label_ref (match_operand 0 "" ""))))]
6499
  ""
6500
  "*
6501
{
6502
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6503
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6504
  else
6505
    return \"ble\\t%l0\";
6506
}")
6507
 
6508
(define_insn ""
6509
  [(set (pc)
6510
        (if_then_else (gtu (cc0)
6511
                           (const_int 0))
6512
                      (pc)
6513
                      (label_ref (match_operand 0 "" ""))))]
6514
  ""
6515
  "bls\\t%l0")
6516
 
6517
(define_insn ""
6518
  [(set (pc)
6519
        (if_then_else (lt (cc0)
6520
                          (const_int 0))
6521
                      (pc)
6522
                      (label_ref (match_operand 0 "" ""))))]
6523
  ""
6524
  "*
6525
{
6526
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6527
    return \"bpl\\t%l0\";
6528
  else
6529
    return \"bge\\t%l0\";
6530
}")
6531
 
6532
(define_insn ""
6533
  [(set (pc)
6534
        (if_then_else (ltu (cc0)
6535
                           (const_int 0))
6536
                      (pc)
6537
                      (label_ref (match_operand 0 "" ""))))]
6538
  ""
6539
  "bhs\\t%l0")
6540
 
6541
(define_insn ""
6542
  [(set (pc)
6543
        (if_then_else (ge (cc0)
6544
                          (const_int 0))
6545
                      (pc)
6546
                      (label_ref (match_operand 0 "" ""))))]
6547
  ""
6548
  "*
6549
{
6550
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
6551
    return \"bmi\\t%l0\";
6552
  else
6553
    return \"blt\\t%l0\";
6554
}")
6555
 
6556
(define_insn ""
6557
  [(set (pc)
6558
        (if_then_else (geu (cc0)
6559
                           (const_int 0))
6560
                      (pc)
6561
                      (label_ref (match_operand 0 "" ""))))]
6562
  ""
6563
  "blo\\t%l0")
6564
 
6565
(define_insn ""
6566
  [(set (pc)
6567
        (if_then_else (le (cc0)
6568
                          (const_int 0))
6569
                      (pc)
6570
                      (label_ref (match_operand 0 "" ""))))]
6571
  ""
6572
  "bgt\\t%l0")
6573
 
6574
(define_insn ""
6575
  [(set (pc)
6576
        (if_then_else (leu (cc0)
6577
                           (const_int 0))
6578
                      (pc)
6579
                      (label_ref (match_operand 0 "" ""))))]
6580
  ""
6581
  "bhi\\t%l0")
6582
 
6583
;;--------------------------------------------------------------------
6584
;;-  Calls
6585
;;--------------------------------------------------------------------
6586
;;
6587
;;- Call a function that returns no value.
6588
(define_insn "call"
6589
  [(call (match_operand:QI 0 "memory_operand" "m")
6590
         (match_operand:SI 1 "general_operand" "g"))]
6591
  ;; Operand 1 not really used on the m68hc11.
6592
  ""
6593
 "*
6594
{
6595
  if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6596
    {
6597
      if (m68hc11_is_far_symbol (operands[0]))
6598
        {
6599
          if (TARGET_M6812)
6600
            {
6601
              output_asm_insn (\"call\\t%0\", operands);
6602
              return \"\";
6603
            }
6604
          else
6605
            {
6606
              output_asm_insn (\"pshb\", operands);
6607
              output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6608
              output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6609
              return \"jsr\\t__call_a32\";
6610
            }
6611
        }
6612
      if (m68hc11_is_trap_symbol (operands[0]))
6613
        return \"swi\";
6614
      else
6615
        return \"bsr\\t%0\";
6616
    }
6617
  else
6618
    {
6619
      return \"jsr\\t%0\";
6620
    }
6621
}")
6622
 
6623
(define_insn "call_value"
6624
  [(set (match_operand 0 "" "=g")
6625
        (call (match_operand:QI 1 "memory_operand" "m")
6626
              (match_operand:SI 2 "general_operand" "g")))]
6627
  ""
6628
 "*
6629
{
6630
  if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6631
    {
6632
      if (m68hc11_is_far_symbol (operands[1]))
6633
        {
6634
          if (TARGET_M6812)
6635
            {
6636
              output_asm_insn (\"call\\t%1\", operands);
6637
              return \"\";
6638
            }
6639
          else
6640
            {
6641
              output_asm_insn (\"pshb\", operands);
6642
              output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6643
              output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6644
              return \"jsr\\t__call_a32\";
6645
            }
6646
        }
6647
      if (m68hc11_is_trap_symbol (operands[1]))
6648
        return \"swi\";
6649
      else
6650
        return \"bsr\\t%1\";
6651
    }
6652
  else
6653
    {
6654
      return \"jsr\\t%1\";
6655
    }
6656
}")
6657
 
6658
;; Call subroutine returning any type.
6659
 
6660
(define_expand "untyped_call"
6661
  [(parallel [(call (match_operand 0 "" "")
6662
                    (const_int 0))
6663
              (match_operand 1 "" "")
6664
              (match_operand 2 "" "")])]
6665
  ""
6666
  "
6667
{
6668
  int i;
6669
 
6670
  emit_call_insn (gen_call (operands[0], const0_rtx));
6671
 
6672
  for (i = 0; i < XVECLEN (operands[2], 0); i++)
6673
    {
6674
      rtx set = XVECEXP (operands[2], 0, i);
6675
      emit_move_insn (SET_DEST (set), SET_SRC (set));
6676
    }
6677
 
6678
  /* The optimizer does not know that the call sets the function value
6679
     registers we stored in the result block.  We avoid problems by
6680
     claiming that all hard registers are used and clobbered at this
6681
     point.  */
6682
  emit_insn (gen_blockage ());
6683
 
6684
  DONE;
6685
}")
6686
 
6687
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6688
;; all of memory.  This blocks insns from being moved across this point.
6689
 
6690
(define_insn "blockage"
6691
  [(unspec_volatile [(const_int 0)] 0)]
6692
  ""
6693
  "")
6694
 
6695
(define_insn "nop"
6696
  [(const_int 0)]
6697
  ""
6698
  "nop")
6699
 
6700
(define_expand "prologue"
6701
  [(const_int 0)]
6702
  ""
6703
  "
6704
{
6705
  expand_prologue ();
6706
  DONE;
6707
}")
6708
 
6709
(define_expand "epilogue"
6710
  [(return)]
6711
  ""
6712
  "
6713
{
6714
  expand_epilogue ();
6715
  DONE;
6716
}")
6717
 
6718
;; Used for frameless functions which save no regs and allocate no locals.
6719
(define_expand "return"
6720
  [(return)]
6721
  "reload_completed && m68hc11_total_frame_size () == 0"
6722
  "
6723
{
6724
  int ret_size = 0;
6725
 
6726
  if (current_function_return_rtx)
6727
    ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6728
 
6729
  /* Emit use notes only when HAVE_return is true.  */
6730
  if (m68hc11_total_frame_size () != 0)
6731
    ret_size = 0;
6732
 
6733
  if (ret_size && ret_size <= 2)
6734
    {
6735
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6736
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6737
                                 gen_rtx_USE (VOIDmode,
6738
                                              gen_rtx_REG (HImode, 1)))));
6739
      DONE;
6740
    }
6741
  if (ret_size)
6742
    {
6743
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6744
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6745
                                 gen_rtx_USE (VOIDmode,
6746
                                              gen_rtx_REG (SImode, 0)))));
6747
      DONE;
6748
    }
6749
}")
6750
 
6751
(define_insn "*return_void"
6752
  [(return)]
6753
  "reload_completed"
6754
  "*
6755
{
6756
  rtx next = next_active_insn (insn);
6757
 
6758
  if (next
6759
      && GET_CODE (next) == JUMP_INSN
6760
      && GET_CODE (PATTERN (next)) == RETURN)
6761
    return \"\";
6762
  if (current_function_interrupt || current_function_trap)
6763
    return \"rti\";
6764
  else if (!current_function_far)
6765
    return \"rts\";
6766
  else if (TARGET_M6812)
6767
    return \"rtc\";
6768
  else
6769
    {
6770
      int ret_size = 0;
6771
 
6772
      if (current_function_return_rtx)
6773
        ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6774
 
6775
      if (ret_size == 0)
6776
        return \"jmp\\t__return_void\";
6777
      if (ret_size <= 2)
6778
        return \"jmp\\t__return_16\";
6779
      if (ret_size <= 4)
6780
        return \"jmp\\t__return_32\";
6781
      return \"jmp\\t__return_16\";
6782
    }
6783
}")
6784
 
6785
(define_insn "*return_16bit"
6786
  [(return)
6787
   (use (reg:HI D_REGNUM))]
6788
  "reload_completed && m68hc11_total_frame_size () == 0"
6789
  "*
6790
{
6791
  rtx next = next_active_insn (insn);
6792
 
6793
  if (next
6794
      && GET_CODE (next) == JUMP_INSN
6795
      && GET_CODE (PATTERN (next)) == RETURN)
6796
    return \"\";
6797
  if (current_function_interrupt || current_function_trap)
6798
    return \"rti\";
6799
  else if (!current_function_far)
6800
    return \"rts\";
6801
  else if (TARGET_M6812)
6802
    return \"rtc\";
6803
  else
6804
    return \"jmp\\t__return_16\";
6805
}")
6806
 
6807
(define_insn "*return_32bit"
6808
  [(return)
6809
   (use (reg:SI 0))]
6810
  "reload_completed && m68hc11_total_frame_size () == 0"
6811
  "*
6812
{
6813
  rtx next = next_active_insn (insn);
6814
 
6815
  if (next
6816
      && GET_CODE (next) == JUMP_INSN
6817
      && GET_CODE (PATTERN (next)) == RETURN)
6818
    return \"\";
6819
  if (current_function_interrupt || current_function_trap)
6820
    return \"rti\";
6821
  else if (!current_function_far)
6822
    return \"rts\";
6823
  else if (TARGET_M6812)
6824
    return \"rtc\";
6825
  else
6826
    return \"jmp\\t__return_32\";
6827
}")
6828
 
6829
(define_insn "indirect_jump"
6830
  [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6831
  ""
6832
  "jmp\\t0,%0")
6833
 
6834
;;--------------------------------------------------------------------
6835
;;-  Table jump
6836
;;--------------------------------------------------------------------
6837
;;
6838
;; Operand 0 is the address of the table element to use
6839
;; operand 1 is the CODE_LABEL for the table
6840
;;--------------------------------------------------------------------
6841
(define_expand "tablejump"
6842
  [(parallel [(set (pc) (match_operand 0 "" ""))
6843
              (use (label_ref (match_operand 1 "" "")))])]
6844
  ""
6845
  "")
6846
 
6847
(define_insn "*jump_indirect"
6848
   [(parallel [
6849
        (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6850
        (use (label_ref (match_operand 1 "" "")))])]
6851
   ""
6852
  "jmp\\t0,%0")
6853
 
6854
;;--------------------------------------------------------------------
6855
;;- Peepholes
6856
;;--------------------------------------------------------------------
6857
 
6858
;;--------------------------------------------------------------------
6859
;;- 68HC12 dbcc/ibcc peepholes
6860
;;--------------------------------------------------------------------
6861
;;
6862
;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6863
;;          "addd #-1; beq L1" into "dbeq d,L1"
6864
;;          "addd #1; bne L1" into "ibne d,L1"
6865
;;          "addd #1; beq L1" into "ibeq d,L1"
6866
;;
6867
(define_peephole2
6868
  [(set (match_operand:HI 0 "hard_reg_operand" "")
6869
        (plus:HI (match_dup 0)
6870
                 (match_operand:HI 1 "const_int_operand" "")))
6871
   (set (pc)
6872
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6873
                         [(match_dup 0)
6874
                          (const_int 0)])
6875
                      (label_ref (match_operand 3 "" "")) (pc)))]
6876
  "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6877
  [(parallel [
6878
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6879
                              (label_ref (match_dup 3)) (pc)))
6880
      (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6881
      (clobber (match_dup 4))])]
6882
  "operands[4] = gen_rtx_SCRATCH(HImode);
6883
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
6884
 
6885
 
6886
;;
6887
;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6888
;;          "addb #-1; beq L1" into "dbeq b,L1"
6889
;;
6890
(define_peephole2
6891
  [(set (match_operand:QI 0 "hard_reg_operand" "")
6892
        (plus:QI (match_dup 0)
6893
                 (match_operand:QI 1 "const_int_operand" "")))
6894
   (set (pc)
6895
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6896
                         [(match_dup 0)
6897
                          (const_int 0)])
6898
                      (label_ref (match_operand 3 "" "")) (pc)))]
6899
  "TARGET_M6812 && D_REG_P (operands[0])
6900
   && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6901
  [(parallel [
6902
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6903
                              (label_ref (match_dup 3)) (pc)))
6904
      (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6905
      (clobber (match_dup 4))])]
6906
  "operands[4] = gen_rtx_SCRATCH(QImode);
6907
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
6908
 
6909
 
6910
;;--------------------------------------------------------------------
6911
;;- Move peephole2
6912
;;--------------------------------------------------------------------
6913
 
6914
;;
6915
;; Replace "leas 2,sp" with a "pulx" or a "puly".
6916
;; On 68HC12, this is one cycle slower but one byte smaller.
6917
;; pr target/6899: This peephole was not valid because a register CSE
6918
;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
6919
;; not removed.
6920
;;
6921
(define_peephole2
6922
  [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6923
   (match_scratch:HI 0 "xy")]
6924
  "TARGET_M6812 && optimize_size"
6925
  [(set (match_dup 0) (match_dup 1))
6926
   (use (match_dup 0))]
6927
  "operands[1] = gen_rtx_MEM (HImode,
6928
                          gen_rtx_POST_INC (HImode,
6929
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6930
 
6931
;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6932
;;
6933
;; PR 14542: emit a use to pretend we need the value of initial register.
6934
;; Otherwise verify_local_live_at_start will die due to a live change
6935
;; of that register.
6936
;;
6937
(define_peephole2
6938
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6939
        (match_operand:HI 0 "hard_reg_operand" ""))
6940
   (set (match_dup 0)
6941
        (match_operand:HI 1 "hard_reg_operand" ""))
6942
   (set (mem:HI (reg:HI SP_REGNUM))
6943
        (match_dup 0))]
6944
  "TARGET_M6812"
6945
  [(use (match_dup 0))
6946
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6947
        (match_dup 1))
6948
   (set (match_dup 0) (match_dup 1))]
6949
  "")
6950
 
6951
;;
6952
;; Change: "ldd 0,sp; pulx" into  "puld"
6953
;; This sequence usually appears at end a functions.
6954
(define_peephole2
6955
  [(set (match_operand:HI 0 "hard_reg_operand" "")
6956
        (mem:HI (reg:HI SP_REGNUM)))
6957
   (use (match_dup 0))
6958
   (set (match_operand:HI 1 "hard_reg_operand" "")
6959
        (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6960
  "peep2_reg_dead_p (2, operands[1])"
6961
  [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6962
   (use (match_dup 0))]
6963
  "")
6964
 
6965
;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6966
;; Appears to allocate local variables.
6967
(define_peephole2
6968
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6969
        (match_operand:HI 0 "hard_reg_operand" ""))
6970
   (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6971
        (const_int 0))
6972
   (set (mem:QI (reg:HI SP_REGNUM))
6973
        (const_int 0))]
6974
  "TARGET_M6812"
6975
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6976
        (const_int 0))]
6977
  "")
6978
 
6979
;; Likewise for HI mode
6980
(define_peephole2
6981
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6982
        (match_operand:HI 0 "hard_reg_operand" ""))
6983
   (set (mem:HI (reg:HI SP_REGNUM))
6984
        (const_int 0))]
6985
  "TARGET_M6812"
6986
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6987
        (const_int 0))]
6988
  "")
6989
;;--------------------------------------------------------------------
6990
;;-
6991
;;--------------------------------------------------------------------
6992
;;
6993
;; Optimize memory<->memory moves when the value is also loaded in
6994
;; a register.
6995
;;
6996
(define_peephole2
6997
  [(set (match_operand:QI 0 "memory_operand" "")
6998
        (match_operand:QI 1 "memory_operand" ""))
6999
   (set (reg:QI D_REGNUM)
7000
        (match_operand:QI 2 "memory_operand" ""))]
7001
  "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
7002
   || (GET_CODE (XEXP (operands[0], 0)) == REG
7003
       && GET_CODE (XEXP (operands[2], 0)) == POST_INC
7004
       && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
7005
  [(set (reg:QI D_REGNUM) (match_dup 1))
7006
   (set (match_dup 2) (reg:QI D_REGNUM))]
7007
  "")
7008
 
7009
;;
7010
;; Remove a possible move before a compare instruction when that
7011
;; move will go in a dead register.  Compare with the source then.
7012
;;
7013
(define_peephole2
7014
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7015
        (match_operand:HI 1 "hard_reg_operand" ""))
7016
   (set (cc0)
7017
        (compare (match_dup 0)
7018
                 (match_operand:HI 2 "cmp_operand" "")))]
7019
  "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7020
   && peep2_reg_dead_p (2, operands[0])
7021
   && !reg_mentioned_p (operands[0], operands[2])"
7022
  [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7023
  "")
7024
 
7025
;;
7026
;; Optimize loading a constant to memory when that same constant
7027
;; is loaded to a hard register.  Switch the two to use the register
7028
;; for memory initialization.  In most cases, the constant is 0.
7029
;;
7030
(define_peephole2
7031
  [(set (match_operand:HI 0 "memory_operand" "")
7032
        (match_operand:HI 1 "immediate_operand" ""))
7033
   (set (match_operand:HI 2 "hard_reg_operand" "")
7034
        (match_dup 1))]
7035
  "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7036
   && !reg_mentioned_p (operands[2], operands[0])"
7037
  [(set (match_dup 2) (match_dup 1))
7038
   (set (match_dup 0) (match_dup 2))]
7039
  "")
7040
 
7041
;;
7042
;; Reorganize to optimize address computations.
7043
;;
7044
(define_peephole2
7045
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7046
        (match_operand:HI 1 "const_int_operand" ""))
7047
   (set (match_dup 0)
7048
        (plus:HI (match_dup 0)
7049
                 (match_operand:HI 2 "general_operand" "")))]
7050
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7051
  [(set (match_dup 0) (match_dup 2))
7052
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7053
  "")
7054
 
7055
;;
7056
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
7057
;;
7058
(define_peephole2
7059
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7060
        (match_operand:HI 1 "const_int_operand" ""))
7061
   (set (match_dup 0)
7062
        (plus:HI (match_dup 0)
7063
                 (match_operand:HI 2 "general_operand" "")))
7064
   (match_scratch:QI 3 "d")]
7065
  "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7066
  [(set (match_dup 3) (match_dup 4))
7067
   (set (match_dup 0) (match_dup 2))
7068
   (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7069
  "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7070
 
7071
;;
7072
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
7073
;;
7074
(define_peephole2
7075
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7076
        (match_operand:HI 1 "const_int_operand" ""))
7077
   (set (match_dup 0)
7078
        (plus:HI (match_dup 0)
7079
                 (match_operand:HI 2 "general_operand" "")))]
7080
  "TARGET_M6812"
7081
  [(set (match_dup 0) (match_dup 2))
7082
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7083
  "")
7084
 
7085
;;
7086
;; Optimize an address register increment and a compare to use
7087
;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7088
;; before reload, but can be enabled after).
7089
;;
7090
(define_peephole2
7091
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7092
        (plus:HI (match_dup 0)
7093
                 (match_operand:HI 1 "const_int_operand" "")))
7094
   (set (cc0)
7095
        (match_operand:QI 2 "memory_operand" ""))]
7096
  "TARGET_AUTO_INC_DEC
7097
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7098
   && reg_mentioned_p (operands[0], operands[2])"
7099
  [(set (cc0) (match_dup 3))]
7100
  "if (INTVAL (operands[1]) == 1)
7101
     operands[3] = gen_rtx_MEM (QImode,
7102
                            gen_rtx_PRE_INC (HImode, operands[0]));
7103
   else
7104
     operands[3] = gen_rtx_MEM (QImode,
7105
                            gen_rtx_PRE_DEC (HImode, operands[0]));
7106
  ")
7107
 
7108
;;
7109
;; Likewise for compare.
7110
;;
7111
(define_peephole2
7112
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7113
        (plus:HI (match_dup 0)
7114
                 (match_operand:HI 1 "const_int_operand" "")))
7115
   (set (cc0)
7116
        (compare (match_operand:QI 2 "hard_reg_operand" "")
7117
                 (match_operand:QI 3 "memory_operand" "")))]
7118
  "TARGET_AUTO_INC_DEC
7119
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7120
   && reg_mentioned_p (operands[0], operands[3])"
7121
  [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7122
  "if (INTVAL (operands[1]) == 1)
7123
     operands[4] = gen_rtx_MEM (QImode,
7124
                            gen_rtx_PRE_INC (HImode, operands[0]));
7125
   else
7126
     operands[4] = gen_rtx_MEM (QImode,
7127
                            gen_rtx_PRE_DEC (HImode, operands[0]));
7128
  ")
7129
 
7130
(define_peephole2
7131
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7132
        (plus:HI (match_dup 0)
7133
                 (match_operand:HI 1 "const_int_operand" "")))
7134
   (set (cc0)
7135
        (compare (match_operand:QI 2 "memory_operand" "")
7136
                 (match_operand:QI 3 "hard_reg_operand" "")))]
7137
  "TARGET_AUTO_INC_DEC
7138
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7139
   && reg_mentioned_p (operands[0], operands[2])"
7140
  [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7141
  "if (INTVAL (operands[1]) == 1)
7142
     operands[4] = gen_rtx_MEM (QImode,
7143
                            gen_rtx_PRE_INC (HImode, operands[0]));
7144
   else
7145
     operands[4] = gen_rtx_MEM (QImode,
7146
                            gen_rtx_PRE_DEC (HImode, operands[0]));
7147
  ")
7148
 
7149
;;
7150
;; Replace a "ldx #N; addx " with a "ldx ; addx #n"
7151
;; (avoids many temporary moves because we can't add sp to another reg easily)
7152
;;
7153
(define_peephole2
7154
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7155
        (match_operand:HI 1 "const_int_operand" ""))
7156
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7157
  ""
7158
  [(set (match_dup 0) (reg:HI SP_REGNUM))
7159
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7160
  "")
7161
 
7162
;;
7163
;; Replace "ldd #N; addd " with "ldd ; addd #N".
7164
;;
7165
(define_peephole2
7166
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7167
        (match_operand:HI 1 "const_int_operand" ""))
7168
   (set (match_dup 0)
7169
        (plus:HI (match_dup 0)
7170
                 (match_operand:HI 2 "general_operand" "")))]
7171
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7172
  [(set (match_dup 0) (match_dup 2))
7173
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7174
  "")
7175
 
7176
;;
7177
;;
7178
;;
7179
(define_peephole2
7180
  [(parallel
7181
     [(set (match_operand:SI 0 "hard_reg_operand" "")
7182
        (ashift:SI (match_operand:SI 1 "general_operand" "")
7183
                   (const_int 1)))
7184
      (clobber (match_scratch:HI 2 ""))])
7185
   (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7186
   (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7187
  "!X_REG_P (operands[1])
7188
   && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7189
   && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7190
  [(set (reg:HI D_REGNUM) (match_dup 5))
7191
   (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7192
   (set (match_dup 3) (reg:HI D_REGNUM))
7193
   (set (reg:HI D_REGNUM) (match_dup 6))
7194
   (parallel [(set (reg:HI D_REGNUM)
7195
                   (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7196
              (clobber (reg:HI CC_REGNUM))])
7197
   (set (match_dup 4) (reg:HI D_REGNUM))]
7198
  "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7199
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7200
 
7201
;;
7202
;; Replace a "ldd ; psha; pshb" with a "ldx ; pshx".
7203
;;
7204
(define_peephole2
7205
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7206
        (match_operand:HI 1 "memory_operand" ""))
7207
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7208
        (match_dup 0))
7209
   (match_scratch:HI 2 "x")]
7210
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7211
  [(set (match_dup 2) (match_dup 1))
7212
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7213
  "")
7214
 
7215
;;
7216
;; Remove one load when copying a value to/from memory and also
7217
;; to a register.  Take care not clobbering a possible register used
7218
;; by operand 2.
7219
;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7220
;;
7221
(define_peephole2
7222
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7223
        (match_operand:HI 1 "general_operand" ""))
7224
   (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7225
   (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7226
  "peep2_reg_dead_p (2, operands[0])
7227
   && !side_effects_p (operands[1])
7228
   && !side_effects_p (operands[2])
7229
   && !reg_mentioned_p (operands[3], operands[2])"
7230
  [(set (match_dup 3) (match_dup 1))
7231
   (set (match_dup 2) (match_dup 3))]
7232
  "")
7233
 
7234
;;
7235
;; Replace a "ldd ; addd #N; std " into a
7236
;; "ldx ; leax; stx " if we have a free X/Y register
7237
;; and the constant is small.
7238
;;
7239
(define_peephole2
7240
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7241
        (match_operand:HI 1 "general_operand" ""))
7242
   (set (match_dup 0) (plus:HI (match_dup 0)
7243
                               (match_operand:HI 2 "const_int_operand" "")))
7244
   (set (match_operand:HI 3 "nonimmediate_operand" "")
7245
        (match_dup 0))
7246
   (match_scratch:HI 4 "xy")]
7247
  "D_REG_P (operands[0])
7248
   && (TARGET_M6812
7249
       || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7250
   && peep2_reg_dead_p (3, operands[0])"
7251
  [(set (match_dup 4) (match_dup 1))
7252
   (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7253
   (set (match_dup 3) (match_dup 4))]
7254
  "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7255
   if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7256
 
7257
;;--------------------------------------------------------------------
7258
;;- Bset peephole2
7259
;;--------------------------------------------------------------------
7260
;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7261
;;
7262
;; Replace 'ldab ; orab #N; stab ' by 'bset  #N'.
7263
;; Register D must be dead and there must be no register side effects for mem.
7264
;; The  *can* be volatile this is why we must not use 'side_effects_p'.
7265
;; The good side effect is that it makes the sequence atomic.
7266
;;
7267
(define_peephole2
7268
  [(set (match_operand:QI 0 "hard_reg_operand" "")
7269
        (match_operand:QI 1 "nonimmediate_operand" ""))
7270
   (set (match_dup 0) (ior:QI (match_dup 0)
7271
                              (match_operand:QI 2 "const_int_operand" "")))
7272
   (set (match_dup 1) (match_dup 0))]
7273
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7274
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7275
   && peep2_reg_dead_p (3, operands[0])"
7276
  [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7277
  "")
7278
 
7279
(define_peephole2
7280
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7281
        (match_operand:HI 1 "nonimmediate_operand" ""))
7282
   (set (match_dup 0) (ior:HI (match_dup 0)
7283
                              (match_operand:HI 2 "const_int_operand" "")))
7284
   (set (match_dup 1) (match_dup 0))]
7285
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7286
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7287
   && peep2_reg_dead_p (3, operands[0])"
7288
  [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7289
  "")
7290
 
7291
;;--------------------------------------------------------------------
7292
;;- Bclr peephole2
7293
;;--------------------------------------------------------------------
7294
;; Replace 'ldab ; andab #N; stab ' by 'bclr  #N'.
7295
;; See Bset peephole2.
7296
;;
7297
(define_peephole2
7298
  [(set (match_operand:QI 0 "hard_reg_operand" "")
7299
        (match_operand:QI 1 "nonimmediate_operand" ""))
7300
   (set (match_dup 0) (and:QI (match_dup 0)
7301
                              (match_operand:QI 2 "const_int_operand" "")))
7302
   (set (match_dup 1) (match_dup 0))]
7303
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7304
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7305
   && peep2_reg_dead_p (3, operands[0])"
7306
  [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7307
  "")
7308
 
7309
(define_peephole2
7310
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7311
        (match_operand:HI 1 "nonimmediate_operand" ""))
7312
   (set (match_dup 0) (and:HI (match_dup 0)
7313
                              (match_operand:HI 2 "const_int_operand" "")))
7314
   (set (match_dup 1) (match_dup 0))]
7315
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7316
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7317
   && peep2_reg_dead_p (3, operands[0])"
7318
  [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7319
  "")
7320
 
7321
 
7322
;;--------------------------------------------------------------------
7323
;;- Compare peephole2
7324
;;--------------------------------------------------------------------
7325
(define_peephole2
7326
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7327
        (match_operand:HI 1 "hard_reg_operand" ""))
7328
   (set (match_dup 1) (plus:HI (match_dup 1)
7329
                               (match_operand:HI 2 "const_int_operand" "")))
7330
   (set (cc0) (match_dup 0))]
7331
  "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7332
  [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7333
   (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7334
  "")
7335
 
7336
(define_peephole2
7337
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7338
        (match_operand:HI 1 "hard_reg_operand" ""))
7339
   (set (match_operand:HI 2 "hard_reg_operand" "")
7340
        (plus:HI (match_dup 2)
7341
                 (match_operand:HI 3 "const_int_operand" "")))
7342
   (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7343
   (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7344
  "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7345
   && !reg_mentioned_p (operands[2], operands[4])
7346
 
7347
   && ((rtx_equal_p (operands[5], operands[0])
7348
        && rtx_equal_p (operands[2], operands[1]))
7349
 
7350
       || (rtx_equal_p (operands[5], operands[1])
7351
           && rtx_equal_p (operands[2], operands[0])))"
7352
  [(set (match_dup 2) (match_dup 1))
7353
   (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7354
   (set (match_dup 4) (match_dup 2))
7355
   (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7356
  "")
7357
 
7358
 
7359
;;--------------------------------------------------------------------
7360
;;- Load peephole2
7361
;;--------------------------------------------------------------------
7362
;;
7363
;; Optimize initialization of 2 hard regs from the same memory location
7364
;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7365
;; from the same memory location.
7366
;;
7367
(define_peephole2
7368
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7369
        (match_operand:HI 1 "memory_operand" ""))
7370
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7371
  "TARGET_M6811
7372
   && !side_effects_p (operands[1])
7373
   && !reg_mentioned_p (operands[0], operands[1])"
7374
  [(set (match_dup 0) (match_dup 1))
7375
   (set (match_dup 2) (match_dup 1))]
7376
  "")
7377
 
7378
;; Replace "ldd #N; addd " with "ldd ; addd #N".
7379
;;
7380
(define_peephole2
7381
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7382
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7383
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7384
   (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7385
   (match_scratch:HI 4 "d")]
7386
  ""
7387
  [(set (match_dup 4) (const_int 0))
7388
   (set (match_dup 0) (match_dup 4))
7389
   (set (match_dup 1) (match_dup 4))
7390
   (set (match_dup 2) (match_dup 4))
7391
   (set (match_dup 3) (match_dup 4))]
7392
  "")
7393
 
7394
;;
7395
;; Replace "ldd #N; addd " with "ldd ; addd #N".
7396
;;
7397
(define_peephole2
7398
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7399
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7400
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7401
   (match_scratch:HI 3 "d")]
7402
  ""
7403
  [(set (match_dup 3) (const_int 0))
7404
   (set (match_dup 0) (match_dup 3))
7405
   (set (match_dup 1) (match_dup 3))
7406
   (set (match_dup 2) (match_dup 3))]
7407
  "")
7408
 
7409
;;
7410
;; Replace "ldd #N; addd " with "ldd ; addd #N".
7411
;;
7412
(define_peephole2
7413
  [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7414
   (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7415
   (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7416
   (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7417
   (match_scratch:HI 4 "x")]
7418
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7419
  [(set (match_dup 4) (const_int 0))
7420
   (set (match_dup 1) (match_dup 4))
7421
   (set (match_dup 2) (match_dup 4))
7422
   (set (match_dup 3) (match_dup 4))]
7423
  "")
7424
 
7425
;;
7426
;; This peephole catches the address computations generated by the reload
7427
;; pass.
7428
(define_peephole
7429
  [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7430
        (match_operand:HI 1 "const_int_operand" ""))
7431
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7432
              (set (match_dup 0) (reg:HI D_REGNUM))])
7433
   (set (reg:HI D_REGNUM)
7434
        (plus (reg:HI D_REGNUM)
7435
              (match_operand:HI 2 "general_operand" "")))
7436
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7437
              (set (match_dup 0) (reg:HI D_REGNUM))])]
7438
  "(INTVAL (operands[1]) & 0x0FF) == 0"
7439
  "*
7440
{
7441
  int value_loaded = 1;
7442
 
7443
  if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7444
    {
7445
      rtx ops[2];
7446
 
7447
      ops[0] = operands[0];
7448
      ops[1] = operands[2];
7449
      m68hc11_gen_movhi (insn, ops);
7450
      output_asm_insn (\"xgd%0\", operands);
7451
    }
7452
  else if (Y_REG_P (operands[0]))
7453
    {
7454
      if (reg_mentioned_p (iy_reg, operands[2]))
7455
        output_asm_insn (\"ldy\\t%2\", operands);
7456
      else
7457
        value_loaded = 0;
7458
      output_asm_insn (\"xgdy\", operands);
7459
    }
7460
  else
7461
    {
7462
      output_asm_insn (\"ldd\\t%2\", operands);
7463
    }
7464
 
7465
  if (value_loaded == 0)
7466
    output_asm_insn (\"ldd\\t%2\", operands);
7467
  if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7468
    output_asm_insn (\"inca\", operands);
7469
  else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7470
    output_asm_insn (\"deca\", operands);
7471
  else if (INTVAL (operands[1]) != 0)
7472
    output_asm_insn (\"adda\\t%h1\", operands);
7473
 
7474
  if (X_REG_P (operands[0]))
7475
    return \"xgdx\";
7476
  else if (Y_REG_P (operands[0]))
7477
    return \"xgdy\";
7478
  else
7479
    return \"\";
7480
}
7481
")
7482
 
7483
(define_peephole
7484
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
7485
        (match_operand:HI 1 "non_push_operand" "g"))
7486
   (set (match_operand:HI 2 "hard_reg_operand" "h")
7487
        (match_dup 0))]
7488
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7489
   && !S_REG_P (operands[2])"
7490
  "*
7491
{
7492
  rtx ops[2];
7493
 
7494
  ops[0] = operands[2];
7495
  ops[1] = operands[1];
7496
  m68hc11_gen_movhi (insn, ops);
7497
  return \"\";
7498
}
7499
")
7500
 
7501
(define_peephole
7502
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
7503
        (match_operand:HI 1 "hard_reg_operand" "h"))
7504
   (set (match_operand:HI 2 "non_push_operand" "g")
7505
        (match_dup 0))]
7506
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7507
   && !S_REG_P (operands[2])"
7508
  "*
7509
{
7510
  rtx ops[2];
7511
 
7512
  ops[0] = operands[2];
7513
  ops[1] = operands[1];
7514
  m68hc11_gen_movhi (insn, ops);
7515
  return \"\";
7516
}
7517
")
7518
 
7519
;;
7520
;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7521
;; the set, so we don't need to emit anything. 'ins1' refers to the
7522
;; (set ...) insn.
7523
;;
7524
(define_peephole
7525
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7526
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7527
              (set (match_dup 0) (reg:HI D_REGNUM))])]
7528
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7529
  "*
7530
{
7531
   cc_status = cc_prev_status;
7532
   return \"\";
7533
}
7534
")
7535
 
7536
;; Same as above but due to some split, there may be a noop set
7537
;; between the two.
7538
(define_peephole
7539
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7540
   (set (match_dup 0) (match_dup 0))
7541
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7542
              (set (match_dup 0) (reg:HI D_REGNUM))])]
7543
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7544
  "*
7545
{
7546
   cc_status = cc_prev_status;
7547
   return \"\";
7548
}
7549
")
7550
 
7551
;;
7552
;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7553
;; and we must, at least, setup X/Y with value of D.
7554
;;
7555
(define_peephole
7556
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7557
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7558
              (set (match_dup 0) (reg:HI D_REGNUM))])]
7559
  ""
7560
  "*
7561
{
7562
  rtx ops[2];
7563
 
7564
  ops[0] = operands[0];
7565
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7566
  m68hc11_gen_movhi (insn, ops);
7567
  return \"\";
7568
}
7569
")
7570
 
7571
;;;
7572
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7573
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7574
;;;
7575
(define_peephole
7576
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7577
              (set (match_dup 0) (reg:HI D_REGNUM))])
7578
   (set (reg:HI D_REGNUM) (match_dup 0))]
7579
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7580
  "*
7581
{
7582
  cc_status = cc_prev_status;
7583
  return \"\";
7584
}
7585
")
7586
 
7587
;;;
7588
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7589
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7590
;;;
7591
(define_peephole
7592
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7593
              (set (match_dup 0) (reg:HI D_REGNUM))])
7594
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7595
  "REGNO (operands[0]) == REGNO (operands[1])
7596
   && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7597
  "*
7598
{
7599
  cc_status = cc_prev_status;
7600
  return \"\";
7601
}
7602
")
7603
 
7604
;;;
7605
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7606
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7607
;;;
7608
(define_peephole
7609
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7610
              (set (match_dup 0) (reg:HI D_REGNUM))])
7611
   (set (reg:HI D_REGNUM) (match_dup 0))]
7612
  ""
7613
  "*
7614
{
7615
  rtx ops[2];
7616
 
7617
  ops[0] = operands[0];
7618
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7619
  m68hc11_gen_movhi (insn, ops);
7620
  return \"\";
7621
}
7622
")
7623
 
7624
;;;
7625
;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
7626
;;; with the xgdx.
7627
;;;
7628
(define_peephole
7629
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7630
              (set (match_dup 0) (reg:HI D_REGNUM))])
7631
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7632
  "REGNO (operands[0]) == REGNO (operands[1])"
7633
  "*
7634
{
7635
  rtx ops[2];
7636
 
7637
  ops[0] = operands[0];
7638
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7639
  m68hc11_gen_movhi (insn, ops);
7640
  return \"\";
7641
}
7642
")
7643
 
7644
;;;
7645
;;; Catch two consecutive xgdx or xgdy, emit nothing.
7646
;;;
7647
(define_peephole
7648
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7649
              (set (match_dup 0) (reg:HI D_REGNUM))])
7650
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7651
              (set (match_dup 0) (reg:HI D_REGNUM))])]
7652
  ""
7653
  "*
7654
{
7655
  cc_status = cc_prev_status;
7656
  return \"\";
7657
}
7658
")
7659
 
7660
(define_peephole
7661
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7662
        (match_operand:HI 1 "stack_register_operand" ""))
7663
   (set (match_operand:HI 2 "hard_reg_operand" "")
7664
        (match_operand:HI 3 "memory_operand" "m"))
7665
   (set (match_dup 0)
7666
        (match_operand:HI 4 "memory_operand" "m"))]
7667
  "IS_STACK_POP (operands[4])
7668
   && (GET_CODE (operands[3]) == MEM &&
7669
       rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7670
  "*
7671
{
7672
  rtx ops[2];
7673
 
7674
  ops[0] = operands[2];
7675
  ops[1] = gen_rtx_MEM (HImode,
7676
                    gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7677
  m68hc11_gen_movhi (insn, ops);
7678
  return \"\";
7679
}
7680
")
7681
 
7682
;;
7683
;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7684
;;
7685
(define_peephole
7686
  [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7687
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7688
  "TARGET_M6811"
7689
  "*
7690
{
7691
  return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7692
}
7693
")
7694
 
7695
(define_peephole
7696
  [(set (match_operand:HI 0 "hard_reg_operand" "")
7697
        (match_operand:HI 1 "memory_operand" ""))
7698
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7699
  "TARGET_M6811
7700
   && !side_effects_p (operands[1])
7701
   && !reg_mentioned_p (operands[0], operands[1])"
7702
  "*
7703
{
7704
  rtx ops[2];
7705
 
7706
  ops[0] = operands[0];
7707
  ops[1] = operands[1];
7708
  m68hc11_gen_movhi (insn, ops);
7709
  ops[0] = operands[2];
7710
  m68hc11_gen_movhi (insn, ops);
7711
  return \"\";
7712
}")
7713
 
7714
;; Peephole for Z register replacement.
7715
;; Avoid to use _.tmp register when comparing D and X if we can compare
7716
;; with soft register
7717
(define_peephole
7718
  [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7719
   (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7720
   (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7721
                       (reg:HI SOFT_TMP_REGNUM)))]
7722
  "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7723
  "*
7724
{
7725
  rtx ops[2];
7726
 
7727
  ops[0] = operands[0];
7728
  ops[1] = operands[1];
7729
  m68hc11_gen_movhi (insn, ops);
7730
  return \"cp%2\\t%1\";
7731
}")

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.