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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [pdp11/] [pdp11.md] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;;- Machine description for the pdp11 for GNU C compiler
2
;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005
3
;; 2007, 2008, 2010 Free Software Foundation, Inc.
4
;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
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
(include "predicates.md")
23
(include "constraints.md")
24
 
25
(define_c_enum "unspecv"
26
  [
27
    UNSPECV_BLOCKAGE
28
    UNSPECV_SETD
29
    UNSPECV_SETI
30
  ])
31
 
32
(define_constants
33
  [
34
   ;; Register numbers
35
   (R0_REGNUM             0)
36
   (RETVAL_REGNUM         0)
37
   (HARD_FRAME_POINTER_REGNUM  5)
38
   (STACK_POINTER_REGNUM  6)
39
   (PC_REGNUM             7)
40
   (AC0_REGNUM            8)
41
   (AC3_REGNUM            11)
42
   (AC4_REGNUM            12)
43
   (AC5_REGNUM            13)
44
   ;; The next two are not physical registers but are used for addressing
45
   ;; arguments.
46
   (FRAME_POINTER_REGNUM  14)
47
   (ARG_POINTER_REGNUM    15)
48
   (FIRST_PSEUDO_REGISTER 16)
49
   ;; Branch offset limits, as byte offsets from instruction address
50
   (MIN_BRANCH            -254)
51
   (MAX_BRANCH            256)
52
   (MIN_SOB               -126)
53
   (MAX_SOB               0)])
54
 
55
;; HI is 16 bit
56
;; QI is 8 bit
57
 
58
;; Integer modes supported on the PDP11, with a mapping from machine mode
59
;; to mnemonic suffix.  SImode and DImode always are special cases.
60
(define_mode_iterator PDPint [QI HI])
61
(define_mode_attr  isfx [(QI "b") (HI "")])
62
 
63
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
64
 
65
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
66
;;- updates for most instructions.
67
 
68
;;- Operand classes for the register allocator:
69
 
70
;; Compare instructions.
71
 
72
;; currently we only support df floats, which saves us quite some
73
;; hassle switching the FP mode!
74
;; we assume that CPU is always in long float mode, and
75
;; 16 bit integer mode - currently, the prologue for main does this,
76
;; but maybe we should just set up a NEW crt0 properly,
77
;; -- and what about signal handling code?
78
;; (we don't even let sf floats in the register file, so
79
;; we only should have to worry about truncating and widening
80
;; when going to memory)
81
 
82
;; abort() call by g++ - must define libfunc for cmp_optab
83
;; and ucmp_optab for mode SImode, because we don't have that!!!
84
;; - yet since no libfunc is there, we abort ()
85
 
86
;; The only thing that remains to be done then is output
87
;; the floats in a way the assembler can handle it (and
88
;; if you're really into it, use a PDP11 float emulation
89
;; library to do floating point constant folding - but
90
;; I guess you'll get reasonable results even when not
91
;; doing this)
92
;; the last thing to do is fix the UPDATE_CC macro to check
93
;; for floating point condition codes, and set cc_status
94
;; properly, also setting the CC_IN_FCCR flag.
95
 
96
;; define attributes
97
;; currently type is only fpu or arith or unknown, maybe branch later ?
98
;; default is arith
99
(define_attr "type" "unknown,arith,fp" (const_string "arith"))
100
 
101
;; length default is 2 bytes each
102
(define_attr "length" "" (const_int 2))
103
 
104
;; a user's asm statement
105
(define_asm_attributes
106
  [(set_attr "type" "unknown")
107
; length for asm is the max length per statement.  That would be
108
; 3 words, for a two-operand instruction with extra word addressing
109
; modes for both operands.
110
   (set_attr "length" "6")])
111
 
112
;; define function units
113
 
114
;; Prologue and epilogue support.
115
 
116
(define_expand "prologue"
117
  [(const_int 0)]
118
  ""
119
{
120
  pdp11_expand_prologue ();
121
  DONE;
122
})
123
 
124
(define_expand "epilogue"
125
  [(const_int 0)]
126
  ""
127
{
128
  pdp11_expand_epilogue ();
129
  DONE;
130
})
131
 
132
(define_expand "return"
133
  [(return)]
134
  "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
135
  "")
136
 
137
(define_insn "*rts"
138
  [(return)]
139
  ""
140
  "rts pc")
141
 
142
(define_insn "blockage"
143
  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
144
  ""
145
  ""
146
  [(set_attr "length" "0")])
147
 
