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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [m68hc11/] [m68hc11.md] - Blame information for rev 292

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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