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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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