multiply_and_divide.py revision 6459:f7f0d361d6fc
1# Copyright (c) 2007 The Hewlett-Packard Development Company
2# All rights reserved.
3#
4# Redistribution and use of this software in source and binary forms,
5# with or without modification, are permitted provided that the
6# following conditions are met:
7#
8# The software must be used only for Non-Commercial Use which means any
9# use which is NOT directed to receiving any direct monetary
10# compensation for, or commercial advantage from such use.  Illustrative
11# examples of non-commercial use are academic research, personal study,
12# teaching, education and corporate research & development.
13# Illustrative examples of commercial use are distributing products for
14# commercial advantage and providing services using the software for
15# commercial advantage.
16#
17# If you wish to use this software or functionality therein that may be
18# covered by patents for commercial use, please contact:
19#     Director of Intellectual Property Licensing
20#     Office of Strategy and Technology
21#     Hewlett-Packard Company
22#     1501 Page Mill Road
23#     Palo Alto, California  94304
24#
25# Redistributions of source code must retain the above copyright notice,
26# this list of conditions and the following disclaimer.  Redistributions
27# in binary form must reproduce the above copyright notice, this list of
28# conditions and the following disclaimer in the documentation and/or
29# other materials provided with the distribution.  Neither the name of
30# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
31# contributors may be used to endorse or promote products derived from
32# this software without specific prior written permission.  No right of
33# sublicense is granted herewith.  Derivatives of the software and
34# output created using the software may be prepared, but only for
35# Non-Commercial Uses.  Derivatives of the software may be shared with
36# others provided: (i) the others agree to abide by the list of
37# conditions herein which includes the Non-Commercial Use restrictions;
38# and (ii) such Derivatives of the software include the above copyright
39# notice to acknowledge the contribution from this software where
40# applicable, this list of conditions and the disclaimer below.
41#
42# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53#
54# Authors: Gabe Black
55
56microcode = '''
57
58#
59# Byte version of one operand unsigned multiply.
60#
61
62def macroop MUL_B_R
63{
64    mul1u rax, reg
65    mulel rax
66    muleh ah, flags=(OF,CF)
67};
68
69def macroop MUL_B_M
70{
71    ld t1, seg, sib, disp
72    mul1u rax, t1
73    mulel rax
74    muleh ah, flags=(OF,CF)
75};
76
77def macroop MUL_B_P
78{
79    rdip t7
80    ld t1, seg, riprel, disp
81    mul1u rax, t1
82    mulel rax
83    muleh ah, flags=(OF,CF)
84};
85
86#
87# One operand unsigned multiply.
88#
89
90def macroop MUL_R
91{
92    mul1u rax, reg
93    mulel rax
94    muleh rdx, flags=(OF,CF)
95};
96
97def macroop MUL_M
98{
99    ld t1, seg, sib, disp
100    mul1u rax, t1
101    mulel rax
102    muleh rdx, flags=(OF,CF)
103};
104
105def macroop MUL_P
106{
107    rdip t7
108    ld t1, seg, riprel, disp
109    mul1u rax, t1
110    mulel rax
111    muleh rdx, flags=(OF,CF)
112};
113
114#
115# Byte version of one operand signed multiply.
116#
117
118def macroop IMUL_B_R
119{
120    mul1s rax, reg
121    mulel rax
122    muleh ah, flags=(OF,CF)
123};
124
125def macroop IMUL_B_M
126{
127    ld t1, seg, sib, disp
128    mul1s rax, t1
129    mulel rax
130    muleh ah, flags=(OF,CF)
131};
132
133def macroop IMUL_B_P
134{
135    rdip t7
136    ld t1, seg, riprel, disp
137    mul1s rax, t1
138    mulel rax
139    muleh ah, flags=(OF,CF)
140};
141
142#
143# One operand signed multiply.
144#
145
146def macroop IMUL_R
147{
148    mul1s rax, reg
149    mulel rax
150    muleh rdx, flags=(OF,CF)
151};
152
153def macroop IMUL_M
154{
155    ld t1, seg, sib, disp
156    mul1s rax, t1
157    mulel rax
158    muleh rdx, flags=(OF,CF)
159};
160
161def macroop IMUL_P
162{
163    rdip t7
164    ld t1, seg, riprel, disp
165    mul1s rax, t1
166    mulel rax
167    muleh rdx, flags=(OF,CF)
168};
169
170def macroop IMUL_R_R
171{
172    mul1s reg, regm
173    mulel reg
174    muleh t0, flags=(CF,OF)
175};
176
177def macroop IMUL_R_M
178{
179    ld t1, seg, sib, disp
180    mul1s reg, t1
181    mulel reg
182    muleh t0, flags=(CF,OF)
183};
184
185def macroop IMUL_R_P
186{
187    rdip t7
188    ld t1, seg, riprel, disp
189    mul1s reg, t1
190    mulel reg
191    muleh t0, flags=(CF,OF)
192};
193
194#
195# Three operand signed multiply.
196#
197
198def macroop IMUL_R_R_I
199{
200    limm t1, imm
201    mul1s regm, t1
202    mulel reg
203    muleh t0, flags=(OF,CF)
204};
205
206def macroop IMUL_R_M_I
207{
208    limm t1, imm
209    ld t2, seg, sib, disp
210    mul1s t2, t1
211    mulel reg
212    muleh t0, flags=(OF,CF)
213};
214
215def macroop IMUL_R_P_I
216{
217    rdip t7
218    limm t1, imm
219    ld t2, seg, riprel
220    mul1s t2, t1
221    mulel reg
222    muleh t0, flags=(OF,CF)
223};
224
225#
226# One byte version of unsigned division
227#
228
229def macroop DIV_B_R
230{
231    # Do the initial part of the division
232    div1 ah, reg, dataSize=1
233
234    #These are split out so we can initialize the number of bits in the
235    #second register
236    div2i t1, rax, 8, dataSize=1
237    div2 t1, rax, t1, dataSize=1
238
239    #Loop until we're out of bits to shift in
240divLoopTop:
241    div2 t1, rax, t1, dataSize=1
242    div2 t1, rax, t1, flags=(EZF,), dataSize=1
243    br label("divLoopTop"), flags=(nCEZF,)
244
245    #Unload the answer
246    divq rax, dataSize=1
247    divr ah, dataSize=1
248};
249
250def macroop DIV_B_M
251{
252    ld t2, seg, sib, disp
253
254    # Do the initial part of the division
255    div1 ah, t2, dataSize=1
256
257    #These are split out so we can initialize the number of bits in the
258    #second register
259    div2i t1, rax, 8, dataSize=1
260    div2 t1, rax, t1, dataSize=1
261
262    #Loop until we're out of bits to shift in
263divLoopTop:
264    div2 t1, rax, t1, dataSize=1
265    div2 t1, rax, t1, flags=(EZF,), dataSize=1
266    br label("divLoopTop"), flags=(nCEZF,)
267
268    #Unload the answer
269    divq rax, dataSize=1
270    divr ah, dataSize=1
271};
272
273def macroop DIV_B_P
274{
275    rdip t7
276    ld t2, seg, riprel, disp
277
278    # Do the initial part of the division
279    div1 ah, t2, dataSize=1
280
281    #These are split out so we can initialize the number of bits in the
282    #second register
283    div2i t1, rax, 8, dataSize=1
284    div2 t1, rax, t1, dataSize=1
285
286    #Loop until we're out of bits to shift in
287divLoopTop:
288    div2 t1, rax, t1, dataSize=1
289    div2 t1, rax, t1, flags=(EZF,), dataSize=1
290    br label("divLoopTop"), flags=(nCEZF,)
291
292    #Unload the answer
293    divq rax, dataSize=1
294    divr ah, dataSize=1
295};
296
297#
298# Unsigned division
299#
300
301def macroop DIV_R
302{
303    # Do the initial part of the division
304    div1 rdx, reg
305
306    #These are split out so we can initialize the number of bits in the
307    #second register
308    div2i t1, rax, "env.dataSize * 8"
309    div2 t1, rax, t1
310
311    #Loop until we're out of bits to shift in
312    #The amount of unrolling here could stand some tuning
313divLoopTop:
314    div2 t1, rax, t1
315    div2 t1, rax, t1
316    div2 t1, rax, t1
317    div2 t1, rax, t1, flags=(EZF,)
318    br label("divLoopTop"), flags=(nCEZF,)
319
320    #Unload the answer
321    divq rax
322    divr rdx
323};
324
325def macroop DIV_M
326{
327    ld t2, seg, sib, disp
328
329    # Do the initial part of the division
330    div1 rdx, t2
331
332    #These are split out so we can initialize the number of bits in the
333    #second register
334    div2i t1, rax, "env.dataSize * 8"
335    div2 t1, rax, t1
336
337    #Loop until we're out of bits to shift in
338    #The amount of unrolling here could stand some tuning
339divLoopTop:
340    div2 t1, rax, t1
341    div2 t1, rax, t1
342    div2 t1, rax, t1
343    div2 t1, rax, t1, flags=(EZF,)
344    br label("divLoopTop"), flags=(nCEZF,)
345
346    #Unload the answer
347    divq rax
348    divr rdx
349};
350
351def macroop DIV_P
352{
353    rdip t7
354    ld t2, seg, riprel, disp
355
356    # Do the initial part of the division
357    div1 rdx, t2
358
359    #These are split out so we can initialize the number of bits in the
360    #second register
361    div2i t1, rax, "env.dataSize * 8"
362    div2 t1, rax, t1
363
364    #Loop until we're out of bits to shift in
365    #The amount of unrolling here could stand some tuning
366divLoopTop:
367    div2 t1, rax, t1
368    div2 t1, rax, t1
369    div2 t1, rax, t1
370    div2 t1, rax, t1, flags=(EZF,)
371    br label("divLoopTop"), flags=(nCEZF,)
372
373    #Unload the answer
374    divq rax
375    divr rdx
376};
377
378#
379# One byte version of signed division
380#
381
382def macroop IDIV_B_R
383{
384    # Negate dividend
385    sub t1, t0, rax, flags=(ECF,), dataSize=1
386    ruflag t4, 3
387    sub t2, t0, ah, dataSize=1
388    sub t2, t2, t4
389
390    #Find the sign of the divisor
391    #FIXME!!! This depends on shifts setting the carry flag correctly.
392    slli t0, reg, 1, flags=(ECF,), dataSize=1
393
394    # Negate divisor
395    sub t3, t0, reg, dataSize=1
396    # Put the divisor's absolute value into t3
397    mov t3, t3, reg, flags=(nCECF,), dataSize=1
398
399    #Find the sign of the dividend
400    #FIXME!!! This depends on shifts setting the carry flag correctly.
401    slli t0, ah, 1, flags=(ECF,), dataSize=1
402
403    # Put the dividend's absolute value into t1 and t2
404    mov t1, t1, rax, flags=(nCECF,), dataSize=1
405    mov t2, t2, ah, flags=(nCECF,), dataSize=1
406
407    # Do the initial part of the division
408    div1 t2, t3, dataSize=1
409
410    #These are split out so we can initialize the number of bits in the
411    #second register
412    div2i t4, t1, 8, dataSize=1
413    div2 t4, t1, t4, dataSize=1
414
415    #Loop until we're out of bits to shift in
416divLoopTop:
417    div2 t4, t1, t4, dataSize=1
418    div2 t4, t1, t4, flags=(EZF,), dataSize=1
419    br label("divLoopTop"), flags=(nCEZF,)
420
421    #Unload the answer
422    divq t5, dataSize=1
423    divr t6, dataSize=1
424
425    # Fix up signs. The sign of the dividend is still lying around in ECF.
426    # The sign of the remainder, ah, is the same as the dividend. The sign
427    # of the quotient is negated if the signs of the divisor and dividend
428    # were different.
429
430    # Negate the remainder
431    sub t4, t0, t6, dataSize=1
432    # If the dividend was negitive, put the negated remainder in ah.
433    mov ah, ah, t4, (CECF,), dataSize=1
434    # Otherwise put the regular remainder in ah.
435    mov ah, ah, t6, (nCECF,), dataSize=1
436
437    # Negate the quotient.
438    sub t4, t0, t5, dataSize=1
439    # If the dividend was negative, start using the negated quotient
440    mov t5, t5, t4, (CECF,), dataSize=1
441
442    # Check the sign of the divisor
443    slli t0, t3, 1, flags=(ECF,), dataSize=1
444
445    # Negate the (possibly already negated) quotient
446    sub t4, t0, t5, dataSize=1
447    # If the divisor was negative, put the negated quotient in rax.
448    mov rax, rax, t4, (CECF,), dataSize=1
449    # Otherwise put the one that wasn't negated (at least here) in rax.
450    mov rax, rax, t5, (nCECF,), dataSize=1
451};
452
453def macroop IDIV_B_M
454{
455    # Negate dividend
456    sub t1, t0, rax, flags=(ECF,), dataSize=1
457    ruflag t4, 3
458    sub t2, t0, ah, dataSize=1
459    sub t2, t2, t4
460
461    ld t3, seg, sib, disp
462
463    #Find the sign of the divisor
464    #FIXME!!! This depends on shifts setting the carry flag correctly.
465    slli t0, t3, 1, flags=(ECF,), dataSize=1
466
467    # Negate divisor
468    sub t4, t0, t3, dataSize=1
469    # Put the divisor's absolute value into t3
470    mov t3, t3, t4, flags=(CECF,), dataSize=1
471
472    #Find the sign of the dividend
473    #FIXME!!! This depends on shifts setting the carry flag correctly.
474    slli t0, ah, 1, flags=(ECF,), dataSize=1
475
476    # Put the dividend's absolute value into t1 and t2
477    mov t1, t1, rax, flags=(nCECF,), dataSize=1
478    mov t2, t2, ah, flags=(nCECF,), dataSize=1
479
480    # Do the initial part of the division
481    div1 t2, t3, dataSize=1
482
483    #These are split out so we can initialize the number of bits in the
484    #second register
485    div2i t4, t1, 8, dataSize=1
486    div2 t4, t1, t4, dataSize=1
487
488    #Loop until we're out of bits to shift in
489divLoopTop:
490    div2 t4, t1, t4, dataSize=1
491    div2 t4, t1, t4, flags=(EZF,), dataSize=1
492    br label("divLoopTop"), flags=(nCEZF,)
493
494    #Unload the answer
495    divq t5, dataSize=1
496    divr t6, dataSize=1
497
498    # Fix up signs. The sign of the dividend is still lying around in ECF.
499    # The sign of the remainder, ah, is the same as the dividend. The sign
500    # of the quotient is negated if the signs of the divisor and dividend
501    # were different.
502
503    # Negate the remainder
504    sub t4, t0, t6, dataSize=1
505    # If the dividend was negitive, put the negated remainder in ah.
506    mov ah, ah, t4, (CECF,), dataSize=1
507    # Otherwise put the regular remainder in ah.
508    mov ah, ah, t6, (nCECF,), dataSize=1
509
510    # Negate the quotient.
511    sub t4, t0, t5, dataSize=1
512    # If the dividend was negative, start using the negated quotient
513    mov t5, t5, t4, (CECF,), dataSize=1
514
515    # Check the sign of the divisor
516    slli t0, t3, 1, flags=(ECF,), dataSize=1
517
518    # Negate the (possibly already negated) quotient
519    sub t4, t0, t5, dataSize=1
520    # If the divisor was negative, put the negated quotient in rax.
521    mov rax, rax, t4, (CECF,), dataSize=1
522    # Otherwise put the one that wasn't negated (at least here) in rax.
523    mov rax, rax, t5, (nCECF,), dataSize=1
524};
525
526def macroop IDIV_B_P
527{
528    # Negate dividend
529    sub t1, t0, rax, flags=(ECF,), dataSize=1
530    ruflag t4, 3
531    sub t2, t0, ah, dataSize=1
532    sub t2, t2, t4
533
534    rdip t7
535    ld t3, seg, riprel, disp
536
537    #Find the sign of the divisor
538    #FIXME!!! This depends on shifts setting the carry flag correctly.
539    slli t0, t3, 1, flags=(ECF,), dataSize=1
540
541    # Negate divisor
542    sub t4, t0, t3, dataSize=1
543    # Put the divisor's absolute value into t3
544    mov t3, t3, t4, flags=(CECF,), dataSize=1
545
546    #Find the sign of the dividend
547    #FIXME!!! This depends on shifts setting the carry flag correctly.
548    slli t0, ah, 1, flags=(ECF,), dataSize=1
549
550    # Put the dividend's absolute value into t1 and t2
551    mov t1, t1, rax, flags=(nCECF,), dataSize=1
552    mov t2, t2, ah, flags=(nCECF,), dataSize=1
553
554    # Do the initial part of the division
555    div1 t2, t3, dataSize=1
556
557    #These are split out so we can initialize the number of bits in the
558    #second register
559    div2i t4, t1, 8, dataSize=1
560    div2 t4, t1, t4, dataSize=1
561
562    #Loop until we're out of bits to shift in
563divLoopTop:
564    div2 t4, t1, t4, dataSize=1
565    div2 t4, t1, t4, flags=(EZF,), dataSize=1
566    br label("divLoopTop"), flags=(nCEZF,)
567
568    #Unload the answer
569    divq t5, dataSize=1
570    divr t6, dataSize=1
571
572    # Fix up signs. The sign of the dividend is still lying around in ECF.
573    # The sign of the remainder, ah, is the same as the dividend. The sign
574    # of the quotient is negated if the signs of the divisor and dividend
575    # were different.
576
577    # Negate the remainder
578    sub t4, t0, t6, dataSize=1
579    # If the dividend was negitive, put the negated remainder in ah.
580    mov ah, ah, t4, (CECF,), dataSize=1
581    # Otherwise put the regular remainder in ah.
582    mov ah, ah, t6, (nCECF,), dataSize=1
583
584    # Negate the quotient.
585    sub t4, t0, t5, dataSize=1
586    # If the dividend was negative, start using the negated quotient
587    mov t5, t5, t4, (CECF,), dataSize=1
588
589    # Check the sign of the divisor
590    slli t0, t3, 1, flags=(ECF,), dataSize=1
591
592    # Negate the (possibly already negated) quotient
593    sub t4, t0, t5, dataSize=1
594    # If the divisor was negative, put the negated quotient in rax.
595    mov rax, rax, t4, (CECF,), dataSize=1
596    # Otherwise put the one that wasn't negated (at least here) in rax.
597    mov rax, rax, t5, (nCECF,), dataSize=1
598};
599
600#
601# Signed division
602#
603
604def macroop IDIV_R
605{
606    # Negate dividend
607    sub t1, t0, rax, flags=(ECF,)
608    ruflag t4, 3
609    sub t2, t0, rdx
610    sub t2, t2, t4
611
612    #Find the sign of the divisor
613    #FIXME!!! This depends on shifts setting the carry flag correctly.
614    slli t0, reg, 1, flags=(ECF,)
615
616    # Negate divisor
617    sub t3, t0, reg
618    # Put the divisor's absolute value into t3
619    mov t3, t3, reg, flags=(nCECF,)
620
621    #Find the sign of the dividend
622    #FIXME!!! This depends on shifts setting the carry flag correctly.
623    slli t0, rdx, 1, flags=(ECF,)
624
625    # Put the dividend's absolute value into t1 and t2
626    mov t1, t1, rax, flags=(nCECF,)
627    mov t2, t2, rdx, flags=(nCECF,)
628
629    # Do the initial part of the division
630    div1 t2, t3
631
632    #These are split out so we can initialize the number of bits in the
633    #second register
634    div2i t4, t1, "env.dataSize * 8"
635    div2 t4, t1, t4
636
637    #Loop until we're out of bits to shift in
638divLoopTop:
639    div2 t4, t1, t4
640    div2 t4, t1, t4
641    div2 t4, t1, t4
642    div2 t4, t1, t4, flags=(EZF,)
643    br label("divLoopTop"), flags=(nCEZF,)
644
645    #Unload the answer
646    divq t5
647    divr t6
648
649    # Fix up signs. The sign of the dividend is still lying around in ECF.
650    # The sign of the remainder, ah, is the same as the dividend. The sign
651    # of the quotient is negated if the signs of the divisor and dividend
652    # were different.
653
654    # Negate the remainder
655    sub t4, t0, t6
656    # If the dividend was negitive, put the negated remainder in rdx.
657    mov rdx, rdx, t4, (CECF,)
658    # Otherwise put the regular remainder in rdx.
659    mov rdx, rdx, t6, (nCECF,)
660
661    # Negate the quotient.
662    sub t4, t0, t5
663    # If the dividend was negative, start using the negated quotient
664    mov t5, t5, t4, (CECF,)
665
666    # Check the sign of the divisor
667    slli t0, t3, 1, flags=(ECF,)
668
669    # Negate the (possibly already negated) quotient
670    sub t4, t0, t5
671    # If the divisor was negative, put the negated quotient in rax.
672    mov rax, rax, t4, (CECF,)
673    # Otherwise put the one that wasn't negated (at least here) in rax.
674    mov rax, rax, t5, (nCECF,)
675};
676
677def macroop IDIV_M
678{
679    # Negate dividend
680    sub t1, t0, rax, flags=(ECF,)
681    ruflag t4, 3
682    sub t2, t0, rdx
683    sub t2, t2, t4
684
685    ld t3, seg, sib, disp
686
687    #Find the sign of the divisor
688    #FIXME!!! This depends on shifts setting the carry flag correctly.
689    slli t0, t3, 1, flags=(ECF,)
690
691    # Negate divisor
692    sub t4, t0, t3
693    # Put the divisor's absolute value into t3
694    mov t3, t3, t4, flags=(CECF,)
695
696    #Find the sign of the dividend
697    #FIXME!!! This depends on shifts setting the carry flag correctly.
698    slli t0, rdx, 1, flags=(ECF,)
699
700    # Put the dividend's absolute value into t1 and t2
701    mov t1, t1, rax, flags=(nCECF,)
702    mov t2, t2, rdx, flags=(nCECF,)
703
704    # Do the initial part of the division
705    div1 t2, t3
706
707    #These are split out so we can initialize the number of bits in the
708    #second register
709    div2i t4, t1, "env.dataSize * 8"
710    div2 t4, t1, t4
711
712    #Loop until we're out of bits to shift in
713divLoopTop:
714    div2 t4, t1, t4
715    div2 t4, t1, t4
716    div2 t4, t1, t4
717    div2 t4, t1, t4, flags=(EZF,)
718    br label("divLoopTop"), flags=(nCEZF,)
719
720    #Unload the answer
721    divq t5
722    divr t6
723
724    # Fix up signs. The sign of the dividend is still lying around in ECF.
725    # The sign of the remainder, ah, is the same as the dividend. The sign
726    # of the quotient is negated if the signs of the divisor and dividend
727    # were different.
728
729    # Negate the remainder
730    sub t4, t0, t6
731    # If the dividend was negitive, put the negated remainder in rdx.
732    mov rdx, rdx, t4, (CECF,)
733    # Otherwise put the regular remainder in rdx.
734    mov rdx, rdx, t6, (nCECF,)
735
736    # Negate the quotient.
737    sub t4, t0, t5
738    # If the dividend was negative, start using the negated quotient
739    mov t5, t5, t4, (CECF,)
740
741    # Check the sign of the divisor
742    slli t0, t3, 1, flags=(ECF,)
743
744    # Negate the (possibly already negated) quotient
745    sub t4, t0, t5
746    # If the divisor was negative, put the negated quotient in rax.
747    mov rax, rax, t4, (CECF,)
748    # Otherwise put the one that wasn't negated (at least here) in rax.
749    mov rax, rax, t5, (nCECF,)
750};
751
752def macroop IDIV_P
753{
754    # Negate dividend
755    sub t1, t0, rax, flags=(ECF,)
756    ruflag t4, 3
757    sub t2, t0, rdx
758    sub t2, t2, t4
759
760    rdip t7
761    ld t3, seg, riprel, disp
762
763    #Find the sign of the divisor
764    #FIXME!!! This depends on shifts setting the carry flag correctly.
765    slli t0, t3, 1, flags=(ECF,)
766
767    # Negate divisor
768    sub t4, t0, t3
769    # Put the divisor's absolute value into t3
770    mov t3, t3, t4, flags=(CECF,)
771
772    #Find the sign of the dividend
773    #FIXME!!! This depends on shifts setting the carry flag correctly.
774    slli t0, rdx, 1, flags=(ECF,)
775
776    # Put the dividend's absolute value into t1 and t2
777    mov t1, t1, rax, flags=(nCECF,)
778    mov t2, t2, rdx, flags=(nCECF,)
779
780    # Do the initial part of the division
781    div1 t2, t3
782
783    #These are split out so we can initialize the number of bits in the
784    #second register
785    div2i t4, t1, "env.dataSize * 8"
786    div2 t4, t1, t4
787
788    #Loop until we're out of bits to shift in
789divLoopTop:
790    div2 t4, t1, t4
791    div2 t4, t1, t4
792    div2 t4, t1, t4
793    div2 t4, t1, t4, flags=(EZF,)
794    br label("divLoopTop"), flags=(nCEZF,)
795
796    #Unload the answer
797    divq t5
798    divr t6
799
800    # Fix up signs. The sign of the dividend is still lying around in ECF.
801    # The sign of the remainder, ah, is the same as the dividend. The sign
802    # of the quotient is negated if the signs of the divisor and dividend
803    # were different.
804
805    # Negate the remainder
806    sub t4, t0, t6
807    # If the dividend was negitive, put the negated remainder in rdx.
808    mov rdx, rdx, t4, (CECF,)
809    # Otherwise put the regular remainder in rdx.
810    mov rdx, rdx, t6, (nCECF,)
811
812    # Negate the quotient.
813    sub t4, t0, t5
814    # If the dividend was negative, start using the negated quotient
815    mov t5, t5, t4, (CECF,)
816
817    # Check the sign of the divisor
818    slli t0, t3, 1, flags=(ECF,)
819
820    # Negate the (possibly already negated) quotient
821    sub t4, t0, t5
822    # If the divisor was negative, put the negated quotient in rax.
823    mov rax, rax, t4, (CECF,)
824    # Otherwise put the one that wasn't negated (at least here) in rax.
825    mov rax, rax, t5, (nCECF,)
826};
827'''
828