multiply_and_divide.py revision 8973
1# Copyright (c) 2007 The Hewlett-Packard Development Company
2# All rights reserved.
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder.  You may use the software subject to the license
9# terms below provided that you ensure that this notice is replicated
10# unmodified and in its entirety in all distributions of the software,
11# modified or unmodified, in source code or in binary form.
12#
13# Redistribution and use in source and binary forms, with or without
14# modification, are permitted provided that the following conditions are
15# met: redistributions of source code must retain the above copyright
16# notice, this list of conditions and the following disclaimer;
17# redistributions in binary form must reproduce the above copyright
18# notice, this list of conditions and the following disclaimer in the
19# documentation and/or other materials provided with the distribution;
20# neither the name of the copyright holders nor the names of its
21# contributors may be used to endorse or promote products derived from
22# this software without specific prior written permission.
23#
24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35#
36# Authors: Gabe Black
37
38microcode = '''
39
40#
41# Byte version of one operand unsigned multiply.
42#
43
44def macroop MUL_B_R
45{
46    mul1u rax, reg, flags=(OF,CF)
47    mulel rax
48    muleh ah
49};
50
51def macroop MUL_B_M
52{
53    ld t1, seg, sib, disp
54    mul1u rax, t1, flags=(OF,CF)
55    mulel rax
56    muleh ah
57};
58
59def macroop MUL_B_P
60{
61    rdip t7
62    ld t1, seg, riprel, disp
63    mul1u rax, t1, flags=(OF,CF)
64    mulel rax
65    muleh ah
66};
67
68#
69# One operand unsigned multiply.
70#
71
72def macroop MUL_R
73{
74    mul1u rax, reg, flags=(OF,CF)
75    mulel rax
76    muleh rdx
77};
78
79def macroop MUL_M
80{
81    ld t1, seg, sib, disp
82    mul1u rax, t1, flags=(OF,CF)
83    mulel rax
84    muleh rdx
85};
86
87def macroop MUL_P
88{
89    rdip t7
90    ld t1, seg, riprel, disp
91    mul1u rax, t1, flags=(OF,CF)
92    mulel rax
93    muleh rdx
94};
95
96#
97# Byte version of one operand signed multiply.
98#
99
100def macroop IMUL_B_R
101{
102    mul1s rax, reg, flags=(OF,CF)
103    mulel rax
104    muleh ah
105};
106
107def macroop IMUL_B_M
108{
109    ld t1, seg, sib, disp
110    mul1s rax, t1, flags=(OF,CF)
111    mulel rax
112    muleh ah
113};
114
115def macroop IMUL_B_P
116{
117    rdip t7
118    ld t1, seg, riprel, disp
119    mul1s rax, t1, flags=(OF,CF)
120    mulel rax
121    muleh ah
122};
123
124#
125# One operand signed multiply.
126#
127
128def macroop IMUL_R
129{
130    mul1s rax, reg, flags=(OF,CF)
131    mulel rax
132    muleh rdx
133};
134
135def macroop IMUL_M
136{
137    ld t1, seg, sib, disp
138    mul1s rax, t1, flags=(OF,CF)
139    mulel rax
140    muleh rdx
141};
142
143def macroop IMUL_P
144{
145    rdip t7
146    ld t1, seg, riprel, disp
147    mul1s rax, t1, flags=(OF,CF)
148    mulel rax
149    muleh rdx
150};
151
152def macroop IMUL_R_R
153{
154    mul1s reg, regm, flags=(OF,CF)
155    mulel reg
156    muleh t0
157};
158
159def macroop IMUL_R_M
160{
161    ld t1, seg, sib, disp
162    mul1s reg, t1, flags=(CF,OF)
163    mulel reg
164    muleh t0
165};
166
167def macroop IMUL_R_P
168{
169    rdip t7
170    ld t1, seg, riprel, disp
171    mul1s reg, t1, flags=(CF,OF)
172    mulel reg
173    muleh t0
174};
175
176#
177# Three operand signed multiply.
178#
179
180def macroop IMUL_R_R_I
181{
182    limm t1, imm
183    mul1s regm, t1, flags=(OF,CF)
184    mulel reg
185    muleh t0
186};
187
188def macroop IMUL_R_M_I
189{
190    limm t1, imm
191    ld t2, seg, sib, disp
192    mul1s t2, t1, flags=(OF,CF)
193    mulel reg
194    muleh t0
195};
196
197def macroop IMUL_R_P_I
198{
199    rdip t7
200    limm t1, imm
201    ld t2, seg, riprel, disp
202    mul1s t2, t1, flags=(OF,CF)
203    mulel reg
204    muleh t0
205};
206'''
207
208pcRel = '''
209    rdip t7
210    ld %s, seg, riprel, disp
211'''
212sibRel = '''
213    ld %s, seg, sib, disp
214'''
215
216#
217# One byte version of unsigned division
218#
219
220divcode = '''
221def macroop DIV_B_%(suffix)s
222{
223    %(readOp1)s
224    # Do the initial part of the division
225    div1 ah, %(op1)s, dataSize=1
226
227    #These are split out so we can initialize the number of bits in the
228    #second register
229    div2i t1, rax, 8, dataSize=1
230    div2 t1, rax, t1, dataSize=1
231
232    #Loop until we're out of bits to shift in
233divLoopTop:
234    div2 t1, rax, t1, dataSize=1
235    div2 t1, rax, t1, flags=(EZF,), dataSize=1
236    br label("divLoopTop"), flags=(nCEZF,)
237
238    #Unload the answer
239    divq rax, dataSize=1
240    divr ah, dataSize=1
241};
242'''
243
244#
245# Unsigned division
246#
247
248divcode += '''
249def macroop DIV_%(suffix)s
250{
251    %(readOp1)s
252    # Do the initial part of the division
253    div1 rdx, %(op1)s
254
255    #These are split out so we can initialize the number of bits in the
256    #second register
257    div2i t1, rax, "env.dataSize * 8"
258    div2 t1, rax, t1
259
260    #Loop until we're out of bits to shift in
261    #The amount of unrolling here could stand some tuning
262divLoopTop:
263    div2 t1, rax, t1
264    div2 t1, rax, t1
265    div2 t1, rax, t1
266    div2 t1, rax, t1, flags=(EZF,)
267    br label("divLoopTop"), flags=(nCEZF,)
268
269    #Unload the answer
270    divq rax
271    divr rdx
272};
273'''
274
275#
276# One byte version of signed division
277#
278
279divcode += '''
280def macroop IDIV_B_%(suffix)s
281{
282    # Negate dividend
283    sub t1, t0, rax, flags=(ECF,), dataSize=1
284    ruflag t4, 3
285    sub t2, t0, ah, dataSize=1
286    sub t2, t2, t4
287
288    %(readOp1)s
289
290    #Find the sign of the divisor
291    slli t0, %(op1)s, 1, flags=(ECF,), dataSize=1
292
293    # Negate divisor
294    sub t3, t0, %(op1)s, dataSize=1
295    # Put the divisor's absolute value into t3
296    mov t3, t3, %(op1)s, flags=(nCECF,), dataSize=1
297
298    #Find the sign of the dividend
299    slli t0, ah, 1, flags=(ECF,), dataSize=1
300
301    # Put the dividend's absolute value into t1 and t2
302    mov t1, t1, rax, flags=(nCECF,), dataSize=1
303    mov t2, t2, ah, flags=(nCECF,), dataSize=1
304
305    # Do the initial part of the division
306    div1 t2, t3, dataSize=1
307
308    #These are split out so we can initialize the number of bits in the
309    #second register
310    div2i t4, t1, 8, dataSize=1
311    div2 t4, t1, t4, dataSize=1
312
313    #Loop until we're out of bits to shift in
314divLoopTop:
315    div2 t4, t1, t4, dataSize=1
316    div2 t4, t1, t4, flags=(EZF,), dataSize=1
317    br label("divLoopTop"), flags=(nCEZF,)
318
319    #Unload the answer
320    divq t5, dataSize=1
321    divr t6, dataSize=1
322
323    # Fix up signs. The sign of the dividend is still lying around in ECF.
324    # The sign of the remainder, ah, is the same as the dividend. The sign
325    # of the quotient is negated if the signs of the divisor and dividend
326    # were different.
327
328    # Negate the remainder
329    sub t4, t0, t6, dataSize=1
330    # If the dividend was negitive, put the negated remainder in ah.
331    mov ah, ah, t4, (CECF,), dataSize=1
332    # Otherwise put the regular remainder in ah.
333    mov ah, ah, t6, (nCECF,), dataSize=1
334
335    # Negate the quotient.
336    sub t4, t0, t5, dataSize=1
337    # If the dividend was negative, start using the negated quotient
338    mov t5, t5, t4, (CECF,), dataSize=1
339
340    # Check the sign of the divisor
341    slli t0, %(op1)s, 1, flags=(ECF,), dataSize=1
342
343    # Negate the (possibly already negated) quotient
344    sub t4, t0, t5, dataSize=1
345    # If the divisor was negative, put the negated quotient in rax.
346    mov rax, rax, t4, (CECF,), dataSize=1
347    # Otherwise put the one that wasn't negated (at least here) in rax.
348    mov rax, rax, t5, (nCECF,), dataSize=1
349};
350'''
351
352#
353# Signed division
354#
355
356divcode += '''
357def macroop IDIV_%(suffix)s
358{
359    # Negate dividend
360    sub t1, t0, rax, flags=(ECF,)
361    ruflag t4, 3
362    sub t2, t0, rdx
363    sub t2, t2, t4
364
365    %(readOp1)s
366
367    #Find the sign of the divisor
368    slli t0, %(op1)s, 1, flags=(ECF,)
369
370    # Negate divisor
371    sub t3, t0, %(op1)s
372    # Put the divisor's absolute value into t3
373    mov t3, t3, %(op1)s, flags=(nCECF,)
374
375    #Find the sign of the dividend
376    slli t0, rdx, 1, flags=(ECF,)
377
378    # Put the dividend's absolute value into t1 and t2
379    mov t1, t1, rax, flags=(nCECF,)
380    mov t2, t2, rdx, flags=(nCECF,)
381
382    # Do the initial part of the division
383    div1 t2, t3
384
385    #These are split out so we can initialize the number of bits in the
386    #second register
387    div2i t4, t1, "env.dataSize * 8"
388    div2 t4, t1, t4
389
390    #Loop until we're out of bits to shift in
391divLoopTop:
392    div2 t4, t1, t4
393    div2 t4, t1, t4
394    div2 t4, t1, t4
395    div2 t4, t1, t4, flags=(EZF,)
396    br label("divLoopTop"), flags=(nCEZF,)
397
398    #Unload the answer
399    divq t5
400    divr t6
401
402    # Fix up signs. The sign of the dividend is still lying around in ECF.
403    # The sign of the remainder, ah, is the same as the dividend. The sign
404    # of the quotient is negated if the signs of the divisor and dividend
405    # were different.
406
407    # Negate the remainder
408    sub t4, t0, t6
409    # If the dividend was negitive, put the negated remainder in rdx.
410    mov rdx, rdx, t4, (CECF,)
411    # Otherwise put the regular remainder in rdx.
412    mov rdx, rdx, t6, (nCECF,)
413
414    # Negate the quotient.
415    sub t4, t0, t5
416    # If the dividend was negative, start using the negated quotient
417    mov t5, t5, t4, (CECF,)
418
419    # Check the sign of the divisor
420    slli t0, %(op1)s, 1, flags=(ECF,)
421
422    # Negate the (possibly already negated) quotient
423    sub t4, t0, t5
424    # If the divisor was negative, put the negated quotient in rax.
425    mov rax, rax, t4, (CECF,)
426    # Otherwise put the one that wasn't negated (at least here) in rax.
427    mov rax, rax, t5, (nCECF,)
428};
429'''
430
431microcode += divcode % {"suffix": "R",
432                        "readOp1": "", "op1": "reg"}
433microcode += divcode % {"suffix": "M",
434                        "readOp1": sibRel % "t2", "op1": "t2"}
435microcode += divcode % {"suffix": "P",
436                        "readOp1": pcRel % "t2", "op1": "t2"}
437