148
(define_insn "setd"
149
  [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
150
  ""
151
  "setd")
152
 
153
(define_insn "seti"
154
  [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
155
  ""
156
  "seti")
157
 
158
;; arithmetic - values here immediately when next insn issued
159
;; or does it mean the number of cycles after this insn was issued?
160
;; how do I say that fpu insns use cpu also? (pre-interaction phase)
161
 
162
;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
163
;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
164
 
165
;; compare
166
(define_insn "*cmpdf"
167
  [(set (cc0)
168
        (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
169
                 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
170
  "TARGET_FPU"
171
  "*
172
{
173
  cc_status.flags = CC_IN_FPU;
174
  if (which_alternative == 0 || which_alternative == 2)
175
    return \"{tstd|tstf} %0\;cfcc\";
176
  else
177
    return \"{cmpd|cmpf} %0, %1\;cfcc\";
178
}"
179
  [(set_attr "length" "4,4,6,6")])
180
 
181
(define_insn "*cmp"
182
  [(set (cc0)
183
        (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
184
                 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
185
  ""
186
  "@
187
   tst %0
188
   cmp %0,%1
189
   cmp %0,%1
190
   tst %0
191
   cmp %0,%1
192
   cmp %0,%1"
193
  [(set_attr "length" "2,2,4,4,4,6")])
194
 
195
;; sob instruction - we need an assembler which can make this instruction
196
;; valid under _all_ circumstances!
197
 
198
(define_insn ""
199
  [(set (pc)
200
        (if_then_else
201
         (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
202
                      (const_int -1))
203
             (const_int 0))
204
         (label_ref (match_operand 1 "" ""))
205
         (pc)))
206
   (set (match_dup 0)
207
        (plus:HI (match_dup 0)
208
                 (const_int -1)))]
209
  "TARGET_40_PLUS"
210
  "*
211
{
212
 static int labelcount = 0;
213
 static char buf[1000];
214
 
215
 if (get_attr_length (insn) == 2)
216
    return \"sob %0, %l1\";
217
 
218
 /* emulate sob */
219
 output_asm_insn (\"dec %0\", operands);
220
 
221
 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
222
 output_asm_insn (buf, NULL);
223
 
224
 output_asm_insn (\"jmp %l1\", operands);
225
 
226
 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
227
 output_asm_insn (buf, NULL);
228
 
229
 return \"\";
230
}"
231
  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
232
                                                       (pc))
233
                                                (const_int MIN_SOB))
234
                                           (gt (minus (match_dup 0)
235
                                                       (pc))
236
                                                (const_int MAX_SOB)))
237
                                      (const_int 8)
238
                                      (const_int 2)))])
239
 
240
;; These control RTL generation for conditional jump insns
241
;; and match them for register allocation.
242
 
243
(define_expand "cbranchdf4"
244
  [(set (cc0)
245
        (compare (match_operand:DF 1 "general_operand")
246
                 (match_operand:DF 2 "register_or_const0_operand")))
247
   (set (pc)
248
        (if_then_else (match_operator 0 "ordered_comparison_operator"
249
                       [(cc0) (const_int 0)])
250
                      (label_ref (match_operand 3 "" ""))
251
                      (pc)))]
252
  "TARGET_FPU"
253
  "")
254
 
255
(define_expand "cbranch4"
256
  [(set (cc0)
257
        (compare (match_operand:PDPint 1 "general_operand")
258
                 (match_operand:PDPint 2 "general_operand")))
259
   (set (pc)
260
        (if_then_else (match_operator 0 "ordered_comparison_operator"
261
                       [(cc0) (const_int 0)])
262
                      (label_ref (match_operand 3 "" ""))
263
                      (pc)))]
264
  ""
265
  "")
266
 
267
;; problem with too short jump distance! we need an assembler which can
268
;; make this valid for all jump distances!
269
;; e.g. gas!
270
 
271
;; these must be changed to check for CC_IN_FCCR if float is to be
272
;; enabled
273
 
274
(define_insn "*branch"
275
  [(set (pc)
276
        (if_then_else (match_operator 0 "ordered_comparison_operator"
277
                       [(cc0) (const_int 0)])
278
                      (label_ref (match_operand 1 "" ""))
279
                      (pc)))]
280
  ""
281
  "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
282
  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
283
                                                      (pc))
284
                                               (const_int MIN_BRANCH))
285
                                           (gt (minus (match_dup 1)
286
                                                      (pc))
287
                                               (const_int MAX_BRANCH)))
288
                                      (const_int 6)
289
                                      (const_int 2)))])
290
 
291
 
292
;; These match inverted jump insns for register allocation.
293
 
294
(define_insn "*branch_inverted"
295
  [(set (pc)
296
        (if_then_else (match_operator 0 "ordered_comparison_operator"
297
                       [(cc0) (const_int 0)])
298
                      (pc)
299
                      (label_ref (match_operand 1 "" ""))))]
300
  ""
301
  "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
302
  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
303
                                                      (pc))
304
                                               (const_int MIN_BRANCH))
305
                                           (gt (minus (match_dup 1)
306
                                                      (pc))
307
                                               (const_int MAX_BRANCH)))
308
                                      (const_int 6)
309
                                      (const_int 2)))])
310
 
311
;; Move instructions
312
 
313
(define_insn "movdi"
314
  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
315
        (match_operand:DI 1 "general_operand" "rN,g"))]
316
  ""
317
  "* return output_move_multiple (operands);"
318
;; what's the mose expensive code - say twice movsi = 16
319
  [(set_attr "length" "16,32")])
320
 
