0
|
1 #!/bin/sh
|
|
2 # Generate mova.md, a file containing patterns that can be implemented
|
|
3 # using the h8sx mova instruction.
|
|
4
|
|
5 echo ";; -*- buffer-read-only: t -*-"
|
|
6 echo ";; Generated automatically from genmova.sh"
|
|
7
|
|
8 # Loop over modes for the source operand (the index). Only 8-bit and
|
|
9 # 16-bit indices are allowed.
|
|
10 for s in QI HI; do
|
|
11
|
|
12 # Set $src to the operand syntax for this size of index.
|
|
13 case $s in
|
|
14 QI) src=%X1.b;;
|
|
15 HI) src=%T1.w;;
|
|
16 esac
|
|
17
|
|
18 # A match_operand for the source.
|
|
19 operand="(match_operand:$s 1 \"h8300_dst_operand\" \"0,rQ\")"
|
|
20
|
|
21 # Loop over the destination register's mode. The QI and HI versions use
|
|
22 # the same instructions as the SI ones, they just ignore the upper bits
|
|
23 # of the result.
|
|
24 for d in QI HI SI; do
|
|
25
|
|
26 # If the destination is larger than the source, include a
|
|
27 # zero_extend/plus pattern. We could also match zero extensions
|
|
28 # of memory without the plus, but it's not any smaller or faster
|
|
29 # than separate insns.
|
|
30 case $d:$s in
|
|
31 SI:QI | SI:HI | HI:QI)
|
|
32 cat <<EOF
|
|
33 (define_insn ""
|
|
34 [(set (match_operand:$d 0 "register_operand" "=r,r")
|
|
35 (plus:$d (zero_extend:$d $operand)
|
|
36 (match_operand:$d 2 "immediate_operand" "i,i")))]
|
|
37 "TARGET_H8300SX"
|
|
38 "mova/b.l @(%o2,$src),%S0"
|
|
39 [(set_attr "length_table" "mova")
|
|
40 (set_attr "cc" "none")])
|
|
41
|
|
42 EOF
|
|
43 ;;
|
|
44 esac
|
|
45
|
|
46 # Loop over the shift amount.
|
|
47 for shift in 1 2; do
|
|
48 case $shift in
|
|
49 1) opsize=w mult=2;;
|
|
50 2) opsize=l mult=4;;
|
|
51 esac
|
|
52
|
|
53 # Calculate the mask of bits that will be nonzero after the source
|
|
54 # has been extended and shifted.
|
|
55 case $s:$shift in
|
|
56 QI:1) mask=510;;
|
|
57 QI:2) mask=1020;;
|
|
58 HI:1) mask=131070;;
|
|
59 HI:2) mask=262140;;
|
|
60 esac
|
|
61
|
|
62 # There doesn't seem to be a well-established canonical form for
|
|
63 # some of the patterns we need. Emit both shift and multiplication
|
|
64 # patterns.
|
|
65 for form in mult ashift; do
|
|
66 case $form in
|
|
67 mult) amount=$mult;;
|
|
68 ashift) amount=$shift;;
|
|
69 esac
|
|
70
|
|
71 case $d:$s in
|
|
72 # If the source and destination are the same size, we can treat
|
|
73 # mova as a sort of multiply-add instruction.
|
|
74 QI:QI | HI:HI)
|
|
75 cat <<EOF
|
|
76 (define_insn ""
|
|
77 [(set (match_operand:$d 0 "register_operand" "=r,r")
|
|
78 (plus:$d ($form:$d $operand
|
|
79 (const_int $amount))
|
|
80 (match_operand:$d 2 "immediate_operand" "i,i")))]
|
|
81 "TARGET_H8300SX"
|
|
82 "mova/$opsize.l @(%o2,$src),%S0"
|
|
83 [(set_attr "length_table" "mova")
|
|
84 (set_attr "cc" "none")])
|
|
85
|
|
86 EOF
|
|
87 ;;
|
|
88
|
|
89 # Handle the cases where the source is smaller than the
|
|
90 # destination. Sometimes combine will keep the extension,
|
|
91 # sometimes it will use an AND.
|
|
92 SI:QI | SI:HI | HI:QI)
|
|
93
|
|
94 # Emit the forms that use zero_extend.
|
|
95 cat <<EOF
|
|
96 (define_insn ""
|
|
97 [(set (match_operand:$d 0 "register_operand" "=r,r")
|
|
98 ($form:$d (zero_extend:$d $operand)
|
|
99 (const_int $amount)))]
|
|
100 "TARGET_H8300SX"
|
|
101 "mova/$opsize.l @(0,$src),%S0"
|
|
102 [(set_attr "length_table" "mova_zero")
|
|
103 (set_attr "cc" "none")])
|
|
104
|
|
105 (define_insn ""
|
|
106 [(set (match_operand:$d 0 "register_operand" "=r,r")
|
|
107 (plus:$d ($form:$d (zero_extend:$d $operand)
|
|
108 (const_int $amount))
|
|
109 (match_operand:$d 2 "immediate_operand" "i,i")))]
|
|
110 "TARGET_H8300SX"
|
|
111 "mova/$opsize.l @(%o2,$src),%S0"
|
|
112 [(set_attr "length_table" "mova")
|
|
113 (set_attr "cc" "none")])
|
|
114
|
|
115 EOF
|
|
116
|
|
117 # Now emit the forms that use AND. When the index is a register,
|
|
118 # these forms are effectively $d-mode operations: the index will
|
|
119 # be a $d-mode REG or SUBREG. When the index is a memory
|
|
120 # location, we will have a paradoxical subreg such as:
|
|
121 #
|
|
122 # (and:SI (mult:SI (subreg:SI (mem:QI ...) 0)
|
|
123 # (const_int 4))
|
|
124 # (const_int 1020))
|
|
125 #
|
|
126 # Match the two case separately: a $d-mode register_operand
|
|
127 # or a $d-mode subreg of an $s-mode memory_operand. Match the
|
|
128 # memory form first since register_operand accepts mem subregs
|
|
129 # before reload.
|
|
130 memory="(match_operand:$s 1 \"memory_operand\" \"m\")"
|
|
131 memory="(subreg:$d $memory 0)"
|
|
132 register="(match_operand:$d 1 \"register_operand\" \"0\")"
|
|
133 for paradoxical in "$memory" "$register"; do
|
|
134 cat <<EOF
|
|
135 (define_insn ""
|
|
136 [(set (match_operand:$d 0 "register_operand" "=r")
|
|
137 (and:$d ($form:$d $paradoxical
|
|
138 (const_int $amount))
|
|
139 (const_int $mask)))]
|
|
140 "TARGET_H8300SX"
|
|
141 "mova/$opsize.l @(0,$src),%S0"
|
|
142 [(set_attr "length_table" "mova_zero")
|
|
143 (set_attr "cc" "none")])
|
|
144
|
|
145 (define_insn ""
|
|
146 [(set (match_operand:$d 0 "register_operand" "=r")
|
|
147 (plus:$d (and:$d ($form:$d $paradoxical
|
|
148 (const_int $amount))
|
|
149 (const_int $mask))
|
|
150 (match_operand:$d 2 "immediate_operand" "i")))]
|
|
151 "TARGET_H8300SX"
|
|
152 "mova/$opsize.l @(%o2,$src),%S0"
|
|
153 [(set_attr "length_table" "mova")
|
|
154 (set_attr "cc" "none")])
|
|
155
|
|
156 EOF
|
|
157 done
|
|
158 ;;
|
|
159 esac
|
|
160 done
|
|
161 done
|
|
162 done
|
|
163 done
|