321
(define_insn "movsi"
322
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
323
        (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
324
  ""
325
  "* return output_move_multiple (operands);"
326
;; what's the most expensive code ? - I think 8!
327
;; we could split it up and make several sub-cases...
328
  [(set_attr "length" "4,6,8,16")])
329
 
330
(define_insn "mov"
331
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
332
        (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
333
  ""
334
  "*
335
{
336
  if (operands[1] == const0_rtx)
337
    return \"clr %0\";
338
 
339
  return \"mov %1, %0\";
340
}"
341
  [(set_attr "length" "2,4,4,6")])
342
 
343
(define_insn "movdf"
344
  [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
345
        (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
346
  "TARGET_FPU"
347
  "* if (which_alternative ==0 || which_alternative == 2)
348
       return \"ldd %1, %0\";
349
     else if (which_alternative == 1 || which_alternative == 3)
350
       return \"std %1, %0\";
351
     else
352
       return output_move_multiple (operands); "
353
;; last one is worst-case
354
  [(set_attr "length" "2,2,4,4,24")])
355
 
356
(define_insn "movsf"
357
  [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
358
        (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
359
  "TARGET_FPU"
360
  "* if (which_alternative ==0 || which_alternative == 2)
361
       return \"{ldcfd|movof} %1, %0\";
362
     else if (which_alternative == 1 || which_alternative == 3)
363
       return \"{stcdf|movfo} %1, %0\";
364
     else
365
       return output_move_multiple (operands); "
366
;; last one is worst-case
367
  [(set_attr "length" "2,2,4,4,12")])
368
 
369
;; maybe fiddle a bit with move_ratio, then
370
;; let constraints only accept a register ...
371
 
372
(define_expand "movmemhi"
373
  [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
374
                   (match_operand:BLK 1 "general_operand" "g,g"))
375
              (use (match_operand:HI 2 "general_operand" "n,mr"))
376
              (use (match_operand:HI 3 "immediate_operand" "i,i"))
377
              (clobber (match_scratch:HI 4 "=&r,X"))
378
              (clobber (match_dup 5))
379
              (clobber (match_dup 6))
380
              (clobber (match_dup 2))])]
381
  "(TARGET_BCOPY_BUILTIN)"
382
  "
383
{
384
  operands[0]
385
    = replace_equiv_address (operands[0],
386
                             copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
387
  operands[1]
388
    = replace_equiv_address (operands[1],
389
                             copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
390
 
391
  operands[5] = XEXP (operands[0], 0);
392
  operands[6] = XEXP (operands[1], 0);
393
}")
394
 
395
 
396
(define_insn "movmemhi1"
397
  [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
398
        (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
399
   (use (match_operand:HI 2 "general_operand" "n,r"))
400
   (use (match_operand:HI 3 "immediate_operand" "i,i"))
401
   (clobber (match_scratch:HI 4 "=&r,X"))
402
   (clobber (match_dup 0))
403
   (clobber (match_dup 1))
404
   (clobber (match_dup 2))]
405
  "(TARGET_BCOPY_BUILTIN)"
406
  "* return output_block_move (operands);"
407
;;; just a guess
408
  [(set_attr "length" "80")])
409
 
410
 
411
 
412
;;- truncation instructions
413
 
414
(define_insn  "truncdfsf2"
415
  [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
416
        (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
417
  "TARGET_FPU"
418
  "* if (which_alternative ==0)
419
     {
420
       return \"\";
421
     }
422
     else if (which_alternative == 1)
423
       return \"{stcdf|movfo} %1, %0\";
424
     else
425
       return \"{stcdf|movfo} %1, %0\";
426
  "
427
  [(set_attr "length" "0,2,4")])
428
 
429
 
430
(define_expand "truncsihi2"
431
  [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
432
        (subreg:HI
433
          (match_operand:SI 1 "general_operand" "or")
434
          0))]
435
  ""
436
  "")
437
 
438
 
439
;;- zero extension instructions
440
 
441
(define_insn "zero_extendqihi2"
442
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
443
        (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
444
  ""
445
  "bic $0177400, %0"
446
  [(set_attr "length" "4,6")])
447
 
448
(define_expand "zero_extendhisi2"
449
  [(set (subreg:HI
450
          (match_dup 0)
451
          2)
452
        (match_operand:HI 1 "register_operand" "r"))
453
   (set (subreg:HI
454
          (match_operand:SI 0 "register_operand" "=r")
455
          0)
456
        (const_int 0))]
457
  ""
458
  "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
459
 
460
 
461
;;- sign extension instructions
462
 
463
(define_insn "extendsfdf2"
464
  [(set (match_operand:DF 0 "register_operand" "=f,a,a")
465
        (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
466
  "TARGET_FPU"
467
  "@
468
   /* nothing */
469
   {ldcfd|movof} %1, %0
470
   {ldcfd|movof} %1, %0"
471
  [(set_attr "length" "0,2,4")])
472
 
473
;; does movb sign extend in register-to-register move?
474
(define_insn "extendqihi2"
475
  [(set (match_operand:HI 0 "register_operand" "=r,r")
476
        (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
477
  ""
478
  "movb %1, %0"
479
  [(set_attr "length" "2,4")])
480
 
481
(define_insn "extendqisi2"
482
  [(set (match_operand:SI 0 "register_operand" "=r,r")
483
        (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
484
  "TARGET_40_PLUS"
485
  "*
486
{
487
  rtx latehalf[2];
488
 
489
  /* make register pair available */
490
  latehalf[0] = operands[0];
491
  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
492
 
493
  output_asm_insn(\"movb %1, %0\", operands);
494
  output_asm_insn(\"sxt %0\", latehalf);
495
 
496
  return \"\";
497
}"
498
  [(set_attr "length" "4,6")])
499
 
500
;; maybe we have to use define_expand to say that we have the instruction,
501
;; unconditionally, and then match dependent on CPU type:
502
 
503
(define_expand "extendhisi2"
504
  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
505
        (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
506
  ""
507
  "")
508
 
509
(define_insn "" ; "extendhisi2"
510
  [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
511
        (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
512
  "TARGET_40_PLUS"
513
  "*
514
{
515
  rtx latehalf[2];
516
 
517
  /* we don't want to mess with auto increment */
518
 
519
  switch (which_alternative)
520
  {
521
    case 0:
522
 
523
      latehalf[0] = operands[0];
524
      operands[0] = adjust_address(operands[0], HImode, 2);
525
 
526
      output_asm_insn(\"mov %1, %0\", operands);
527
      output_asm_insn(\"sxt %0\", latehalf);
528
 
529
      return \"\";
530
 
531
    case 1:
532
 
533
      /* - auto-decrement - right direction ;-) */
534
      output_asm_insn(\"mov %1, %0\", operands);
535
      output_asm_insn(\"sxt %0\", operands);
536
 
537
      return \"\";
538
 
539
    case 2:
540
 
541
      /* make register pair available */
542
      latehalf[0] = operands[0];
543
      operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
544
 
545
      output_asm_insn(\"mov %1, %0\", operands);
546
      output_asm_insn(\"sxt %0\", latehalf);
547
 
548
      return \"\";
549
 
550
    default:
551
 
552
      gcc_unreachable ();
553
  }
554
}"
555
  [(set_attr "length" "10,6,6")])
556
 
557
 
558
(define_insn ""
559
  [(set (match_operand:SI 0 "register_operand" "=r")
560
        (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
561
  "(! TARGET_40_PLUS)"
562
  "*
563
{
564
  static int count = 0;
565
  char buf[100];
566
  rtx lateoperands[2];
567
 
568
  lateoperands[0] = operands[0];
569
  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
570
 
571
  output_asm_insn(\"tst %0\", operands);
572
  sprintf(buf, \"bge extendhisi%d\", count);
573
  output_asm_insn(buf, NULL);
574
  output_asm_insn(\"mov -1, %0\", lateoperands);
575
  sprintf(buf, \"bne extendhisi%d\", count+1);
576
  output_asm_insn(buf, NULL);
577
  sprintf(buf, \"\\nextendhisi%d:\", count);
578
  output_asm_insn(buf, NULL);
579
  output_asm_insn(\"clr %0\", lateoperands);
580
  sprintf(buf, \"\\nextendhisi%d:\", count+1);
581
  output_asm_insn(buf, NULL);
582
 
583
  count += 2;
584
 
585
  return \"\";
586
}"
587
  [(set_attr "length" "12")])
588
 
589
;; make float to int and vice versa
590
;; using the cc_status.flag field we could probably cut down
591
;; on seti and setl
592
;; assume that we are normally in double and integer mode -
593
;; what do pdp library routines do to fpu mode ?
594
 
595
(define_insn "floatsidf2"
596
  [(set (match_operand:DF 0 "register_operand" "=a,a,a")
597
        (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
598
  "TARGET_FPU"
599
  "* if (which_alternative ==0)
600
     {
601
       rtx latehalf[2];
602
 
603
       latehalf[0] = NULL;
604
       latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
605
       output_asm_insn(\"mov %1, -(sp)\", latehalf);
606
       output_asm_insn(\"mov %1, -(sp)\", operands);
607
 
608
       output_asm_insn(\"setl\", operands);
609
       output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
610
       output_asm_insn(\"seti\", operands);
611
       return \"\";
612
     }
613
     else if (which_alternative == 1)
614
       return \"setl\;{ldcld|movif} %1, %0\;seti\";
615
     else
616
       return \"setl\;{ldcld|movif} %1, %0\;seti\";
617
  "
618
  [(set_attr "length" "10,6,8")])
619
 
620
(define_insn "floathidf2"
621
  [(set (match_operand:DF 0 "register_operand" "=a,a")
622
        (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
623
  "TARGET_FPU"
624
  "{ldcid|movif} %1, %0"
625
  [(set_attr "length" "2,4")])
626
 
627
;; cut float to int
628
(define_insn "fix_truncdfsi2"
629
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
630
        (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
631
  "TARGET_FPU"
632
  "* if (which_alternative ==0)
633
     {
634
       output_asm_insn(\"setl\", operands);
635
       output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
636
       output_asm_insn(\"seti\", operands);
637
       output_asm_insn(\"mov (sp)+, %0\", operands);
638
       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
639
       output_asm_insn(\"mov (sp)+, %0\", operands);
640
       return \"\";
641
     }
642
     else if (which_alternative == 1)
643
       return \"setl\;{stcdl|movfi} %1, %0\;seti\";
644
     else
645
       return \"setl\;{stcdl|movfi} %1, %0\;seti\";
646
  "
647
  [(set_attr "length" "10,6,8")])
648
 
649
(define_insn "fix_truncdfhi2"
650
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
651
        (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
652
  "TARGET_FPU"
653
  "{stcdi|movfi} %1, %0"
654
  [(set_attr "length" "2,4")])
655
 
656
 
657
;;- arithmetic instructions
658
;;- add instructions
659
 
660
(define_insn "adddf3"
661
  [(set (match_operand:DF 0 "register_operand" "=a,a")
662
        (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
663
                 (match_operand:DF 2 "general_operand" "fR,QF")))]
664
  "TARGET_FPU"
665
  "{addd|addf} %2, %0"
666
  [(set_attr "length" "2,4")])
667
 
668
(define_insn "adddi3"
669
  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
670
        (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
671
                 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
672
  ""
673
  "*
674
{
675
  rtx inops[2];
676
  rtx exops[4][2];
677
 
678
  inops[0] = operands[0];
679
  inops[1] = operands[2];
680
  pdp11_expand_operands (inops, exops, 2, NULL, either);
681
 
682
  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
683
    output_asm_insn (\"add %1, %0\", exops[0]);
684
  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
685
  {
686
    output_asm_insn (\"add %1, %0\", exops[1]);
687
    output_asm_insn (\"adc %0\", exops[0]);
688
  }
689
  if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
690
  {
691
    output_asm_insn (\"add %1, %0\", exops[2]);
692
    output_asm_insn (\"adc %0\", exops[1]);
693
    output_asm_insn (\"adc %0\", exops[0]);
694
  }
695
  if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
696
  {
697
    output_asm_insn (\"add %1, %0\", exops[3]);
698
    output_asm_insn (\"adc %0\", exops[2]);
699
    output_asm_insn (\"adc %0\", exops[1]);
700
    output_asm_insn (\"adc %0\", exops[0]);
701
  }
702
 
703
  return \"\";
704
}"
705
  [(set_attr "length" "20,28,40,48")])
706
 
707
;; Note that the register operand is not marked earlyclobber.
708
;; The reason is that SI values go in register pairs, so they
709
;; can't partially overlap.  They can be either disjoint, or
710
;; source and destination can be equal.  The latter case is
711
;; handled properly because of the ordering of the individual
712
;; instructions used.  Specifically, carry from the low to the
713
;; high word is added at the end, so the adding of the high parts
714
;; will always used the original high part and not a high part
715
;; modified by carry (which would amount to double carry).
716
(define_insn "addsi3"
717
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
718
        (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
719
                 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
720
  ""
721
  "*
722
{
723
  rtx inops[2];
724
  rtx exops[2][2];
725
 
726
  inops[0] = operands[0];
727
  inops[1] = operands[2];
728
  pdp11_expand_operands (inops, exops, 2, NULL, either);
729
 
730
  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
731
    output_asm_insn (\"add %1, %0\", exops[0]);
732
  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
733
  {
734
    output_asm_insn (\"add %1, %0\", exops[1]);
735
    output_asm_insn (\"adc %0\", exops[0]);
736
  }
737
 
738
  return \"\";
739
}"
740
  [(set_attr "length" "6,10,12,16")])
741
 
742
(define_insn "addhi3"
743
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
744
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
745
                 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
746
  ""
747
  "*
748
{
749
  if (GET_CODE (operands[2]) == CONST_INT)
750
    {
751
      if (INTVAL(operands[2]) == 1)
752
        return \"inc %0\";
753
      else if (INTVAL(operands[2]) == -1)
754
        return \"dec %0\";
755
    }
756
 
757
  return \"add %2, %0\";
758
}"
759
  [(set_attr "length" "2,4,4,6")])
760
 
761
 
762
;;- subtract instructions
763
;; we don't have to care for constant second
764
;; args, since they are canonical plus:xx now!
765
;; also for minus:DF ??
766
 
767
(define_insn "subdf3"
768
  [(set (match_operand:DF 0 "register_operand" "=a,a")
769
        (minus:DF (match_operand:DF 1 "register_operand" "0,0")
770
                  (match_operand:DF 2 "general_operand" "fR,Q")))]
771
  "TARGET_FPU"
772
  "{subd|subf} %2, %0"
773
  [(set_attr "length" "2,4")])
774
 
775
(define_insn "subdi3"
776
  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
777
        (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
778
                 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
779
  ""
780
  "*
781
{
782
  rtx inops[2];
783
  rtx exops[4][2];
784
 
785
  inops[0] = operands[0];
786
  inops[1] = operands[2];
787
  pdp11_expand_operands (inops, exops, 2, NULL, either);
788
 
789
  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
790
    output_asm_insn (\"sub %1, %0\", exops[0]);
791
  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
792
  {
793
    output_asm_insn (\"sub %1, %0\", exops[1]);
794
    output_asm_insn (\"sbc %0\", exops[0]);
795
  }
796
  if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
797
  {
798
    output_asm_insn (\"sub %1, %0\", exops[2]);
799
    output_asm_insn (\"sbc %0\", exops[1]);
800
    output_asm_insn (\"sbc %0\", exops[0]);
801
  }
802
  if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
803
  {
804
    output_asm_insn (\"sub %1, %0\", exops[3]);
805
    output_asm_insn (\"sbc %0\", exops[2]);
806
    output_asm_insn (\"sbc %0\", exops[1]);
807
    output_asm_insn (\"sbc %0\", exops[0]);
808
  }
809
 
810
  return \"\";
811
}"
812
  [(set_attr "length" "20,28,40,48")])
813
 
814
(define_insn "subsi3"
815
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
816
        (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
817
                 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
818
  ""
819
  "*
820
{
821
  rtx inops[2];
822
  rtx exops[2][2];
823
 
824
  inops[0] = operands[0];
825
  inops[1] = operands[2];
826
  pdp11_expand_operands (inops, exops, 2, NULL, either);
827
 
828
  if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
829
    output_asm_insn (\"sub %1, %0\", exops[0]);
830
  if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
831
  {
832
    output_asm_insn (\"sub %1, %0\", exops[1]);
833
    output_asm_insn (\"sbc %0\", exops[0]);
834
  }
835
 
836
  return \"\";
837
}"
838
  [(set_attr "length" "6,10,12,16")])
839
 
840
(define_insn "subhi3"
841
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
842
        (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
843
                  (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
844
  ""
845
  "*
846
{
847
  gcc_assert (GET_CODE (operands[2]) != CONST_INT);
848
 
849
  return \"sub %2, %0\";
850
}"
851
  [(set_attr "length" "2,4,4,6")])
852
 
853
;;;;- and instructions
854
;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
855
 
856
(define_expand "and3"
857
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
858
        (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
859
                   (match_operand:PDPint 2 "general_operand" "")))]
860
  ""
861
  "
862
{
863
  rtx op1 = operands[1];
864
 
865
  /* If there is a constant argument, complement that one.
866
     Similarly, if one of the inputs is the same as the output,
867
     complement the other input.  */
868
  if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
869
      rtx_equal_p (operands[0], operands[1]))
870
    {
871
      operands[1] = operands[2];
872
      operands[2] = op1;
873
      op1 = operands[1];
874
    }
875
 
876
  if (CONST_INT_P (op1))
877
    operands[1] = GEN_INT (~INTVAL (op1));
878
  else
879
    operands[1] = expand_unop (mode, one_cmpl_optab, op1, 0, 1);
880
}")
881
 
882
(define_insn "*bic"
883
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
884
        (and:PDPint
885
             (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
886
             (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
887
  ""
888
  "bic %1, %0"
889
  [(set_attr "length" "2,4,4,6")])
890
 
891
;;- Bit set (inclusive or) instructions
892
(define_insn "ior3"
893
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
894
        (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
895
                (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
896
  ""
897
  "bis %2, %0"
898
  [(set_attr "length" "2,4,4,6")])
899
 
900
;;- xor instructions
901
(define_insn "xorhi3"
902
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
903
        (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
904
                (match_operand:HI 2 "register_operand" "r,r")))]
905
  "TARGET_40_PLUS"
906
  "xor %2, %0"
907
  [(set_attr "length" "2,4")])
908
 
909
;;- one complement instructions
910
 
911
(define_insn "one_cmpl2"
912
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
913
        (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
914
  ""
915
  "com %0"
916
  [(set_attr "length" "2,4")])
917
 
918
;;- arithmetic shift instructions
919
(define_insn "ashlsi3"
920
  [(set (match_operand:SI 0 "register_operand" "=r,r")
921
        (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
922
                   (match_operand:HI 2 "general_operand" "rR,Qi")))]
923
  "TARGET_40_PLUS"
924
  "ashc %2,%0"
925
  [(set_attr "length" "2,4")])
926
 
927
;; Arithmetic right shift on the pdp works by negating the shift count.
928
(define_expand "ashrsi3"
929
  [(set (match_operand:SI 0 "register_operand" "=r")
930
        (ashift:SI (match_operand:SI 1 "register_operand" "0")
931
                   (match_operand:HI 2 "general_operand" "g")))]
932
  ""
933
  "
934
{
935
  operands[2] = negate_rtx (HImode, operands[2]);
936
}")
937
 
938
;; define asl aslb asr asrb - ashc missing!
939
 
940
;; asl
941
(define_insn ""
942
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
943
        (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
944
                   (const_int 1)))]
945
  ""
946
  "asl %0"
947
  [(set_attr "length" "2,4")])
948
 
949
;; and another possibility for asr is << -1
950
;; might cause problems since -1 can also be encoded as 65535!
951
;; not in gcc2 ???
952
 
953
;; asr
954
(define_insn ""
955
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
956
        (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
957
                   (const_int -1)))]
958
  ""
959
  "asr %0"
960
  [(set_attr "length" "2,4")])
961
 
962
;; lsr
963
(define_insn "lsrhi1"
964
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
965
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
966
                   (const_int 1)))]
967
  ""
968
  "clc\;ror %0"
969
  [(set_attr "length" "2,4")])
970
 
971
(define_insn "lsrsi1"
972
  [(set (match_operand:SI 0 "register_operand" "=r")
973
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
974
                   (const_int 1)))]
975
  ""
976
{
977
 
978
  rtx lateoperands[2];
979
 
980
  lateoperands[0] = operands[0];
981
  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
982
 
983
  lateoperands[1] = operands[1];
984
  operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
985
 
986
  output_asm_insn (\"clc\", operands);
987
  output_asm_insn (\"ror %0\", lateoperands);
988
  output_asm_insn (\"ror %0\", operands);
989
 
990
  return \"\";
991
}
992
  [(set_attr "length" "10")])
993
 
994
(define_expand "lshrsi3"
995
  [(match_operand:SI 0 "register_operand" "")
996
   (match_operand:SI 1 "register_operand" "0")
997
   (match_operand:HI 2 "general_operand" "")]
998
  ""
999
  "
1000
{
1001
  rtx r;
1002
 
1003
  if (!TARGET_40_PLUS &&
1004
      (GET_CODE (operands[2]) != CONST_INT ||
1005
       (unsigned) INTVAL (operands[2]) > 3))
1006
    FAIL;
1007
  emit_insn (gen_lsrsi1 (operands[0], operands[1]));
1008
  if (GET_CODE (operands[2]) != CONST_INT)
1009
    {
1010
      r = gen_reg_rtx (HImode);
1011
      emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1012
      emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
1013
    }
1014
  else if ((unsigned) INTVAL (operands[2]) != 1)
1015
    {
1016
      emit_insn (gen_ashlsi3 (operands[0], operands[0],
1017
                              GEN_INT (1 - INTVAL (operands[2]))));
1018
    }
1019
  DONE;
1020
}
1021
"
1022
)
1023
 
1024
;; shift is by arbitrary count is expensive,
1025
;; shift by one cheap - so let's do that, if
1026
;; space doesn't matter
1027
(define_insn ""
1028
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
1029
        (ashift:HI (match_operand:HI 1 "general_operand" "0")
1030
                   (match_operand:HI 2 "expand_shift_operand" "O")))]
1031
  "! optimize_size"
1032
  "*
1033
{
1034
  register int i;
1035
 
1036
  for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1037
    if (INTVAL(operands[2]) < 0)
1038
      output_asm_insn(\"asr %0\", operands);
1039
    else
1040
      output_asm_insn(\"asl %0\", operands);
1041
 
1042
  return \"\";
1043
}"
1044
;; longest is 4
1045
  [(set (attr "length") (const_int 8))])
1046
 
1047
;; aslb
1048
(define_insn ""
1049
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1050
        (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1051
                   (match_operand:HI 2 "const_int_operand" "n,n")))]
1052
  ""
1053
  "*
1054
{ /* allowing predec or post_inc is possible, but hairy! */
1055
  int i, cnt;
1056
 
1057
  cnt = INTVAL(operands[2]) & 0x0007;
1058
 
1059
  for (i=0 ; i < cnt ; i++)
1060
       output_asm_insn(\"aslb %0\", operands);
1061
 
1062
  return \"\";
1063
}"
1064
;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1065
  [(set_attr_alternative "length"
1066
                         [(const_int 14)
1067
                          (const_int 28)])])
1068
 
1069
;;; asr
1070
;(define_insn ""
1071
;  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1072
;       (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1073
;                    (const_int 1)))]
1074
;  ""
1075
;  "asr %0"
1076
;  [(set_attr "length" "2,4")])
1077
 
1078
;; asrb
1079
(define_insn ""
1080
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1081
        (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1082
                     (match_operand:HI 2 "const_int_operand" "n,n")))]
1083
  ""
1084
  "*
1085
{ /* allowing predec or post_inc is possible, but hairy! */
1086
  int i, cnt;
1087
 
1088
  cnt = INTVAL(operands[2]) & 0x0007;
1089
 
1090
  for (i=0 ; i < cnt ; i++)
1091
       output_asm_insn(\"asrb %0\", operands);
1092
 
1093
  return \"\";
1094
}"
1095
  [(set_attr_alternative "length"
1096
                         [(const_int 14)
1097
                          (const_int 28)])])
1098
 
1099
;; the following is invalid - too complex!!! - just say 14 !!!
1100
;  [(set (attr "length") (plus (and (match_dup 2)
1101
;                                   (const_int 14))
1102
;                              (and (match_dup 2)
1103
;                                   (const_int 14))))])
1104
 
1105
 
1106
 
1107
;; can we get +-1 in the next pattern? should
1108
;; have been caught by previous patterns!
1109
 
1110
(define_insn "ashlhi3"
1111
  [(set (match_operand:HI 0 "register_operand" "=r,r")
1112
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1113
                   (match_operand:HI 2 "general_operand" "rR,Qi")))]
1114
  "TARGET_40_PLUS"
1115
  "*
1116
{
1117
  if (GET_CODE(operands[2]) == CONST_INT)
1118
    {
1119
      if (INTVAL(operands[2]) == 1)
1120
        return \"asl %0\";
1121
      else if (INTVAL(operands[2]) == -1)
1122
        return \"asr %0\";
1123
    }
1124
 
1125
  return \"ash %2,%0\";
1126
}"
1127
  [(set_attr "length" "2,4")])
1128
 
1129
;; Arithmetic right shift on the pdp works by negating the shift count.
1130
(define_expand "ashrhi3"
1131
  [(set (match_operand:HI 0 "register_operand" "=r")
1132
        (ashift:HI (match_operand:HI 1 "register_operand" "0")
1133
                   (match_operand:HI 2 "general_operand" "g")))]
1134
  ""
1135
  "
1136
{
1137
  operands[2] = negate_rtx (HImode, operands[2]);
1138
}")
1139
 
1140
(define_expand "lshrhi3"
1141
  [(match_operand:HI 0 "register_operand" "")
1142
   (match_operand:HI 1 "register_operand" "")
1143
   (match_operand:HI 2 "general_operand" "")]
1144
  ""
1145
  "
1146
{
1147
  rtx r;
1148
 
1149
  if (!TARGET_40_PLUS &&
1150
      (GET_CODE (operands[2]) != CONST_INT ||
1151
       (unsigned) INTVAL (operands[2]) > 3))
1152
    FAIL;
1153
  emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1154
  if (GET_CODE (operands[2]) != CONST_INT)
1155
    {
1156
      r = gen_reg_rtx (HImode);
1157
      emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1158
      emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1159
    }
1160
  else if ((unsigned) INTVAL (operands[2]) != 1)
1161
    {
1162
      emit_insn (gen_ashlhi3 (operands[0], operands[0],
1163
                              GEN_INT (1 - INTVAL (operands[2]))));
1164
    }
1165
  DONE;
1166
}
1167
"
1168
)
1169
 
1170
;; absolute
1171
 
1172
(define_insn "absdf2"
1173
  [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1174
        (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1175
  "TARGET_FPU"
1176
  "{absd|absf} %0"
1177
  [(set_attr "length" "2,4")])
1178
 
1179
 
1180
;; negate insns
1181
 
1182
(define_insn "negdf2"
1183
  [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
1184
        (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1185
  "TARGET_FPU"
1186
  "{negd|negf} %0"
1187
  [(set_attr "length" "2,4")])
1188
 
1189
(define_insn "negdi2"
1190
  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1191
        (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1192
  ""
1193
{
1194
  rtx exops[4][2];
1195
 
1196
  pdp11_expand_operands (operands, exops, 1, NULL, either);
1197
 
1198
  output_asm_insn (\"com %0\", exops[3]);
1199
  output_asm_insn (\"com %0\", exops[2]);
1200
  output_asm_insn (\"com %0\", exops[1]);
1201
  output_asm_insn (\"com %0\", exops[0]);
1202
  output_asm_insn (\"add $1, %0\", exops[3]);
1203
  output_asm_insn (\"adc %0\", exops[2]);
1204
  output_asm_insn (\"adc %0\", exops[1]);
1205
  output_asm_insn (\"adc %0\", exops[0]);
1206
 
1207
  return \"\";
1208
}
1209
[(set_attr "length" "18,34")])
1210
 
1211
(define_insn "negsi2"
1212
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1213
        (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1214
  ""
1215
{
1216
  rtx exops[2][2];
1217
 
1218
  pdp11_expand_operands (operands, exops, 1, NULL, either);
1219
 
1220
  output_asm_insn (\"com %0\", exops[1]);
1221
  output_asm_insn (\"com %0\", exops[0]);
1222
  output_asm_insn (\"add $1, %0\", exops[1]);
1223
  output_asm_insn (\"adc %0\", exops[0]);
1224
 
1225
  return \"\";
1226
}
1227
[(set_attr "length" "12,20")])
1228
 
1229
(define_insn "neg2"
1230
  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1231
        (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1232
  ""
1233
  "neg %0"
1234
  [(set_attr "length" "2,4")])
1235
 
1236
 
1237
;; Unconditional and other jump instructions
1238
(define_insn "jump"
1239
  [(set (pc)
1240
        (label_ref (match_operand 0 "" "")))]
1241
  ""
1242
  "*
1243
{
1244
 if (get_attr_length (insn) == 2)
1245
    return \"br %l0\";
1246
 return \"jmp %l0\";
1247
}"
1248
  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1249
                                                      (pc))
1250
                                               (const_int MIN_BRANCH))
1251
                                           (gt (minus (match_dup 0)
1252
                                                      (pc))
1253
                                               (const_int MAX_BRANCH)))
1254
                                      (const_int 4)
1255
                                      (const_int 2)))])
1256
 
1257
(define_insn ""
1258
  [(set (pc)
1259
    (label_ref (match_operand 0 "" "")))
1260
   (clobber (const_int 1))]
1261
  ""
1262
  "jmp %l0"
1263
  [(set_attr "length" "4")])
1264
 
1265
(define_insn "tablejump"
1266
  [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1267
   (use (label_ref (match_operand 1 "" "")))]
1268
  ""
1269
  "@
1270
  jmp (%0)
1271
  jmp %@%0
1272
  jmp %@%0"
1273
  [(set_attr "length" "2,2,4")])
1274
 
1275
;; indirect jump - let's be conservative!
1276
;; allow only register_operand, even though we could also
1277
;; allow labels etc.
1278
 
1279
(define_insn "indirect_jump"
1280
  [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1281
  ""
1282
  "jmp (%0)")
1283
 
1284
;;- jump to subroutine
1285
 
1286
(define_insn "call"
1287
  [(call (match_operand:HI 0 "general_operand" "rR,Q")
1288
         (match_operand:HI 1 "general_operand" "g,g"))
1289
;;   (use (reg:HI 0)) what was that ???
1290
  ]
1291
  ;;- Don't use operand 1 for most machines.
1292
  ""
1293
  "jsr pc, %0"
1294
  [(set_attr "length" "2,4")])
1295
 
1296
;;- jump to subroutine
1297
(define_insn "call_value"
1298
  [(set (match_operand 0 "" "")
1299
        (call (match_operand:HI 1 "general_operand" "rR,Q")
1300
              (match_operand:HI 2 "general_operand" "g,g")))
1301
;;   (use (reg:HI 0)) - what was that ????
1302
  ]
1303
  ;;- Don't use operand 2 for most machines.
1304
  ""
1305
  "jsr pc, %1"
1306
  [(set_attr "length" "2,4")])
1307
 
1308
;;- nop instruction
1309
(define_insn "nop"
1310
  [(const_int 0)]
1311
  ""
1312
  "nop")
1313
 
1314
 
1315
;;- multiply
1316
 
1317
(define_insn "muldf3"
1318
  [(set (match_operand:DF 0 "register_operand" "=a,a")
1319
        (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1320
                 (match_operand:DF 2 "float_operand" "fR,QF")))]
1321
  "TARGET_FPU"
1322
  "{muld|mulf} %2, %0"
1323
  [(set_attr "length" "2,4")])
1324
 
1325
;; 16 bit result multiply:
1326
;; currently we multiply only into odd registers, so we don't use two
1327
;; registers - but this is a bit inefficient at times. If we define
1328
;; a register class for each register, then we can specify properly
1329
;; which register need which scratch register ....
1330
 
1331
(define_insn "mulhi3"
1332
  [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1333
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1334
                 (match_operand:HI 2 "float_operand" "rR,Qi")))]
1335
  "TARGET_40_PLUS"
1336
  "mul %2, %0"
1337
  [(set_attr "length" "2,4")])
1338
 
1339
;; 32 bit result
1340
(define_expand "mulhisi3"
1341
  [(set (match_dup 3)
1342
        (match_operand:HI 1 "nonimmediate_operand" "g,g"))
1343
   (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1344
        (mult:SI (truncate:HI
1345
                  (match_dup 0))
1346
                 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1347
  "TARGET_40_PLUS"
1348
  "operands[3] = gen_lowpart(HImode, operands[1]);")
1349
 
1350
(define_insn ""
1351
  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1352
        (mult:SI (truncate:HI
1353
                  (match_operand:SI 1 "register_operand" "%0,0"))
1354
                 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1355
  "TARGET_40_PLUS"
1356
  "mul %2, %0"
1357
  [(set_attr "length" "2,4")])
1358
 
1359
;(define_insn "mulhisi3"
1360
;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1361
;       (mult:SI (truncate:HI
1362
;                  (match_operand:SI 1 "register_operand" "%0,0"))
1363
;                (match_operand:HI 2 "general_operand" "rR,Qi")))]
1364
;  "TARGET_40_PLUS"
1365
;  "mul %2, %0"
1366
;  [(set_attr "length" "2,4")])
1367
 
1368
;;- divide
1369
(define_insn "divdf3"
1370
  [(set (match_operand:DF 0 "register_operand" "=a,a")
1371
        (div:DF (match_operand:DF 1 "register_operand" "0,0")
1372
                (match_operand:DF 2 "general_operand" "fR,QF")))]
1373
  "TARGET_FPU"
1374
  "{divd|divf} %2, %0"
1375
  [(set_attr "length" "2,4")])
1376
 
1377
 
1378
(define_expand "divhi3"
1379
  [(set (subreg:HI (match_dup 1) 0)
1380
        (div:HI (match_operand:SI 1 "register_operand" "0")
1381
                (match_operand:HI 2 "general_operand" "g")))
1382
   (set (match_operand:HI 0 "register_operand" "=r")
1383
        (subreg:HI (match_dup 1) 0))]
1384
  "TARGET_40_PLUS"
1385
  "")
1386
 
1387
(define_insn ""
1388
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1389
        (div:HI (match_operand:SI 1 "general_operand" "0")
1390
                (match_operand:HI 2 "general_operand" "g")))]
1391
  "TARGET_40_PLUS"
1392
  "div %2,%0"
1393
  [(set_attr "length" "4")])
1394
 
1395
(define_expand "modhi3"
1396
  [(set (subreg:HI (match_dup 1) 2)
1397
        (mod:HI (match_operand:SI 1 "register_operand" "0")
1398
                (match_operand:HI 2 "general_operand" "g")))
1399
   (set (match_operand:HI 0 "register_operand" "=r")
1400
        (subreg:HI (match_dup 1) 2))]
1401
  "TARGET_40_PLUS"
1402
  "")
1403
 
1404
(define_insn ""
1405
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
1406
        (mod:HI (match_operand:SI 1 "general_operand" "0")
1407
                (match_operand:HI 2 "general_operand" "g")))]
1408
  "TARGET_40_PLUS"
1409
  "div %2,%0"
1410
  [(set_attr "length" "4")])
1411
 
1412
;(define_expand "divmodhi4"
1413
;  [(parallel [(set (subreg:HI (match_dup 1) 0)
1414
;                  (div:HI (match_operand:SI 1 "register_operand" "0")
1415
;                          (match_operand:HI 2 "general_operand" "g")))
1416
;              (set (subreg:HI (match_dup 1) 2)
1417
;                  (mod:HI (match_dup 1)
1418
;                          (match_dup 2)))])
1419
;   (set (match_operand:HI 3 "register_operand" "=r")
1420
;        (subreg:HI (match_dup 1) 2))
1421
;   (set (match_operand:HI 0 "register_operand" "=r")
1422
;        (subreg:HI (match_dup 1) 0))]
1423
;  "TARGET_40_PLUS"
1424
;  "")
1425
;
1426
;(define_insn ""
1427
;  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1428
;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1429
;                          (match_operand:HI 2 "general_operand" "g")))
1430
;   (set (subreg:HI (match_dup 0) 2)
1431
;                  (mod:HI (match_dup 1)
1432
;                          (match_dup 2)))]
1433
;  "TARGET_40_PLUS"
1434
;  "div %2, %0")
1435
;
1436
 
1437
;; is rotate doing the right thing to be included here ????

powered by: WebSVN 2.1.0

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