source: rtems/c/src/lib/libbsp/powerpc/shared/bootloader/em86real.S @ eba2e4f

4.104.114.84.95
Last change on this file since eba2e4f was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on 12/02/99 at 14:31:19

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

  • Property mode set to 100644
File size: 111.5 KB
Line 
1/*
2 *  em86real.S
3 *
4 *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
5 *
6 *  Modified to compile in RTEMS development environment
7 *  by Eric Valette
8 *
9 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10 *
11 *  The license and distribution terms for this file may be
12 *  found in found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 * $Id$
16 */
17
18/* If the symbol __BOOT__ is defined, a slightly different version is
19 * generated to be compiled with the -m relocatable option
20 */
21
22#ifdef __BOOT__
23#include "bootldr.h"
24/* It is impossible to gather statistics in the boot version */
25#undef EIP_STATS
26#endif
27       
28/*
29 *
30 * Given the size of this code, it deserves a few comments on how it works,
31 * and why it was implemented the way it is.
32 *
33 * The goal is to have a real mode i486SX emulator to initialize hardware,
34 * mostly graphics boards, by interpreting ROM BIOSes. The choice of a 486SX
35 * is logical since this is the lowest processor that PCI ROM BIOSes must run
36 * on.
37 *
38 * The goal of this emulator is not performance, but a small enough memory
39 * footprint to include it in a bootloader.
40 *
41 * It is actually likely to be comparable to a 25MHz 386DX on a 200MHz 603e !
42 * This is not as serious as it seems since most of the BIOS code performs
43 * a lot of accesses to I/O and non-cacheable memory spaces. For such
44 * instructions, the execution time is often dominated by bus accesses.
45 * Statistics of the code also shows that it spends a large function of
46 * the time in loops waiting for vertical retrace or programs one of the
47 * timers and waits for the count to go down to zero. This type of loop
48 * runs emulated at the same speed as on 5 GHz Pentium IV++ ;)
49 *
50 */
51
52/*
53 * Known bugs or differences with a real 486SX (real mode):
54 * - segment limits are not enforced (too costly)
55 * - xchg instructions with memory are not locked
56 * - lock prefixes are not implemented at all
57 * - long divides implemented but perhaps still buggy
58 * - miscellaneous system instructions not implemented
59 *   (some probably cannot be implemented)
60 * - neither control nor debug registers are implemented for the time being
61 *   (debug registers are impossible to implement at a reasonable cost)
62 */
63
64/* Code options,  put them on the compiler command line */     
65/* #define EIP_STATS */ /* EIP based profiling */
66/* #undef EIP_STATS */
67
68/*
69 * Implementation notes:
70 *
71 * A) flags emulation. 
72 *
73 * The most important decisions when it comes to obtain a reasonable speed
74 * are related to how the EFLAGS register is emulated.
75 *
76 *   Note: the code to set up flags is complex, but it is only seldom
77 * executed since cmp and test instructions use much faster flag evaluation
78 * paths. For example the overflow flag is almost only needed for pushf and
79 * int. Comparison results only involve (SF^OF) or (SF^OF)+ZF and the
80 * implementation is fast in this case.
81 *
82 * Rarely used flags: AC, NT and IOPL are kept in a memory EFLAGS image.
83 * All other flags are either kept explicitly in PPC cr (DF, IF, and TF) or
84 * lazily evaluated from the state of 4 registers called flags, result, op1,
85 * op2, and sometimes the cr itself. The emulation has been designed for
86 * minimal overhead for the common case where the flags are never used. With
87 * few exceptions, all instructions that set flags leave the result of the
88 * computation in a register called result, and operands are taken from op1
89 * and op2 registers. However a few instructions like cmp, test and bit tests
90 * (bt/btc/btr/bts/bsf/bsr) explicitly set cr bits to short circuit
91 * condition code evaluation of conditional instructions.
92 *
93 * As a very brief summary:
94 *
95 * - the result of the last flag setting operation is often either in the
96 *   result register or in op2 after increment or decrement instructions
97 *   because result and op1 may be needed to compute the carry.
98 *
99 * - compare instruction leave the result of the unsigned comparison
100 *   in cr4 and of signed comparison in cr6. This means that:
101 *   - cr4[0]=CF            (short circuit for jc/jnc)
102 *   - cr4[1]=~(CF+ZF)      (short circuit for ja/jna)
103 *   - cr6[0]=(OF^SF)       (short circuit for jl/jnl)
104 *   - cr6[1]=~((SF^OF)+ZF) (short circuit for jg/jng)
105 *   - cr6[2]=ZF            (short circuit for jz/jnz)
106 *
107 * - test instruction set flags in cr6 and clear overflow. This means that:
108 *   - cr6[0]=SF=(SF^OF)    (short circuit for jl/jnl/js/jns)
109 *   - cr6[1]=~((SF^OF)+ZF) (short circuit for jg/jng)
110 *   - cr6[2]=ZF            (short circuit for jz/jnz)
111 *
112 * All flags may be lazily evaluated from several values kept in registers:
113 *
114 *      Flag:   Depends upon:   
115 *      OF      result, op1, op2, flags[INCDEC_FIELD,SUBTRACTING,OF_STATE_MASK]
116 *      SF      result, op2, flags[INCDEC_FIELD,RES_SIZE]
117 *      ZF      result, op2, cr6[2], flags[INCDEC_FIELD,RES_SIZE,ZF_PROTECT]
118 *      AF      op1, op2, flags[INCDEC_FIELD,SUBTRACTING,CF_IN]
119 *      PF      result, op2, flags[INCDEC_FIELD]
120 *      CF      result, op1, flags[CF_STATE_MASK, CF_IN]
121 *
122 * The order of the fields in the flags register has been chosen so that a
123 * single rlwimi is necessary for common instruction that do not affect all
124 * flags. (See the code for inc/dec emulation).
125 *
126 *
127 * B) opcodes and prefixes.
128 *
129 * The register called opcode holds in its low order 8 bits the opcode
130 * (second byte if the first byte is 0x0f). More precisely it holds the
131 * last byte fetched before the modrm byte or the immediate operand(s)
132 * of the instruction, if any. High order 24 bits are zero unless the
133 * instruction has prefixes. These higher order bits have the following
134 * meaning:
135 * 0x80000000   segment override prefix
136 * 0x00001000   repnz prefix (0xf2)
137 * 0x00000800   repz prefix (0xf3)
138 * 0x00000400   address size prefix (0x67)
139 * 0x00000200   operand size prefix (0x66)
140 * (bit 0x1000 and 0x800 cannot be set simultaneously)
141 *
142 * Therefore if there is a segment override the value will be between very
143 * negative (between 0x80000000 and 0x800016ff), if there is no segment
144 * override, the value will be between 0 and 0x16ff. The reason for
145 * this choice will be understood in the next part.
146 *
147 * C) addresing mode description tables.
148 *
149 * the encoding of the modrm bytes (especially in 16 bit mode) is quite
150 * complex. Hence a table, indexed by the five useful bits of the modrm
151 * byte is used to simplify decoding. Here is a description:
152 *
153 *  bit mask    meaning
154 *  0x80000000  use ss as default segment register
155 *  0x00004000  means that this addressing mode needs a base register
156 *              (set for all entries except sib and displacement-only)
157 *  0x00002000  set if preceding is not set
158 *  0x00001000  set if an sib follows
159 *  0x00000700  base register to use (16 and 32 bit)
160 *  0x00000080  set in 32 bit addressing mode table, cleared in 16 bit
161 *              (so extsb mask,entry; ori mask,mask,0xffff gives a mask)
162 *  0x00000070  kludge field, possible values are
163 *              0: 16 bit addressing mode without index
164 *              10: 32 bit addressing mode
165 *              60: 16 bit addressing mode with %si as index
166 *              70: 16 bit addressing mode with %di as index
167 * 
168 *  This convention leads to the following special values used to check for
169 * sib present and displacement-only, which happen to the three lowest
170 * values in the table (unsigned):
171 * 0x00003090   sib follows (implies it is a 32 bit mode)
172 * 0x00002090   32 bit displacement-only
173 * 0x00002000   16 bit displacement-only
174 *
175 * This means that all entries are either very negative in the 0x80002000
176 * range if the segment defaults to ss or higher than 0x2000 if it defaults
177 * to ds. Combined with the value in opcode this gives the following table:
178 * opcode       entry           entry>opcode ?  segment to use
179 * positive     positive        yes             ds (default)
180 * negative     positive        yes             overriden by prefix
181 * positive     negative        no              ss
182 * negative     negative        yes             overridden by prefix
183 *
184 * Hence a simple comparison allows to check for the need to override
185 * the current base with ss, i.e., when ss is the default base and the
186 * instruction has no override prefix.
187 *
188 * D) BUGS
189 *
190 * This software is obviously bug-free :-). Nevertheless, if you encounter
191 * an interesting feature. Mail me a note, if possible with a detailed
192 * instruction example showing where and how it fails.
193 * 
194 */
195
196
197/* Now the details of flag evaluation with the necessary macros */
198
199/* Alignment check is toggable so the system believes it is a 486, but
200CPUID is not to avoid unnecessary complexities. However, alignment
201is actually never checked (real mode is CPL 0 anyway). */
202#define AC86    13              /* Can only be toggled */
203#define VM86    14              /* Not used for now */
204#define RF86    15              /* Not emulated precisely */
205/* Actually NT and IOPL are kept in memory */
206#define NT86    17
207#define IOPL86  18              /* Actually 18 and 19 */
208#define OF86    20                             
209#define DF86    21
210#define IF86    22
211#define TF86    23
212#define SF86    24
213#define ZF86    25
214#define AF86    27
215#define PF86    29
216#define CF86    31
217
218/* Where the less important flags are placed in PPC cr */
219#define RF      20              /* Suppress trap flag: cr5[0] */
220#define DF      21              /* Direction flag: cr5[1] */
221#define IF      22              /* Interrupt flag: cr5[2] */
222#define TF      23              /* Single step flag: cr5[3] */
223
224/* Now the flags which are frequently used */
225/*
226 * CF_IN is a copy of the input carry with PPC polarity,
227 * it is cleared for add, set for sub and cmp,
228 * equal to the x86 carry for adc and to its complement for sbb.
229 * it is used to evaluate AF and CF.
230 */
231#define CF_IN           0x80000000
232
233/* #define GET_CF_IN(dst)       rlwinm dst,flags,1,0x01 */
234
235/* CF_IN_CR set in flags means that cr4[0] is a copy of carry bit */
236#define CF_IN_CR        0x40000000
237
238#define EVAL_CF         andis. r3,flags,(CF_IN_CR)>>16; beql- _eval_cf
239
240/*
241 * CF_STATE tells how to compute the carry bit. 
242 * NOTRESULT16 and NOTRESULT8 are never set explicitly,
243 * but they may happen after a cmc instruction.
244 */
245#define CF              16              /* cr4[0] */
246#define CF_LOCATION     0x30000000
247#define CF_ZERO         0x00000000
248#define CF_EXPLICIT     0x00000000
249#define CF_COMPLEMENT   0x08000000      /* Indeed a polarity bit */
250#define CF_STATE_MASK   (CF_LOCATION|CF_COMPLEMENT)
251#define CF_VALUE        0x08000000
252#define CF_SET          0x08000000
253#define CF_RES32        0x10000000
254#define CF_NOTRES32     0x18000000
255#define CF_RES16        0x20000000
256#define CF_NOTRES16     0x28000000
257#define CF_RES8         0x30000000
258#define CF_NOTRES8      0x38000000
259       
260#define CF_ADDL         CF_RES32
261#define CF_SUBL         CF_NOTRES32
262#define CF_ADDW         CF_RES16
263#define CF_SUBW         CF_RES16
264#define CF_ADDB         CF_RES8
265#define CF_SUBB         CF_RES8
266
267#define CF_ROTCNT(dst)  rlwinm dst,flags,7,0x18
268#define CF_POL(dst,pos) rlwinm dst,flags,(36-pos)%32,pos,pos
269#define CF_POL_INSERT(dst,pos)  \
270                        rlwimi dst,flags,(36-pos)%32,pos,pos
271#define RES2CF(dst)     rlwinm dst,result,8,7,15
272       
273/*
274 * OF_STATE tells how to compute the overflow bit. When the low order bit
275 * is set (OF_EXPLICIT), it means that OF is the exclusive or of the
276 * two other bits. For the reason of this choice, see rotate instructions.
277 */
278#define OF              1               /* Only after EVAL_OF */
279#define OF_STATE_MASK   0x07000000
280#define OF_INCDEC       0x00000000
281#define OF_EXPLICIT     0x01000000
282#define OF_ZERO         0x01000000
283#define OF_VALUE        0x04000000
284#define OF_SET          0x04000000
285#define OF_ONE          0x05000000
286#define OF_XOR          0x06000000
287#define OF_ARITHL       0x06000000
288#define OF_ARITHW       0x02000000
289#define OF_ARITHB       0x04000000
290
291#define EVAL_OF         rlwinm. r3,flags,6,0,1; bngl+ _eval_of; andis. r3,flags,OF_VALUE>>16
292       
293/* See _eval_of to see how this can be used */
294#define OF_ROTCNT(dst)  rlwinm dst,flags,10,0x1c
295       
296/*
297 * SIGNED_IN_CR means that cr6 is set as after a signed compare:
298 * - cr6[0] is SF^OF for jl/jnl/setl/setnl...
299 * - cr6[1] is ~((SF^OF)+ZF) for jg/jng/setg/setng...
300 * - cr6[2] is ZF (ZF_IN_CR is always set if this bit is set)
301 */
302#define SLT             24              /* cr6[0], signed less than */
303#define SGT             25              /* cr6[1], signed greater than */
304#define SIGNED_IN_CR    0x00800000
305
306#define EVAL_SIGNED     andis. r3,flags,SIGNED_IN_CR>>16; beql- _eval_signed
307
308/*
309 * Above in CR means that cr4 is set as after an unsigned compare:
310 * - cr4[0] is CF (CF_IN_CR is also set)
311 * - cr4[1] is ~(CF+ZF) (ZF_IN_CR is also set)
312 */
313#define ABOVE           17              /* cr4[1] */
314#define ABOVE_IN_CR     0x00400000
315
316#define EVAL_ABOVE      andis. r3,flags,ABOVE_IN_CR>>16; beql- _eval_above
317
318/* SF_IN_CR means cr6[0] is a copy of SF. It implies ZF_IN_CR is also set */
319#define SF              24              /* cr6[0] */
320#define SF_IN_CR        0x00200000
321
322#define EVAL_SF         andis. r3,flags,SF_IN_CR>>16; beql- _eval_sf_zf
323       
324/* ZF_IN_CR means cr6[2] is a copy of ZF. */
325#define ZF      26             
326#define ZF_IN_CR        0x00100000
327       
328#define EVAL_ZF         andis. r3,flags,ZF_IN_CR>>16; beql- _eval_sf_zf
329#define ZF2ZF86(s,d)    rlwimi d,s,ZF-ZF86,ZF86,ZF86
330#define ZF862ZF(reg)    rlwimi reg,reg,32+ZF86-ZF,ZF,ZF
331       
332/*
333 * ZF_PROTECT means cr6[2] is the only valid value for ZF. This is necessary
334 * because some infrequent instructions may leave SF and ZF in an apparently
335 * inconsistent state (both set): sahf, popf and the few (not implemented)
336 * instructions that only affect ZF.
337 */
338#define ZF_PROTECT      0x00080000
339       
340/* The parity is always evaluated when it is needed */
341#define PF              0               /* Only after EVAL_PF */
342#define EVAL_PF         bl _eval_pf
343
344/* This field gives the shift amount to use to evaluate SF
345   and ZF when ZF_PROTECT is not set */
346#define RES_SIZE_MASK   0x00060000
347#define RESL            0x00000000
348#define RESW            0x00040000
349#define RESB            0x00060000
350
351#define RES_SHIFT(dst)  rlwinm dst,flags,18,0x18
352
353/* SUBTRACTING is set if the last flag setting instruction was sub/sbb/cmp,
354   used to evaluate OF and AF */
355#define SUBTRACTING     0x00010000
356
357#define GET_ADDSUB(dst) rlwinm dst,flags,16,0x01
358       
359/* rotate (rcl/rcr/rol/ror) affect CF and OF but not other flags */
360#define ROTATE_MASK     (CF_IN_CR|CF_STATE_MASK|ABOVE_IN_CR|OF_STATE_MASK|SIGNED_IN_CR)
361#define ROTATE_FLAGS    rlwimi flags,one,24,ROTATE_MASK
362
363/*
364 * INCDEC_FIELD has at most one bit set when the last flag setting instruction
365 * was either inc or dec (which do not affect the carry). When one of these
366 * bits is set, it affects the way OF, SF, ZF, AF, and PF are evaluated.
367 */
368#define INCDEC_FIELD    0x0000ff00
369
370#define DECB_SHIFT      8
371#define INCB_SHIFT      9
372#define DECW_SHIFT      10
373#define INCW_SHIFT      11
374#define DECL_SHIFT      14
375#define INCL_SHIFT      15
376
377#define INCDEC_MASK     (OF_STATE_MASK|SIGNED_IN_CR|ABOVE_IN_CR|SF_IN_CR|\
378                        ZF_IN_CR|ZF_PROTECT|RES_SIZE_MASK|SUBTRACTING|\
379                        INCDEC_FIELD)
380/* Operations to perform to tell where the flags are after inc or dec */
381#define INC_FLAGS(BWL)  rlwimi flags,one,INC##BWL##_SHIFT,INCDEC_MASK
382#define DEC_FLAGS(BWL)  rlwimi flags,one,DEC##BWL##_SHIFT,INCDEC_MASK
383       
384/* How the flags are set after arithmetic operations */
385#define FLAGS_ADD(BWL)  (CF_ADD##BWL|OF_ARITH##BWL|RES##BWL)
386#define FLAGS_SBB(BWL)  (CF_SUB##BWL|OF_ARITH##BWL|RES##BWL|SUBTRACTING)
387#define FLAGS_SUB(BWL)  FLAGS_SBB(BWL)|CF_IN
388#define FLAGS_CMP(BWL)  FLAGS_SUB(BWL)|ZF_IN_CR|CF_IN_CR|SIGNED_IN_CR|ABOVE_IN_CR
389
390/* How the flags are set after logical operations */
391#define FLAGS_LOG(BWL)  (CF_ZERO|OF_ZERO|RES##BWL)
392#define FLAGS_TEST(BWL) FLAGS_LOG(BWL)|ZF_IN_CR|SIGNED_IN_CR|SF_IN_CR
393
394/*  How the flags are set after bt/btc/btr/bts. */
395#define FLAGS_BTEST     CF_IN_CR|CF_ADDL|OF_ZERO|RESL
396
397/*  How the flags are set after bsf/bsr. */
398#define FLAGS_BSRCH(WL) CF_ZERO|OF_ZERO|RES##WL|ZF_IN_CR
399
400/* How the flags are set after logical right shifts */
401#define FLAGS_SHR(BWL)  (CF_EXPLICIT|OF_ARITH##BWL|RES##BWL)
402
403/* How the flags are set after double length shifts */
404#define FLAGS_DBLSH(WL) (CF_EXPLICIT|OF_ARITH##WL|RES##WL)
405
406/* How the flags are set after multiplies */
407#define FLAGS_MUL       (CF_EXPLICIT|OF_EXPLICIT)
408       
409#define SET_FLAGS(fl)   lis flags,(fl)>>16
410#define ADD_FLAGS(fl)   addis flags,flags,(fl)>>16
411
412/*
413 * We are always off by one when compared with Intel's eip, this shortens
414 * code by allowing to load next byte with lbzu x,1(eip). The register
415 * called eip actually contains csbase+eip, and thus should be called lip
416 * for linear ip.
417 */
418               
419/*
420 * Reason codes passed to the C part of the emulator, this includes all
421 * instructions which may change the current code segment. These definitions
422 * will soon go into a separate include file. Codes 0 to 255 correspond
423 * directly to the interrupt/trap that has to be generated.
424 */
425
426#define code_divide_err 0
427#define code_trap       1
428#define code_int3       3
429#define code_into       4
430#define code_bound      5
431#define code_ud         6
432#define code_dna        7       /* FPU not available */
433       
434#define code_iretw      256     /* Interrupt returns */
435#define code_iretl      257
436#define code_lcallw     258     /* Far calls and jumps */
437#define code_lcalll     259
438#define code_ljmpw      260
439#define code_ljmpl      261
440#define code_lretw      262     /* Far returns */
441#define code_lretl      263
442#define code_softint    264     /* int $xx */
443#define code_lock       265     /* Lock prefix */
444/* Codes 1024 to 2047 are used for I/O port access instructions:
445 - The three LSB define the port size (1, 2 or 4)
446 - bit of weight 512 means out if set, in if clear
447 - bit of weight 256 means ins/outs if set, in/out if clear
448 - bit of weight 128 means use 32 bit addresses if set, 16 bit if clear
449   (only used for ins/outs instructions, always clear for in/out)       
450 */
451#define code_inb        1024+1
452#define code_inw        1024+2
453#define code_inl        1024+4
454#define code_outb       1024+512+1
455#define code_outw       1024+512+2
456#define code_outl       1024+512+4
457#define code_insb_a16   1024+256+1
458#define code_insw_a16   1024+256+2
459#define code_insl_a16   1024+256+4
460#define code_outsb_a16  1024+512+256+1
461#define code_outsw_a16  1024+512+256+2
462#define code_outsl_a16  1024+512+256+4
463#define code_insb_a32   1024+256+128+1
464#define code_insw_a32   1024+256+128+2
465#define code_insl_a32   1024+256+128+4
466#define code_outsb_a32  1024+512+256+128+1
467#define code_outsw_a32  1024+512+256+128+2
468#define code_outsl_a32  1024+512+256+128+4
469
470#define state 31
471/* r31 (state) is a pointer to a structure describing the emulated x86
472processor, its layout is the following:
473
474first the general purpose registers, they are in little endian byte order
475
476offset  name
477       
478   0    eax/ax/al
479   1    ah
480   4    ecx/cx/cl
481   5    ch
482   8    edx/dx/dl
483   9    dh
484  12    ebx/bx/bl
485  13    bh
486  16    esp/sp
487  20    ebp/bp
488  24    esi/si
489  28    edi/di
490*/
491
492#define AL      0
493#define AX      0
494#define EAX     0
495#define AH      1
496#define CL      4
497#define CX      4
498#define ECX     4
499#define DX      8
500#define EDX     8
501#define BX      12
502#define EBX     12
503#define SP      16
504#define ESP     16
505#define BP      20
506#define EBP     20
507#define SI      24
508#define ESI     24
509#define DI      28
510#define EDI     28
511
512/*
513than the rest of the machine state, big endian !
514
515offset     name     
516
517  32       essel     segment register selectors (values)
518  36       cssel
519  40       sssel
520  44       dssel
521  48       fssel
522  52       gssel
523  56       eipimg    true eip (register named eip is csbase+eip)
524  60       eflags    eip and eflags only valid when C code running !
525  64       esbase    segment registers bases
526  68       csbase
527  72       ssbase
528  76       dsbase
529  80       fsbase
530  84       gsbase
531  88       iobase    For I/O instructions, I/O space virtual base
532  92       ioperm    I/O permission bitmap pointer
533  96       reason    Reason code when calling external emulator
534 100       nexteip   eip past instruction for external emulator
535 104       parm1     parameter for external emulator
536 108       parm2     parameter for external emulator
537 112       _opcode   current opcode register for external emulator
538 116       _base     segment register base for external emulator
539 120       _offset   intruction operand offset
540 More internal state was dumped here for debugging in first versions
541
542 128       vbase     where the 1Mb memory is mapped
543 132       cntimg    instruction counter
544 136                 scratch         
545 192       eipstat   array of 32k unsigned long pairs for eip stats
546*/
547
548#define essel   32
549#define cssel   36
550#define sssel   40
551#define dssel   44
552#define fssel   48
553#define gssel   52
554#define eipimg  56
555#define eflags  60
556#define esbase  64
557#define csbase  68
558#define ssbase  72
559#define dsbase  76
560#define fsbase  80
561#define gsbase  84
562#define iobase  88
563#define ioperm  92
564#define reason  96
565#define nexteip 100
566#define parm1   104
567#define parm2   108
568#define _opcode 112
569#define _base   116
570#define _offset 120
571#define vbase   128
572#define cntimg  132
573#ifdef EIP_STATS
574#define eipstat 192
575#endif
576/* Global registers */
577
578/* Some segment register bases are permanently kept in registers since they
579are often used: these are csb, esb and ssb because they are
580required for jumps, string instructions, and pushes/pops/calls/rets.
581dsbase is not kept in a register but loaded from memory to allow somewhat
582more parallelism in the main emulation loop.
583*/
584
585#define one     30              /* Constant one, so pervasive */
586#define ssb     29
587#define csb     28
588#define esb     27
589#define eip     26              /* That one is indeed csbase+(e)ip-1 */
590#define result  25              /* For the use of result, op1, op2 */
591#define op1     24              /* see the section on flag emulation */
592#define op2     23
593#define opbase  22              /* default opcode table */
594#define flags   21              /* See earlier description */
595#define opcode  20              /* Opcode */
596#define opreg   19              /* Opcode extension/register number */
597/* base is reloaded with the base of the ds segment at the beginning of
598every instruction, it is modified by segment override prefixes, when
599the default base segment is ss, or when the modrm byte specifies a
600register operand */
601#define base    18              /* Instruction's operand segment base */
602#define offset  17              /* Instruction's memory operand offset */
603/* used to address a table telling how to decode the addressing mode
604specified by the modrm byte */
605#define adbase  16              /* addressing mode table */
606/* Following registers are used only as dedicated temporaries during decoding,
607they are free for use during emulation */
608/*
609 * ceip (current eip) is only in use when we call the external emulator for
610 * instructions that fault. Note that it is forbidden to change flags before
611 * the check for the fault happens (divide by zero...) ! ceip is also used
612 * when measuring timing.
613 */
614#define ceip 15
615
616/* A register used to measure timing information (when enabled) */
617#ifdef EIP_STATS
618#define tstamp 14
619#endif
620
621#define count 12                /* Instruction counter. */
622
623#define r0 0
624#define r1 1                    /* PPC Stack pointer. */
625#define r3 3
626#define r4 4
627#define r5 5
628#define r6 6
629#define r7 7
630
631/* Macros to read code stream */
632#define NEXTBYTE(dest) lbzu dest,1(eip)
633#define NEXTWORD(dest) lhbrx dest,eip,one; la eip,2(eip)
634#define NEXTDWORD(dest) lwbrx dest,eip,one; la eip,4(eip)
635#define NEXT    b nop
636#define GOTNEXT b gotopcode
637
638#ifdef __BOOT__
639                START_GOT
640                GOT_ENTRY(_jtables)
641                GOT_ENTRY(jtab_www)
642                GOT_ENTRY(adtable)
643                END_GOT
644#else   
645                .text
646#endif
647                .align 2
648                .global em86_enter
649                .type em86_enter,@function
650em86_enter:     stwu r1,-96(r1)                 # allocate stack
651                mflr r0
652                stmw 14,24(r1)
653                mfcr r4
654                stw r0,100(r1)
655                mr state,r3
656                stw r4,20(r1)
657#ifdef __BOOT__
658/* We need this since r30 is the default GOT pointer */
659#define r30 30
660                GET_GOT
661/* The relocation of these tables is explicit, this could be done
662 * automatically with fixups but would add more than 8kb in the fixup tables.
663 */
664                lwz r3,GOT(_jtables)
665                lwz r4,_endjtables-_jtables(r3)
666                sub. r4,r3,r4
667                beq+ 1f
668                li r0,((_endjtables-_jtables)>>2)+1
669                addi r3,r3,-4
670                mtctr r0
6710:              lwzu r5,4(r3)
672                add r5,r5,r4
673                stw r5,0(r3)
674                bdnz 0b
6751:              lwz adbase,GOT(adtable)
676                lwz opbase,GOT(jtab_www)
677/* Now r30 is only used as constant 1 */
678#undef r30
679                li one,1                        # pervasive constant
680#else
681                lis opbase,jtab_www@ha
682                lis adbase,adtable@ha
683                li one,1                        # pervasive constant
684                addi opbase,opbase,jtab_www@l
685                addi adbase,adbase,adtable@l
686#ifdef EIP_STATS
687                li ceip,0
688                mftb tstamp
689#endif
690#endif
691/* We branch back here when calling an external function tells us to resume */
692restart:        lwz r3,eflags(state)
693                lis flags,(OF_EXPLICIT|ZF_IN_CR|ZF_PROTECT|SF_IN_CR)>>16
694                lwz csb,csbase(state)
695                extsb result,r3                 # SF/PF
696                rlwinm op1,r3,31,0x08           # AF
697                lwz eip,eipimg(state)
698                ZF862ZF(r3)                     # cr6
699                addi op2,op1,0                  # AF
700                lwz ssb,ssbase(state)
701                rlwimi flags,r3,15,OF_VALUE     # OF
702                rlwimi r3,r3,32+RF86-RF,RF,RF   # RF
703                lwz esb,esbase(state)
704                ori result,result,0xfb          # PF
705                mtcrf 0x06,r3                   # RF/DF/IF/TF/SF/ZF
706                lbzux opcode,eip,csb
707                rlwimi flags,r3,27,CF_VALUE     # CF
708                xori result,result,0xff         # PF
709                lwz count,cntimg(state)
710                GOTNEXT                         # start the emulator
711
712/* Now return */
713exit:           lwz r0,100(r1)
714                lwz r4,20(r1)
715                mtlr r0
716                lmw 14,24(r1)
717                mtcr r4
718                addi r1,r1,96
719                blr
720       
721trap:           crmove 0,RF
722                crclr RF
723                bt- 0,resume
724                sub ceip,eip,csb
725                li r3,code_trap
726complex:        addi eip,eip,1
727                stw r3,reason(state)
728                sub eip,eip,csb
729                stw op1,240(state)
730                stw op2,244(state)
731                stw result,248(state)
732                stw flags,252(state)
733                stw r4,parm1(state)
734                stw r5,parm2(state)
735                stw opcode,_opcode(state)
736                bl _eval_flags
737                stw base,_base(state)
738                stw eip,nexteip(state)
739                stw r3,eflags(state)
740                mr r3,state
741                stw offset,_offset(state)
742                stw ceip,eipimg(state)
743                stw count,cntimg(state)
744                bl em86_trap
745                cmpwi r3,0
746                bne exit
747                b restart
748       
749/* Main loop */
750/*
751 * The two LSB of each entry in the main table mean the following:
752 * 00: indirect opcode: modrm follows and the three middle bits are an
753 *     opcode extension. The entry points to another jump table.
754 * 01: direct instruction, branch directly to the routine.
755 * 10: modrm specifies byte size memory and register operands.
756 * 11: modrm specifies word/long memory and register operands.
757 *     
758 *  The modrm byte, if present, is always loaded in r7.
759 *
760 * Note: most "mr x,y" instructions have been replaced by "addi x,y,0" since
761 * the latter can be executed in the second integer unit on 603e.
762 */
763
764/*
765 * This code is very good example of absolutely unmaintainable code.
766 * It was actually much easier to write than it is to understand !
767 * If my computations are right, the maximum path length from fetching
768 * the opcode to exiting to the actual instruction execution is
769 * 46 instructions (for non-prefixed, single byte opcode instructions).
770 *
771 */
772                .align 5       
773#ifdef EIP_STATS
774nop:            NEXTBYTE(opcode)
775gotopcode:      slwi r3,opcode,2
776                bt- TF,trap
777resume:         lwzx r4,opbase,r3
778                addi r5,state,eipstat+4
779                clrlslwi r6,ceip,17,3
780                mtctr r4
781                lwzux r7,r5,r6
782                slwi. r0,r4,30          # two lsb of table entry
783                sub r7,r7,tstamp
784                lwz r6,-4(r5)
785                mftb tstamp
786                addi r6,r6,1
787                sub ceip,eip,csb
788                stw r6,-4(r5)
789                add r7,r7,tstamp
790                lwz base,dsbase(state)
791                stw r7,0(r5)
792#else
793nop:            NEXTBYTE(opcode)
794gotopcode:      slwi r3,opcode,2
795                bt- TF,trap
796resume:         lwzx r4,opbase,r3
797                sub ceip,eip,csb
798                mtctr r4
799                slwi. r0,r4,30          # two lsb of table entry
800                lwz base,dsbase(state)
801                addi count,count,1
802#endif
803                bgtctr-                 # for instructions without modrm
804
805/* modrm byte present */
806                NEXTBYTE(r7)            # modrm byte
807                cmplwi cr1,r7,192
808                rlwinm opreg,r7,31,0x1c
809                beq- cr0,8f             # extended opcode
810/* modrm with middle 3 bits specifying a register (non prefixed) */
811                rlwinm r0,r4,3,0x8
812                li r4,0x1c0d
813                rlwimi opreg,r7,27,0x01
814                srw r4,r4,r0
815                and opreg,opreg,r4
816                blt cr1,9f
817/* modrm with 2 register operands */
8181:              rlwinm offset,r7,2,0x1c
819                addi base,state,0
820                rlwimi offset,r7,30,0x01
821                and offset,offset,r4
822                bctr
823
824/* Prefixes: first segment overrides */
825                .align 4
826_es:            NEXTBYTE(r7); addi base,esb,0
827                oris opcode,opcode,0x8000; b 2f
828_cs:            NEXTBYTE(r7); addi base,csb,0
829                oris opcode,opcode,0x8000; b 2f
830_fs:            NEXTBYTE(r7); lwz base,fsbase(state)
831                oris opcode,opcode,0x8000; b 2f
832_gs:            NEXTBYTE(r7); lwz base,gsbase(state)
833                oris opcode,opcode,0x8000; b 2f
834_ss:            NEXTBYTE(r7); addi base,ssb,0
835                oris opcode,opcode,0x8000; b 2f
836_ds:            NEXTBYTE(r7)
837                oris opcode,opcode,0x8000; b 2f
838
839/* Lock (unimplemented) and repeat prefixes */
840_lock:          li r3,code_lock; b complex
841_repnz:         NEXTBYTE(r7); rlwimi opcode,one,12,0x1800; b 2f
842_repz:          NEXTBYTE(r7); rlwimi opcode,one,11,0x1800; b 2f
843                       
844/* Operand and address size prefixes */
845                .align 4
846_opsize:        NEXTBYTE(r7); ori opcode,opcode,0x200
847                rlwinm r3,opcode,2,0x1ffc; b 2f
848_adsize:        NEXTBYTE(r7); ori opcode,opcode,0x400
849                rlwinm r3,opcode,2,0x1ffc; b 2f
850
851_twobytes:      NEXTBYTE(r7); addi r3,r3,0x400
8522:              rlwimi r3,r7,2,0x3fc
853                lwzx r4,opbase,r3
854                rlwimi opcode,r7,0,0xff
855                mtctr r4
856                slwi. r0,r4,30
857                bgtctr-                         # direct instruction
858/* modrm byte in a prefixed instruction */
859                NEXTBYTE(r7)                    # modrm byte
860                cmpwi cr1,r7,192
861                rlwinm opreg,r7,31,0x1c
862                beq- 6f
863/* modrm with middle 3 bits specifying a register (prefixed) */
864                rlwinm r0,r4,3,0x8
865                li r4,0x1c0d
866                rlwimi opreg,r7,27,0x01
867                srw r4,r4,r0
868                and opreg,opreg,r4
869                bnl cr1,1b                      # 2 register operands
870/* modrm specifying memory with prefix */
8713:              rlwinm r3,r3,27,0xff80
872                rlwimi adbase,r7,2,0x1c
873                extsh r3,r3
874                rlwimi r3,r7,31,0x60
875                lwzx r4,r3,adbase
876                cmpwi cr1,r4,0x3090
877                bnl+ cr1,10f   
878/* displacement only addressing modes */
8794:              cmpwi r4,0x2000
880                bne 5f
881                NEXTWORD(offset)
882                bctr
8835:              NEXTDWORD(offset)
884                bctr
885/* modrm with opcode extension (prefixed) */
8866:              lwzx r4,r4,opreg
887                mtctr r4
888                blt cr1,3b
889/* modrm with opcode extension and register operand */
8907:              rlwinm offset,r7,2,0x1c
891                addi base,state,0
892                rlwinm r0,r4,3,0x8
893                li r4,0x1c0d
894                rlwimi offset,r7,30,0x01
895                srw r4,r4,r0
896                and offset,offset,r4
897                bctr
898/* modrm with opcode extension (non prefixed) */
8998:              lwzx r4,r4,opreg
900                mtctr r4
901/* FIXME ? We continue fetching even if the opcode extension is undefined.
902 * It shouldn't do any harm on real mode emulation anyway, and for ROM
903 * BIOS emulation, we are supposed to read valid code.
904 */
905                bnl cr1,7b
906/* modrm specifying memory without prefix */
9079:              rlwimi adbase,r7,2,0x1c # memory addressing mode computation
908                rlwinm r3,r7,31,0x60
909                lwzx r4,r3,adbase
910                cmplwi cr1,r4,0x3090
911                blt- cr1,4b             # displacement only addressing mode
91210:             rlwinm. r0,r7,24,0,1    # three cases distinguished
913                beq- cr1,15f            # an sib follows
914                rlwinm r3,r4,30,0x1c    # 16bit/32bit/%si index/%di index
915                cmpwi cr1,r3,8          # set cr1 as early as possible
916                rlwinm r6,r4,26,0x1c    # base register
917                lwbrx offset,state,r6   # load the base register
918                beq cr0,14f             # no displacement
919                cmpw cr2,r4,opcode      # check for ss as default base
920                bgt cr0,12f             # byte offset
921                beq cr1,11f             # 32 bit displacement
922                NEXTWORD(r5)            # 16 bit displacement
923                bgt cr1,13f             # d16(base,index)
924/* d16(base) */
925                add offset,offset,r5
926                clrlwi offset,offset,16
927                bgtctr cr2
928                addi base,ssb,0
929                bctr
930/* d32(base) */
93111:             NEXTDWORD(r5)
932                add offset,offset,r5
933                bgtctr cr2
934                addi base,ssb,0
935                bctr
936/* 8 bit displacement */       
93712:             NEXTBYTE(r5)
938                extsb r5,r5
939                bgt cr1,13f
940/* d8(base) */
941                extsb r6,r4
942                add offset,offset,r5
943                ori r6,r6,0xffff
944                and offset,offset,r6
945                bgtctr cr2
946                addi base,ssb,0
947                bctr
948/* d8(base,index) and d16(base,index) share this code ! */
94913:             lhbrx r3,state,r3
950                add offset,offset,r5
951                add offset,offset,r3
952                clrlwi offset,offset,16
953                bgtctr cr2
954                addi base,ssb,0
955                bctr
956/* no displacement: only indexed modes may use ss as default base */
95714:             beqctr cr1              # 32 bit register indirect
958                clrlwi offset,offset,16
959                bltctr cr1              # 16 bit register indirect
960/* (base,index) */
961                lhbrx r3,state,r3       # 16 bit [{bp,bx}+{si,di}]
962                cmpw cr2,r4,opcode      # check for ss as default base
963                add offset,offset,r3
964                clrlwi offset,offset,r3
965                bgtctr+ cr2
966                addi base,ssb,0
967                bctr
968/* sib modes, note that the size of the offset can be known from cr0 */
96915:             NEXTBYTE(r7)                    # get sib
970                rlwinm r3,r7,31,0x1c            # index
971                rlwinm offset,r7,2,0x1c         # base
972                cmpwi cr1,r3,ESP                # has index ?
973                bne cr0,18f                     # base+d8/d32   
974                cmpwi offset,EBP
975                beq 17f                         # d32(,index,scale)
976                xori r4,one,0xcc01              # build 0x0000cc00
977                rlwnm r4,r4,offset,0,1          # 0 or 0xc0000000
978                lwbrx offset,state,offset
979                cmpw cr2,r4,opcode              # use ss ?
980                beq- cr1,16f                    # no index
981/* (base,index,scale) */
982                lwbrx r3,state,r3
983                srwi r6,r7,6
984                slw r3,r3,r6
985                add offset,offset,r3
986                bgtctr cr2
987                addi base,ssb,0
988                bctr
989/* (base), in practice only (%esp) is coded this way */
99016:             bgtctr cr2
991                addi base,ssb,0
992                bctr
993/* d32(,index,scale) */
99417:             NEXTDWORD(offset)
995                beqctr- cr1                     # no index: very unlikely
996                lwbrx r3,state,r3
997                srwi r6,r7,6
998                slw r3,r3,r6
999                add offset,offset,r3
1000                bctr
1001/* 8 or 32 bit displacement */
100218:             xori r4,one,0xcc01              # build 0x0000cc00
1003                rlwnm r4,r4,offset,0,1          # 0 or 0xc0000000
1004                lwbrx offset,state,offset
1005                cmpw cr2,r4,opcode              # use ss ?
1006                bgt cr0,20f                     # 8 bit offset
1007/* 32 bit displacement */
1008                NEXTDWORD(r5)
1009                beq- cr1,21f
1010/* d(base,index,scale) */
101119:             lwbrx r3,state,r3
1012                add offset,offset,r5
1013                add offset,offset,r3
1014                bgtctr cr2
1015                addi base,ssb,0
1016                bctr
1017/* 8 bit displacement */
101820:             NEXTBYTE(r5)
1019                extsb r5,r5
1020                bne+ cr1,19b
1021/* d(base), in practice base is %esp  */
102221:             add offset,offset,r5
1023                bgtctr- cr2
1024                addi base,ssb,0
1025                bctr
1026
1027/*
1028 *  Flag evaluation subroutines: they have not been written for performance
1029 * since they are not often used in practice. The rule of the game was to
1030 * write them with as few branches as possible.
1031 * The first routines eveluate either one or 2 (ZF and SF simultaneously)
1032 * flags and do not use r0 and r7.
1033 * The more complex routines (_eval_above, _eval_signed and _eval_flags)
1034 * call the former ones, using r0 as a return address save register and
1035 * r7 as a safe temporary.
1036 */
1037
1038/*
1039 * _eval_sf_zf evaluates simultaneously SF and ZF unless ZF is already valid
1040 * and protected because it is possible, although it is exceptional, to have
1041 * SF and ZF set at the same time after a few instructions which may leave the
1042 * flags in this apparently inconsistent state: sahf, popf, iret and the few
1043 * (for now unimplemented) instructions which only affect ZF (lar, lsl, arpl,
1044 * cmpxchg8b). This also solves the obscure case of ZF set and PF clear.
1045 * On return: SF=cr6[0], ZF=cr6[2].
1046 */
1047       
1048_eval_sf_zf:    andis. r5,flags,ZF_PROTECT>>16
1049                rlwinm r3,flags,0,INCDEC_FIELD
1050                RES_SHIFT(r4)
1051                cntlzw r3,r3
1052                slw r4,result,r4
1053                srwi r5,r3,5                    # ? use result : use op1
1054                rlwinm r3,r3,2,0x18
1055                oris flags,flags,(SF_IN_CR|SIGNED_IN_CR|ZF_IN_CR)>>16
1056                neg r5,r5                       # mux result/op2
1057                slw r3,op2,r3
1058                and r4,r4,r5
1059                andc r3,r3,r5
1060                xoris flags,flags,(SIGNED_IN_CR)>>16
1061                bne- 1f                         # 12 instructions between set
1062                or r3,r3,r4                     # and test, good for folding
1063                cmpwi cr6,r3,0
1064                blr
10651:              or. r3,r3,r4
1066                crmove SF,0
1067                blr
1068
1069/*
1070 * _eval_cf may be called at any time, no other flag is affected.
1071 * On return: CF=cr4[0], r3= CF ? 0x100:0 = CF<<8.
1072 */
1073_eval_cf:       addc r3,flags,flags             # CF_IN to xer[ca]
1074                RES2CF(r4)                      # get 8 or 16 bit carry
1075                subfe r3,result,op1             # generate PPC carry for
1076                CF_ROTCNT(r5)                   # preceding operation
1077                addze r3,r4                     # put carry into LSB
1078                CF_POL(r4,23)                   # polarity & 0x100
1079                oris flags,flags,(CF_IN_CR|ABOVE_IN_CR)>>16
1080                rlwnm r3,r3,r5,23,23            # shift carry there
1081                xor r3,r3,r4                    # CF <<8
1082                xoris flags,flags,(ABOVE_IN_CR)>>16
1083                cmplw cr4,one,r3                # sets cr4[0]
1084                blr
1085
1086/*
1087 * eval_of returns the overflow flag in OF_STATE field, which will be
1088 * either 001 (OF clear) or 101 (OF set), is is only called when the two
1089 * low order bits of OF_STATE are not 01 (otherwise it will work but
1090 * it is an elaborate variant of a nop with a few registers destroyed)
1091 * The code multiplexes several sources in a branchless way, was fun to write.
1092 */
1093_eval_of:       GET_ADDSUB(r4)                  # 0(add)/1(sub)
1094                rlwinm r3,flags,0,INCDEC_FIELD
1095                neg r4,r4                       # 0(add)/-1(sub)
1096                eqv r5,result,op1               # result[]==op1[] (bit by bit)
1097                cntlzw r3,r3                    # inc/dec
1098                xor r4,r4,op2                   # true sign of op2
1099                oris r5,r5,0x0808               # bits to clear
1100                clrlwi r6,r3,31                 # 0(inc)/1(dec)
1101                eqv r4,r4,op1                   # op1[]==op2[] (bit by bit)
1102                add r6,op2,r6                   # add 1 if dec
1103                rlwinm r3,r3,2,0x18             # incdec_shift
1104                andc r4,r4,r5                   # arithmetic overflow
1105                slw r3,r6,r3                    # shifted inc/dec result
1106                addis r3,r3,0x8000              # compare with 0x80000000
1107                ori r4,r4,0x0808                # bits to set
1108                cntlzw r3,r3                    # 32 if inc/dec overflow
1109                OF_ROTCNT(r6)
1110                rlwimi r4,r3,18,0x00800000      # insert inc/dec overflow
1111                rlwimi flags,one,24,OF_STATE_MASK
1112                rlwnm r3,r4,r6,8,8              # get field
1113                rlwimi flags,r3,3,OF_VALUE      # insert OF
1114                blr
1115
1116/*
1117 * _eval_pf will always be called when needed (complex but infrequent),
1118 * there are a few quirks for a branchless solution.
1119 * On return: PF=cr0[0], PF=MSB(r3)
1120 */
1121_eval_pf:       rlwinm r3,flags,0,INCDEC_FIELD
1122                rotrwi r4,op2,4                 # from inc/dec
1123                rotrwi r5,result,4              # from result
1124                cntlzw r3,r3                    # use result if 32
1125                xor r4,r4,op2
1126                xor r5,r5,result
1127                rlwinm r3,r3,26,0,0             # 32 becomes 0x80000000
1128                clrlwi r4,r4,28
1129                lis r6,0x9669                   # constant to shift
1130                clrlwi r5,r5,28
1131                rlwnm r4,r6,r4,0,0              # parity from inc/dec
1132                rlwnm r5,r6,r5,0,0              # parity from result
1133                andc r4,r4,r3                   # select which one
1134                and r5,r5,r3
1135                add. r3,r4,r5                   # and test to simplify
1136                blr                             # returns in r3 and cr0 set.
1137
1138/*
1139 * _eval_af will always be called when needed (complex but infrequent):
1140 * - if after inc, af is set when 4 low order bits of op1 are 0
1141 * - if after dec, af is set when 4 low order bits of op1 are 1
1142 *   (or 0 after adding 1 as implemented here)
1143 * - if after add/sub/adc/sbb/cmp af is set from sum of 4 LSB of op1
1144 *    and 4 LSB of op2 (eventually complemented) plus carry in.
1145 * - other instructions leave AF undefined so the returned value is irrelevant.
1146 * Returned value must be masked with 0x10, since all other bits are undefined.
1147 * There branchless code is perhaps not the most efficient, but quite parallel.
1148 */
1149_eval_af:       rlwinm r3,flags,0,INCDEC_FIELD
1150                clrlwi r5,op2,28                # 4 LSB of op2
1151                addc r4,flags,flags             # carry_in
1152                GET_ADDSUB(r6)
1153                cntlzw r3,r3                    # if inc/dec 16..23 else 32
1154                neg r6,r6                       # add/sub
1155                clrlwi r4,r3,31                 # if dec 1 else 0
1156                xor r5,r5,r6                    # conditionally complement
1157                clrlwi r6,op1,28                # 4 LSB of op1
1158                add r4,op2,r4                   # op2+(dec ? 1 : 0)
1159                clrlwi r4,r4,28                 # 4 LSB of op2+(dec ? 1 : 0)
1160                adde r5,r6,r5                   # op1+cy_in+(op2/~op2)
1161                cntlzw r4,r4                    # 28..31 if not AF, 32 if set
1162                andc r5,r5,r3                   # masked AF from add/sub...
1163                andc r4,r3,r4                   # masked AF from inc/dec
1164                or r3,r4,r5
1165                blr
1166
1167/*
1168 * _eval_above will only be called if ABOVE_IN_CR is not set.
1169 * On return: ZF=cr6[2], CF=cr4[0], ABOVE=cr4[1]
1170 */
1171_eval_above:    andis. r3,flags,ZF_IN_CR>>16
1172                mflr r0
1173                beql+ _eval_sf_zf
1174                andis. r3,flags,CF_IN_CR>>16
1175                beql+ _eval_cf
1176                mtlr r0
1177                oris flags,flags,ABOVE_IN_CR>>16
1178                crnor ABOVE,ZF,CF
1179                blr
1180
1181/* _eval_signed may only be called when signed_in_cr is clear ! */
1182_eval_signed:   andis. r3,flags,SF_IN_CR>>16
1183                mflr r0
1184                beql+ _eval_sf_zf
1185# SF_IN_CR and ZF_IN_CR are set, SIGNED_IN_CR is clear
1186                rlwinm. r3,flags,5,0,1
1187                xoris flags,flags,(SIGNED_IN_CR|SF_IN_CR)>>16
1188                bngl+ _eval_of
1189                andis. r3,flags,OF_VALUE>>16
1190                mtlr r0
1191                crxor SLT,SF,OF
1192                crnor SGT,SLT,ZF
1193                blr
1194
1195_eval_flags:    mflr r0
1196                bl _eval_cf
1197                li r7,2
1198                rlwimi r7,r3,24,CF86,CF86       # 2 if CF clear, 3 if set
1199                bl _eval_pf
1200                andis. r4,flags,SF_IN_CR>>16
1201                rlwimi r7,r3,32+PF-PF86,PF86,PF86
1202                bl _eval_af
1203                rlwimi r7,r3,0,AF86,AF86
1204                beql+ _eval_sf_zf
1205                mfcr r3
1206                rlwinm. r4,flags,5,0,1
1207                rlwimi r7,r3,0,DF86,SF86
1208                ZF2ZF86(r3,r7)
1209                bngl+ _eval_of
1210                mtlr r0
1211                lis r4,0x0004
1212                lwz r3,eflags(state)
1213                addi r4,r4,0x7000
1214                rlwimi r7,flags,17,OF86,OF86
1215                and r3,r3,r4
1216                or r3,r3,r7
1217                blr
1218
1219/* Quite simple for real mode, input in r4, returns in r3. */
1220_segment_load:  lwz r5,vbase(state)
1221                rlwinm r3,r4,4,0xffff0          # segment selector * 16
1222                add r3,r3,r5
1223                blr
1224
1225/* To allow I/O port virtualization if necessary, code for exception in r3,
1226port number in r4 */
1227_check_port:    lwz r5,ioperm(state)
1228                rlwinm r6,r4,29,0x1fff          # 0 to 8kB
1229                lis r0,0xffff
1230                lhbrx r5,r5,r6
1231                clrlwi r6,r4,29                 # modulo 8
1232                rlwnm r0,r0,r3,0x0f             # 1, 3, or 0xf
1233                slw r0,r0,r6
1234                and. r0,r0,r5
1235                bne- complex
1236                blr
1237/*
1238 * Instructions are in approximate functional order:
1239 * 1) move, exchange, lea, push/pop, pusha/popa
1240 * 2) cbw/cwde/cwd/cdq, zero/sign extending moves, in/out
1241 * 3) arithmetic: add/sub/adc/sbb/cmp/inc/dec/neg
1242 * 4) logical: and/or/xor/test/not/bt/btc/btr/bts/bsf/bsr
1243 * 5) jump, call, ret
1244 * 6) string instructions and xlat
1245 * 7) rotate/shift/mul/div
1246 * 8) segment register, far jumps, calls and rets, interrupts
1247 * 9) miscellenaous (flags, bcd,...)
1248 */
1249
1250#define MEM offset,base
1251#define REG opreg,state
1252#define SELECTORS 32
1253#define SELBASES 64
1254
1255/* Immediate moves */
1256movb_imm_reg:   rlwinm opreg,opcode,2,28,29; lbz r3,1(eip)
1257                rlwimi opreg,opcode,30,31,31; lbzu opcode,2(eip)
1258                stbx r3,REG; GOTNEXT
1259       
1260movw_imm_reg:   lhz r3,1(eip); clrlslwi opreg,opcode,29,2; lbzu opcode,3(eip)
1261                sthx r3,REG; GOTNEXT
1262               
1263movl_imm_reg:   lwz r3,1(eip); clrlslwi opreg,opcode,29,2; lbzu opcode,5(eip)
1264                stwx r3,REG; GOTNEXT
1265               
1266movb_imm_mem:   lbz r0,1(eip); cmpwi opreg,0
1267                lbzu opcode,2(eip); bne- ud
1268                stbx r0,MEM; GOTNEXT
1269
1270movw_imm_mem:   lhz r0,1(eip); cmpwi opreg,0
1271                lbzu opcode,3(eip); bne- ud
1272                sthx r0,MEM; GOTNEXT
1273
1274movl_imm_mem:   lwz r0,1(eip); cmpwi opreg,0
1275                lbzu opcode,5(eip); bne- ud
1276                stwx r0,MEM; GOTNEXT
1277
1278/* The special short form moves between memory and al/ax/eax */
1279movb_al_a32:    lwbrx offset,eip,one; lbz r0,AL(state); lbzu opcode,5(eip)
1280                stbx r0,MEM; GOTNEXT
1281
1282movb_al_a16:    lhbrx offset,eip,one; lbz r0,AL(state); lbzu opcode,3(eip)
1283                stbx r0,MEM; GOTNEXT
1284
1285movw_ax_a32:    lwbrx offset,eip,one; lhz r0,AX(state); lbzu opcode,5(eip)
1286                sthx r0,MEM; GOTNEXT
1287
1288movw_ax_a16:    lhbrx offset,eip,one; lhz r0,AX(state); lbzu opcode,3(eip)
1289                sthx r0,MEM; GOTNEXT
1290
1291movl_eax_a32:   lwbrx offset,eip,one; lwz r0,EAX(state); lbzu opcode,5(eip)
1292                stwx r0,MEM; GOTNEXT
1293
1294movl_eax_a16:   lhbrx offset,eip,one; lwz r0,EAX(state); lbzu opcode,3(eip)
1295                stwx r0,MEM; GOTNEXT
1296
1297movb_a32_al:    lwbrx offset,eip,one; lbzu opcode,5(eip); lbzx r0,MEM
1298                stb r0,AL(state); GOTNEXT
1299
1300movb_a16_al:    lhbrx offset,eip,one; lbzu opcode,3(eip); lbzx r0,MEM
1301                stb r0,AL(state); GOTNEXT
1302
1303movw_a32_ax:    lwbrx offset,eip,one; lbzu opcode,5(eip); lhzx r0,MEM
1304                sth r0,AX(state); GOTNEXT
1305
1306movw_a16_ax:    lhbrx offset,eip,one; lbzu opcode,3(eip); lhzx r0,MEM
1307                sth r0,AX(state); GOTNEXT
1308
1309movl_a32_eax:   lwbrx offset,eip,one; lbzu opcode,5(eip); lwzx r0,MEM
1310                stw r0,EAX(state); GOTNEXT
1311
1312movl_a16_eax:   lhbrx offset,eip,one; lbzu opcode,3(eip); lwzx r0,MEM
1313                stw r0,EAX(state); GOTNEXT
1314
1315/* General purpose move (all are exactly 4 instructions long) */
1316                .align 4
1317movb_reg_mem:   lbzx r0,REG
1318                NEXTBYTE(opcode)
1319                stbx r0,MEM
1320                GOTNEXT
1321
1322movw_reg_mem:   lhzx r0,REG
1323                NEXTBYTE(opcode)
1324                sthx r0,MEM
1325                GOTNEXT
1326
1327movl_reg_mem:   lwzx r0,REG
1328                NEXTBYTE(opcode)
1329                stwx r0,MEM
1330                GOTNEXT
1331
1332movb_mem_reg:   lbzx r0,MEM
1333                NEXTBYTE(opcode)
1334                stbx r0,REG
1335                GOTNEXT
1336
1337movw_mem_reg:   lhzx r0,MEM
1338                NEXTBYTE(opcode)
1339                sthx r0,REG
1340                GOTNEXT
1341
1342movl_mem_reg:   lwzx r0,MEM
1343                NEXTBYTE(opcode)
1344                stwx r0,REG
1345                GOTNEXT
1346
1347/* short form exchange ax/eax with register */
1348xchgw_ax_reg:   clrlslwi opreg,opcode,29,2
1349                lhz r3,AX(state)
1350                lhzx r4,REG
1351                sthx r3,REG
1352                sth r4,AX(state)
1353                NEXT
1354
1355xchgl_eax_reg:  clrlslwi opreg,opcode,29,2
1356                lwz r3,EAX(state)
1357                lwzx r4,REG
1358                stwx r3,REG
1359                stw r4,EAX(state)
1360                NEXT
1361
1362/* General exchange (unlocked!) */
1363xchgb_reg_mem:  lbzx r3,MEM
1364                lbzx r4,REG
1365                NEXTBYTE(opcode)
1366                stbx r3,REG
1367                stbx r4,MEM
1368                GOTNEXT
1369
1370xchgw_reg_mem:  lhzx r3,MEM
1371                lhzx r4,REG
1372                sthx r3,REG
1373                sthx r4,MEM
1374                NEXT
1375
1376xchgl_reg_mem:  lwzx r3,MEM
1377                lwzx r4,REG
1378                stwx r3,REG
1379                stwx r4,MEM
1380                NEXT
1381
1382/* lea, one of the simplest instructions */
1383leaw:           cmpw base,state
1384                beq- ud
1385                sthbrx offset,REG
1386                NEXT
1387       
1388leal:           cmpw base,state
1389                beq- ud
1390                stwbrx offset,REG
1391                NEXT
1392       
1393/* Short form pushes and pops */
1394pushw_sp_reg:   li r3,SP
1395                lhbrx r4,state,r3
1396                clrlslwi opreg,opcode,29,2
1397                lhzx r0,REG
1398                addi r4,r4,-2
1399                sthbrx r4,state,r3
1400                clrlwi r4,r4,16
1401                sthx r0,ssb,r4
1402                NEXT
1403       
1404pushl_sp_reg:   li r3,SP
1405                lhbrx r4,state,r3
1406                clrlslwi opreg,opcode,29,2
1407                lwzx r0,REG
1408                addi r4,r4,-4
1409                sthbrx r4,state,r3
1410                clrlwi r4,r4,16
1411                stwx r0,ssb,r4
1412                NEXT
1413       
1414popw_sp_reg:    li r3,SP
1415                lhbrx r4,state,r3
1416                clrlslwi opreg,opcode,29,2
1417                lhzx r0,ssb,r4
1418                addi r4,r4,2            # order is important in case of pop sp
1419                sthbrx r4,state,r3
1420                sthx r0,REG
1421                NEXT
1422       
1423popl_sp_reg:    li r3,SP
1424                lhbrx r4,state,r3
1425                clrlslwi opreg,opcode,29,2
1426                lwzx r0,ssb,r4
1427                addi r4,r4,4
1428                sthbrx r4,state,r3
1429                stwx r0,REG
1430                NEXT
1431
1432/* Push immediate */
1433pushw_sp_imm:   li r3,SP
1434                lhbrx r4,state,r3
1435                lhz r0,1(eip)
1436                addi r4,r4,-2
1437                sthbrx r4,state,r3
1438                clrlwi r4,r4,16
1439                lbzu opcode,3(eip)
1440                sthx r0,ssb,r4         
1441                GOTNEXT
1442       
1443pushl_sp_imm:   li r3,SP
1444                lhbrx r4,state,r3
1445                lwz r0,1(eip)
1446                addi r4,r4,-4
1447                sthbrx r4,state,r3
1448                clrlwi r4,r4,16
1449                lbzu opcode,5(eip)
1450                stwx r0,ssb,r4         
1451                GOTNEXT
1452
1453pushw_sp_imm8:  li r3,SP
1454                lhbrx r4,state,r3
1455                lhz r0,1(eip)
1456                addi r4,r4,-2
1457                sthbrx r4,state,r3
1458                clrlwi r4,r4,16
1459                lbzu opcode,2(eip)
1460                extsb r0,r0
1461                sthx r0,ssb,r4         
1462                GOTNEXT
1463       
1464pushl_sp_imm8:  li r3,SP
1465                lhbrx r4,state,r3
1466                lhz r0,1(eip)
1467                addi r4,r4,-4
1468                sthbrx r4,state,r3
1469                clrlwi r4,r4,16
1470                lbzu opcode,2(eip)
1471                extsb r0,r0
1472                stwx r0,ssb,r4         
1473                GOTNEXT
1474       
1475/* General push/pop */
1476pushw_sp:       lhbrx r0,MEM
1477                li r3,SP
1478                lhbrx r4,state,r3
1479                addi r4,r4,-2
1480                sthbrx r4,state,r3
1481                clrlwi r4,r4,16
1482                sthbrx r0,r4,ssb
1483                NEXT
1484       
1485pushl_sp:       lwbrx r0,MEM
1486                li r3,SP
1487                lhbrx r4,state,r3
1488                addi r4,r4,-4
1489                sthbrx r4,state,r3
1490                clrlwi r4,r4,16
1491                stwbrx r0,r4,ssb
1492                NEXT
1493                       
1494/* pop is an exception with 32 bit addressing modes, it is possible
1495to calculate wrongly the address when esp is used as base. But 16 bit
1496addressing modes are safe */
1497               
1498popw_sp_a16:    cmpw cr1,opreg,0        # first check the opcode
1499                li r3,SP
1500                lhbrx r4,state,r3
1501                bne- cr1,ud
1502                lhzx r0,ssb,r4
1503                addi r4,r4,2
1504                sthx r0,MEM
1505                sthbrx r4,state,r3
1506                NEXT
1507       
1508popl_sp_a16:    cmpw cr1,opreg,0
1509                li r3,SP
1510                lhbrx r4,state,r3
1511                bne- cr1,ud
1512                lwzx r0,ssb,r4
1513                addi r4,r4,2
1514                stwx r0,MEM
1515                sthbrx r4,state,r3
1516                NEXT
1517
1518/* 32 bit addressing modes for pop not implemented for now. */
1519                .equ popw_sp_a32,unimpl
1520                .equ popl_sp_a32,unimpl
1521
1522/* pusha/popa */
1523pushaw_sp:      li r3,SP
1524                li r0,8
1525                lhbrx r4,r3,state
1526                mtctr r0
1527                addi r5,state,-4
15281:              addi r4,r4,-2
1529                lhzu r6,4(r5)
1530                clrlwi r4,r4,16
1531                sthx r6,ssb,r4
1532                bdnz 1b
1533                sthbrx r4,r3,state      # new sp
1534                NEXT
1535
1536pushal_sp:      li r3,SP
1537                li r0,8
1538                lhbrx r4,r3,state
1539                mtctr r0
1540                addi r5,state,-4
15411:              addi r4,r4,-4
1542                lwzu r6,4(r5)
1543                clrlwi r4,r4,16
1544                stwx r6,ssb,r4
1545                bdnz 1b
1546                sthbrx r4,r3,state      # new sp
1547                NEXT
1548
1549popaw_sp:       li r3,SP
1550                li r0,8
1551                lhbrx r4,state,r3
1552                mtctr r0
1553                addi r5,state,32
15541:              lhzx r6,ssb,r4
1555                addi r4,r4,2
1556                sthu r6,-4(r5)
1557                clrlwi r4,r4,16
1558                bdnz 1b
1559                sthbrx r4,r3,state      # updated sp
1560                NEXT
1561       
1562popal_sp:       li r3,SP
1563                lis r0,0xef00           # mask to skip esp
1564                lhbrx r4,state,r3
1565                addi r5,state,32
15661:              add. r0,r0,r0
1567                lwzx r6,ssb,r4
1568                addi r4,r4,4
1569                stwu r6,-4(r5)
1570                clrlwi r4,r4,16
1571                blt 1b
1572                addi r6,r6,-4
1573                beq 2f
1574                addi r4,r4,4
1575                clrlwi r4,r4,16
1576                b 1b
15772:              sthbrx r4,state,r3      # updated sp
1578                NEXT
1579
1580/* Moves with zero or sign extension: first the special cases */       
1581cbw:            lbz r3,AL(state)
1582                extsb r3,r3
1583                sthbrx r3,AX,state
1584                NEXT
1585       
1586cwde:           lhbrx r3,AX,state
1587                extsh r3,r3
1588                stwbrx r3,EAX,state
1589                NEXT
1590
1591cwd:            lbz r3,AH(state)
1592                extsb r3,r3
1593                srwi r3,r3,8                    # get sign bits
1594                sth r3,DX(state)
1595                NEXT
1596
1597cdq:            lwbrx r3,EAX,state
1598                srawi r3,r3,31
1599                stw r3,EDX(state)               # byte order unimportant !
1600                NEXT
1601
1602/* The move with zero or sign extension are special since the source
1603and destination are not the same size. The register describing the destination
1604is modified to take this into account. */
1605
1606movsbw:         lbzx r3,MEM
1607                rlwimi opreg,opreg,4,0x10
1608                extsb r3,r3
1609                rlwinm opreg,opreg,0,0x1c
1610                sthbrx r3,REG
1611                NEXT
1612
1613movsbl:         lbzx r3,MEM
1614                rlwimi opreg,opreg,4,0x10
1615                extsb r3,r3
1616                rlwinm opreg,opreg,0,0x1c
1617                stwbrx r3,REG
1618                NEXT
1619
1620                .equ movsww, movw_mem_reg
1621       
1622movswl:         lhbrx r3,MEM
1623                extsh r3,r3
1624                stwbrx r3,REG
1625                NEXT
1626       
1627movzbw:         lbzx r3,MEM
1628                rlwimi opreg,opreg,4,0x10
1629                rlwinm opreg,opreg,0,0x1c
1630                sthbrx r3,REG
1631                NEXT
1632
1633movzbl:         lbzx r3,MEM
1634                rlwimi opreg,opreg,4,0x10
1635                rlwinm opreg,opreg,0,0x1c
1636                stwbrx r3,REG
1637                NEXT
1638       
1639                .equ movzww, movw_mem_reg
1640
1641movzwl:         lhbrx r3,MEM
1642                stwbrx r3,REG
1643                NEXT
1644
1645/* Byte swapping */     
1646bswap:          clrlslwi opreg,opcode,29,2      # extract reg from opcode
1647                lwbrx r0,REG
1648                stwx r0,REG
1649                NEXT
1650       
1651/* Input/output */
1652inb_port_al:    NEXTBYTE(r4)
1653                b 1f
1654inb_dx_al:      li r4,DX
1655                lhbrx r4,r4,state
16561:              li r3,code_inb
1657                bl _check_port
1658                lwz r3,iobase(state)
1659                lbzx r5,r4,r3
1660                eieio
1661                stb r5,AL(state)
1662                NEXT           
1663       
1664inw_port_ax:    NEXTBYTE(r4)
1665                b 1f
1666inw_dx_ax:      li r4,DX
1667                lhbrx r4,r4,state
16681:              li r3,code_inw
1669                bl _check_port
1670                lwz r3,iobase(state)
1671                lhzx r5,r4,r3
1672                eieio
1673                sth r5,AX(state)
1674                NEXT           
1675       
1676inl_port_eax:   NEXTBYTE(r4)
1677                b 1f
1678inl_dx_eax:     li r4,DX
1679                lhbrx r4,r4,state
16801:              li r3,code_inl
1681                bl _check_port
1682                lwz r3,iobase(state)
1683                lwzx r5,r4,r3
1684                eieio
1685                stw r5,EAX(state)
1686                NEXT
1687               
1688outb_al_port:   NEXTBYTE(r4)
1689                b 1f
1690outb_al_dx:     li r4,DX
1691                lhbrx r4,r4,state
16921:              li r3,code_outb
1693                bl _check_port
1694                lwz r3,iobase(state)
1695                lbz r5,AL(state)
1696                stbx r5,r4,r3
1697                eieio
1698                NEXT           
1699       
1700outw_ax_port:   NEXTBYTE(r4)
1701                b 1f
1702outw_ax_dx:     li r4,DX
1703                lhbrx r4,r4,state
17041:              li r3,code_outw
1705                bl _check_port
1706                lwz r3,iobase(state)
1707                lhz r5,AX(state)
1708                sthx r5,r4,r3
1709                eieio
1710                NEXT           
1711       
1712outl_eax_port:  NEXTBYTE(r4)
1713                b 1f
1714outl_eax_dx:    li r4,DX
1715                lhbrx r4,r4,state
17161:              li r3,code_outl
1717                bl _check_port
1718                lwz r4,iobase(state)
1719                lwz r5,EAX(state)
1720                stwx r5,r4,r3
1721                eieio
1722                NEXT
1723
1724
1725/* Macro used for add and sub */
1726#define ARITH(op,fl) \
1727op##b_reg_mem:  lbzx op1,MEM; SET_FLAGS(fl(B)); lbzx op2,REG; \
1728                op result,op1,op2; \
1729                stbx result,MEM; NEXT; \
1730op##w_reg_mem:  lhbrx op1,MEM; SET_FLAGS(fl(W)); lhbrx op2,REG; \
1731                op result,op1,op2; \
1732                sthbrx result,MEM; NEXT; \
1733op##l_reg_mem:  lwbrx op1,MEM; SET_FLAGS(fl(L)); lwbrx op2,REG; \
1734                op result,op1,op2; \
1735                stwbrx result,MEM; NEXT; \
1736op##b_mem_reg:  lbzx op2,MEM; SET_FLAGS(fl(B)); lbzx op1,REG; \
1737                op result,op1,op2; \
1738                stbx result,REG; NEXT; \
1739op##w_mem_reg:  lhbrx op2,MEM; SET_FLAGS(fl(W)); lhbrx op1,REG; \
1740                op result,op1,op2; \
1741                sthbrx result,REG; NEXT; \
1742op##l_mem_reg:  lwbrx op2,MEM; SET_FLAGS(fl(L)); lwbrx op1,REG; \
1743                op result,op1,op2; \
1744                stwbrx result,REG; NEXT; \
1745op##b_imm_al:   addi base,state,0; li offset,AL; \
1746op##b_imm:      lbzx op1,MEM; SET_FLAGS(fl(B)); lbz op2,1(eip); \
1747                op result,op1,op2; \
1748                lbzu opcode,2(eip); \
1749                stbx result,MEM; GOTNEXT; \
1750op##w_imm_ax:   addi base,state,0; li offset,AX; \
1751op##w_imm:      lhbrx op1,MEM; SET_FLAGS(fl(W)); lhbrx op2,eip,one; \
1752                op result,op1,op2; \
1753                lbzu opcode,3(eip); \
1754                sthbrx result,MEM; GOTNEXT; \
1755op##w_imm8:     lbz op2,1(eip); SET_FLAGS(fl(W)); lhbrx op1,MEM; \
1756                extsb op2,op2; clrlwi op2,op2,16; \
1757                op result,op1,op2; \
1758                lbzu opcode,2(eip); \
1759                sthbrx result,MEM; GOTNEXT; \
1760op##l_imm_eax:  addi base,state,0; li offset,EAX; \
1761op##l_imm:      lwbrx op1,MEM; SET_FLAGS(fl(L)); lwbrx op2,eip,one; \
1762                op result,op1,op2; lbzu opcode,5(eip); \
1763                stwbrx result,MEM; GOTNEXT; \
1764op##l_imm8:     lbz op2,1(eip); SET_FLAGS(fl(L)); lwbrx op1,MEM; \
1765                extsb op2,op2; lbzu opcode,2(eip); \
1766                op result,op1,op2; \
1767                stwbrx result,MEM; GOTNEXT
1768
1769                ARITH(add, FLAGS_ADD)
1770                ARITH(sub, FLAGS_SUB)
1771
1772#define adc(result, op1, op2) adde result,op1,op2
1773#define sbb(result, op1, op2) subfe result,op2,op1
1774
1775#define ARITH_WITH_CARRY(op, fl) \
1776op##b_reg_mem:  lbzx op1,MEM; bl carryfor##op; lbzx op2,REG; \
1777                ADD_FLAGS(fl(B)); op(result, op1, op2); \
1778                stbx result,MEM; NEXT; \
1779op##w_reg_mem:  lhbrx op1,MEM; bl carryfor##op; lhbrx op2,REG; \
1780                ADD_FLAGS(fl(W)); op(result, op1, op2); \
1781                sthbrx result,MEM; NEXT; \
1782op##l_reg_mem:  lwbrx op1,MEM; bl carryfor##op; lwbrx op2,REG; \
1783                ADD_FLAGS(fl(L)); op(result, op1, op2); \
1784                stwbrx result,MEM; NEXT; \
1785op##b_mem_reg:  lbzx op1,MEM; bl carryfor##op; lbzx op2,REG; \
1786                ADD_FLAGS(fl(B)); op(result, op1, op2); \
1787                stbx result,REG; NEXT; \
1788op##w_mem_reg:  lhbrx op1,MEM; bl carryfor##op; lhbrx op2,REG; \
1789                ADD_FLAGS(fl(W)); op(result, op1, op2); \
1790                sthbrx result,REG; NEXT; \
1791op##l_mem_reg:  lwbrx op1,MEM; bl carryfor##op; lwbrx op2,REG; \
1792                ADD_FLAGS(fl(L)); op(result, op1, op2); \
1793                stwbrx result,REG; NEXT; \
1794op##b_imm_al:   addi base,state,0; li offset,AL; \
1795op##b_imm:      lbzx op1,MEM; bl carryfor##op; lbz op2,1(eip); \
1796                ADD_FLAGS(fl(B)); lbzu opcode,2(eip); op(result, op1, op2); \
1797                stbx result,MEM; GOTNEXT; \
1798op##w_imm_ax:   addi base,state,0; li offset,AX; \
1799op##w_imm:      lhbrx op1,MEM; bl carryfor##op; lhbrx op2,eip,one; \
1800                ADD_FLAGS(fl(W)); lbzu opcode,3(eip); op(result, op1, op2); \
1801                sthbrx result,MEM; GOTNEXT; \
1802op##w_imm8:     lbz op2,1(eip); bl carryfor##op; lhbrx op1,MEM; \
1803                extsb op2,op2; ADD_FLAGS(fl(W)); clrlwi op2,op2,16; \
1804                lbzu opcode,2(eip); op(result, op1, op2); \
1805                sthbrx result,MEM; GOTNEXT; \
1806op##l_imm_eax:  addi base,state,0; li offset,EAX; \
1807op##l_imm:      lwbrx op1,MEM; bl carryfor##op; lwbrx op2,eip,one; \
1808                ADD_FLAGS(fl(L)); lbzu opcode,5(eip); op(result, op1, op2); \
1809                stwbrx result,MEM; GOTNEXT; \
1810op##l_imm8:     lbz op2,1(eip); SET_FLAGS(fl(L)); lwbrx op1,MEM; \
1811                extsb op2,op2; lbzu opcode,2(eip); \
1812                op(result, op1, op2); \
1813                stwbrx result,MEM; GOTNEXT
1814
1815carryforadc:    addc r3,flags,flags             # CF_IN to xer[ca]
1816                RES2CF(r4)                      # get 8 or 16 bit carry
1817                subfe r3,result,op1             # generate PPC carry for
1818                CF_ROTCNT(r5)                   # preceding operation
1819                addze r3,r4                     # 32 bit carry in LSB
1820                CF_POL(r4,23)                   # polarity
1821                rlwnm r3,r3,r5,0x100            # shift carry there
1822                xor flags,r4,r3                 # CF86 ? 0x100 : 0
1823                addic r4,r3,0xffffff00          # set xer[ca]
1824                rlwinm flags,r3,23,CF_IN
1825                blr
1826
1827                ARITH_WITH_CARRY(adc, FLAGS_ADD)
1828       
1829/* for sbb the input carry must be the complement of the x86 carry */
1830carryforsbb:    addc r3,flags,flags             # CF_IN to xer[ca]
1831                RES2CF(r4)                      # 8/16 bit carry from result
1832                subfe r3,result,op1
1833                CF_ROTCNT(r5)
1834                addze r3,r4     
1835                CF_POL(r4,23)
1836                rlwnm r3,r3,r5,0x100
1837                eqv flags,r4,r3                 # CF86 ? 0xfffffeff:0xffffffff
1838                addic r4,r3,1                   # set xer[ca]
1839                rlwinm flags,r3,23,CF_IN        # keep only the carry
1840                blr
1841
1842                ARITH_WITH_CARRY(sbb, FLAGS_SBB)
1843
1844cmpb_reg_mem:   lbzx op1,MEM
1845                SET_FLAGS(FLAGS_CMP(B))
1846                lbzx op2,REG
1847                extsb r3,op1
1848                cmplw cr4,op1,op2
1849                extsb r4,op2
1850                sub result,op1,op2
1851                cmpw cr6,r3,r4
1852                NEXT
1853
1854cmpw_reg_mem:   lhbrx op1,MEM
1855                SET_FLAGS(FLAGS_CMP(W))
1856                lhbrx op2,REG
1857                extsh r3,op1
1858                cmplw cr4,op1,op2
1859                extsh r4,op2
1860                sub result,op1,op2
1861                cmpw cr6,r3,r4
1862                NEXT
1863
1864cmpl_reg_mem:   lwbrx op1,MEM
1865                SET_FLAGS(FLAGS_CMP(L))
1866                lwbrx op2,REG
1867                cmplw cr4,op1,op2
1868                sub result,op1,op2
1869                cmpw cr6,op1,op2
1870                NEXT
1871
1872cmpb_mem_reg:   lbzx op2,MEM
1873                SET_FLAGS(FLAGS_CMP(B))
1874                lbzx op1,REG
1875                extsb r4,op2
1876                cmplw cr4,op1,op2
1877                extsb r3,op1
1878                sub result,op1,op2
1879                cmpw cr6,r3,r4
1880                NEXT
1881
1882cmpw_mem_reg:   lhbrx op2,MEM
1883                SET_FLAGS(FLAGS_CMP(W))
1884                lhbrx op1,REG
1885                extsh r4,op2
1886                cmplw cr4,op1,op2
1887                extsh r3,op1
1888                sub result,op1,op2
1889                cmpw cr6,r3,r4
1890                NEXT
1891
1892cmpl_mem_reg:   lwbrx op2,MEM
1893                SET_FLAGS(FLAGS_CMP(L))
1894                lwbrx op1,REG
1895                cmpw cr6,op1,op2
1896                sub result,op1,op2
1897                cmplw cr4,op1,op2
1898                NEXT
1899
1900cmpb_imm_al:    addi base,state,0
1901                li offset,AL
1902cmpb_imm:       lbzx op1,MEM
1903                SET_FLAGS(FLAGS_CMP(B))
1904                lbz op2,1(eip)
1905                extsb r3,op1
1906                cmplw cr4,op1,op2
1907                lbzu opcode,2(eip)
1908                extsb r4,op2
1909                sub result,op1,op2
1910                cmpw cr6,r3,r4
1911                GOTNEXT
1912
1913cmpw_imm_ax:    addi base,state,0
1914                li offset,AX
1915cmpw_imm:       lhbrx op1,MEM
1916                SET_FLAGS(FLAGS_CMP(W))
1917                lhbrx op2,eip,one
1918                extsh r3,op1
1919                cmplw cr4,op1,op2
1920                lbzu opcode,3(eip)
1921                extsh r4,op2
1922                sub result,op1,op2
1923                cmpw cr6,r3,r4
1924                GOTNEXT
1925
1926cmpw_imm8:      lbz op2,1(eip)
1927                SET_FLAGS(FLAGS_CMP(W))
1928                lhbrx op1,MEM
1929                extsb r4,op2
1930                extsh r3,op1
1931                lbzu opcode,2(eip)
1932                clrlwi op2,r4,16
1933                cmpw cr6,r3,r4
1934                sub result,op1,op2
1935                cmplw cr4,op1,op2
1936                GOTNEXT
1937               
1938cmpl_imm_eax:   addi base,state,0
1939                li offset,EAX
1940cmpl_imm:       lwbrx op1,MEM
1941                SET_FLAGS(FLAGS_CMP(L))
1942                lwbrx op2,eip,one
1943                cmpw cr6,op1,op2
1944                lbzu opcode,5(eip)
1945                sub result,op1,op2
1946                cmplw cr4,op1,op2
1947                GOTNEXT
1948
1949cmpl_imm8:      lbz op2,1(eip)
1950                SET_FLAGS(FLAGS_CMP(L))
1951                lwbrx op1,MEM
1952                extsb op2,op2
1953                lbzu opcode,2(eip)
1954                cmpw cr6,op1,op2
1955                sub result,op1,op2
1956                cmplw cr4,op1,op2
1957                GOTNEXT
1958
1959/* Increment and decrement */
1960incb:           lbzx op2,MEM
1961                INC_FLAGS(B)
1962                addi op2,op2,1
1963                stbx op2,MEM
1964                NEXT
1965
1966incw_reg:       clrlslwi opreg,opcode,29,2      # extract reg from opcode
1967                lhbrx op2,REG
1968                INC_FLAGS(W)
1969                addi op2,op2,1
1970                sthbrx op2,REG
1971                NEXT
1972
1973incw:           lhbrx op2,MEM
1974                INC_FLAGS(W)
1975                addi op2,op2,1
1976                sthbrx op2,MEM
1977                NEXT
1978
1979incl_reg:       clrlslwi opreg,opcode,29,2
1980                lwbrx op2,REG
1981                INC_FLAGS(L)
1982                addi op2,op2,1
1983                sthbrx op2,REG
1984                NEXT
1985
1986incl:           lwbrx op2,MEM
1987                INC_FLAGS(L)
1988                addi op2,op2,1
1989                stwbrx op2,MEM
1990                NEXT
1991
1992decb:           lbzx op2,MEM
1993                DEC_FLAGS(B)
1994                addi op2,op2,-1
1995                stbx op2,MEM
1996                NEXT
1997
1998decw_reg:       clrlslwi opreg,opcode,29,2      # extract reg from opcode
1999                lhbrx op2,REG
2000                DEC_FLAGS(W)
2001                addi op2,op2,-1
2002                sthbrx op2,REG
2003                NEXT
2004
2005decw:           lhbrx op2,MEM
2006                DEC_FLAGS(W)
2007                addi op2,op2,-1
2008                sthbrx op2,MEM
2009                NEXT
2010
2011decl_reg:       clrlslwi opreg,opcode,29,2
2012                lwbrx op2,REG
2013                DEC_FLAGS(L)
2014                addi op2,op2,-1
2015                sthbrx op2,REG
2016                NEXT
2017
2018decl:           lwbrx op2,MEM
2019                DEC_FLAGS(L)
2020                addi op2,op2,-1
2021                stwbrx op2,MEM
2022                NEXT
2023
2024negb:           lbzx op2,MEM
2025                SET_FLAGS(FLAGS_SUB(B))
2026                neg result,op2
2027                li op1,0
2028                stbx result,MEM
2029                NEXT
2030
2031negw:           lhbrx op2,MEM
2032                SET_FLAGS(FLAGS_SUB(W))
2033                neg result,op2
2034                li op1,0
2035                sthbrx r0,MEM
2036                NEXT
2037
2038negl:           lwbrx op2,MEM
2039                SET_FLAGS(FLAGS_SUB(L))
2040                subfic result,op2,0
2041                li op1,0
2042                stwbrx result,MEM
2043                NEXT
2044
2045/* Macro used to generate code for OR/AND/XOR */
2046#define LOGICAL(op) \
2047op##b_reg_mem:  lbzx op1,MEM; SET_FLAGS(FLAGS_LOG(B)); lbzx op2,REG; \
2048                op result,op1,op2; \
2049                stbx result,MEM; NEXT; \
2050op##w_reg_mem:  lhbrx op1,MEM; SET_FLAGS(FLAGS_LOG(W)); lhbrx op2,REG; \
2051                op result,op1,op2; \
2052                sthbrx result,MEM; NEXT; \
2053op##l_reg_mem:  lwbrx op1,MEM; SET_FLAGS(FLAGS_LOG(L)); lwbrx op2,REG; \
2054                op result,op1,op2; \
2055                stwbrx result,MEM; NEXT; \
2056op##b_mem_reg:  lbzx op1,MEM; SET_FLAGS(FLAGS_LOG(B)); lbzx op2,REG; \
2057                op result,op1,op2; \
2058                stbx result,REG; NEXT; \
2059op##w_mem_reg:  lhbrx op2,MEM; SET_FLAGS(FLAGS_LOG(W)); lhbrx op1,REG; \
2060                op result,op1,op2; \
2061                sthbrx result,REG; NEXT; \
2062op##l_mem_reg:  lwbrx op2,MEM; SET_FLAGS(FLAGS_LOG(L)); lwbrx op1,REG; \
2063                op result,op1,op2; \
2064                stwbrx result,REG; NEXT; \
2065op##b_imm_al:   addi base,state,0; li offset,AL; \
2066op##b_imm:      lbzx op1,MEM; SET_FLAGS(FLAGS_LOG(B)); lbz op2,1(eip); \
2067                op result,op1,op2; lbzu opcode,2(eip); \
2068                stbx result,MEM; GOTNEXT; \
2069op##w_imm_ax:   addi base,state,0; li offset,AX; \
2070op##w_imm:      lhbrx op1,MEM; SET_FLAGS(FLAGS_LOG(W)); lhbrx op2,eip,one; \
2071                op result,op1,op2; lbzu opcode,3(eip); \
2072                sthbrx result,MEM; GOTNEXT; \
2073op##w_imm8:     lbz op2,1(eip); SET_FLAGS(FLAGS_LOG(W)); lhbrx op1,MEM; \
2074                extsb op2,op2; lbzu opcode,2(eip); \
2075                op result,op1,op2; \
2076                sthbrx result,MEM; GOTNEXT; \
2077op##l_imm_eax:  addi base,state,0; li offset,EAX; \
2078op##l_imm:      lwbrx op1,MEM; SET_FLAGS(FLAGS_LOG(L)); lwbrx op2,eip,one; \
2079                op result,op1,op2; lbzu opcode,5(eip); \
2080                stwbrx result,MEM; GOTNEXT; \
2081op##l_imm8:     lbz op2,1(eip); SET_FLAGS(FLAGS_LOG(L)); lwbrx op1,MEM; \
2082                extsb op2,op2; lbzu opcode,2(eip); \
2083                op result,op1,op2; \
2084                stwbrx result,MEM; GOTNEXT
2085               
2086                LOGICAL(or)
2087
2088                LOGICAL(and)
2089
2090                LOGICAL(xor)
2091
2092testb_reg_mem:  lbzx op1,MEM
2093                SET_FLAGS(FLAGS_TEST(B))
2094                lbzx op2,REG
2095                and result,op1,op2
2096                extsb r3,result
2097                cmpwi cr6,r3,0
2098                NEXT
2099
2100testw_reg_mem:  lhbrx op1,MEM
2101                SET_FLAGS(FLAGS_TEST(W))
2102                lhbrx op2,REG
2103                and result,op1,op2
2104                extsh r3,result
2105                cmpwi cr6,r3,0
2106                NEXT
2107
2108testl_reg_mem:  lwbrx r3,MEM
2109                SET_FLAGS(FLAGS_TEST(L))
2110                lwbrx r4,REG
2111                and result,op1,op2
2112                cmpwi cr6,result,0
2113                NEXT
2114
2115testb_imm_al:   addi base,state,0
2116                li offset,AL
2117testb_imm:      lbzx op1,MEM
2118                SET_FLAGS(FLAGS_TEST(B))
2119                lbz op2,1(eip)
2120                and result,op1,op2
2121                lbzu opcode,2(eip)
2122                extsb r3,result
2123                cmpwi cr6,r3,0
2124                GOTNEXT
2125
2126testw_imm_ax:   addi base,state,0
2127                li offset,AX
2128testw_imm:      lhbrx op1,MEM
2129                SET_FLAGS(FLAGS_TEST(W))
2130                lhbrx op2,eip,one
2131                and result,op1,op2
2132                lbzu opcode,3(eip)
2133                extsh r3,result
2134                cmpwi cr6,r3,0
2135                GOTNEXT
2136
2137testl_imm_eax:  addi base,state,0
2138                li offset,EAX
2139testl_imm:      lwbrx op1,MEM
2140                SET_FLAGS(FLAGS_TEST(L))
2141                lwbrx op2,eip,one
2142                and result,r3,r4
2143                lbzu opcode,5(eip)
2144                cmpwi cr6,result,0
2145                GOTNEXT
2146
2147/* Not does not affect flags */
2148notb:           lbzx r3,MEM
2149                xori r3,r3,255
2150                stbx r3,MEM
2151                NEXT
2152       
2153notw:           lhzx r3,MEM
2154                xori r3,r3,65535
2155                sthx r3,MEM
2156                NEXT
2157       
2158notl:           lwzx r3,MEM
2159                not r3,r3
2160                stwx r3,MEM
2161                NEXT
2162       
2163boundw:         lhbrx r4,REG
2164                li r3,code_bound
2165                lhbrx r5,MEM
2166                addi offset,offset,2
2167                extsh r4,r4
2168                lhbrx r6,MEM
2169                extsh r5,r5
2170                cmpw r4,r5
2171                extsh r6,r6
2172                blt- complex
2173                cmpw r4,r6
2174                ble+ nop
2175                b complex
2176               
2177boundl:         lwbrx r4,REG
2178                li r3,code_bound
2179                lwbrx r5,MEM
2180                addi offset,offset,4
2181                lwbrx r6,MEM
2182                cmpw r4,r5
2183                blt- complex
2184                cmpw r4,r6
2185                ble+ nop
2186                b complex
2187
2188/* Bit test and modify instructions */
2189       
2190/* Common routine: bit index in op2, returns memory value in r3, mask in op2,
2191and of mask and value in op1. CF flag is set as with 32 bit add when bit is
2192non zero since result (which is cleared) will be less than op1, and in cr4,
2193all other flags are undefined from Intel doc. Here OF and SF are cleared
2194and ZF is set as a side effect of result being cleared.  */
2195_setup_bitw:    cmpw base,state
2196                SET_FLAGS(FLAGS_BTEST)
2197                extsh op2,op2
2198                beq- 1f
2199                srawi r4,op2,4
2200                add offset,offset,r4
22011:              clrlwi op2,op2,28               # true bit index
2202                lhbrx r3,MEM
2203                slw op2,one,op2                 # build mask
2204                li result,0                     # implicitly sets CF
2205                and op1,r3,op2                  # if result<op1
2206                cmplw cr4,result,op1            # sets CF in cr4
2207                blr
2208       
2209_setup_bitl:    cmpw base,state
2210                SET_FLAGS(FLAGS_BTEST)
2211                beq- 1f
2212                srawi r4,op2,5
2213                add offset,offset,r4
22141:              lwbrx r3,MEM
2215                rotlw op2,one,op2               # build mask
2216                li result,0
2217                and op1,r3,op2
2218                cmplw cr4,result,op1
2219                blr
2220       
2221/* Immediate forms bit tests are not frequent since logical are often faster */
2222btw_imm:        NEXTBYTE(op2)
2223                b 1f
2224btw_reg_mem:    lhbrx op2,REG
22251:              bl _setup_bitw
2226                NEXT
2227               
2228btl_imm:        NEXTBYTE(op2)
2229                b 1f
2230btl_reg_mem:    lhbrx op2,REG
22311:              bl _setup_bitl
2232                NEXT
2233
2234btcw_imm:       NEXTBYTE(op2)
2235                b 1f
2236btcw_reg_mem:   lhbrx op2,REG
22371:              bl _setup_bitw
2238                xor r3,r3,op2
2239                sthbrx r3,MEM
2240                NEXT
2241               
2242btcl_imm:       NEXTBYTE(op2)
2243                b 1f
2244btcl_reg_mem:   lhbrx op2,REG
22451:              bl _setup_bitl
2246                xor r3,r3,op2
2247                stwbrx result,MEM
2248                NEXT
2249               
2250btrw_imm:       NEXTBYTE(op2)
2251                b 1f
2252btrw_reg_mem:   lhbrx op2,REG
22531:              bl _setup_bitw
2254                andc r3,r3,op2
2255                sthbrx r3,MEM
2256                NEXT
2257               
2258btrl_imm:       NEXTBYTE(op2)
2259                b 1f
2260btrl_reg_mem:   lhbrx op2,REG
22611:              bl _setup_bitl
2262                andc r3,r3,op2
2263                stwbrx r3,MEM
2264                NEXT
2265               
2266btsw_imm:       NEXTBYTE(op2)
2267                b 1f
2268btsw_reg_mem:   lhbrx op2,REG
22691:              bl _setup_bitw
2270                or r3,r3,op2
2271                sthbrx r3,MEM
2272                NEXT
2273               
2274btsl_imm:       NEXTBYTE(op2)
2275                b 1f
2276btsl_reg_mem:   lhbrx op2,REG
22771:              bl _setup_bitl
2278                or r3,r3,op2
2279                stwbrx r3,MEM
2280                NEXT
2281
2282/* Bit string search instructions, only ZF is defined after these, and the
2283result value is not defined when the bit field is zero. */
2284bsfw:           lhbrx result,MEM
2285                SET_FLAGS(FLAGS_BSRCH(W))
2286                neg r3,result
2287                cmpwi cr6,result,0              # sets ZF
2288                and r3,r3,result                # keep only LSB
2289                cntlzw r3,r3
2290                subfic r3,r3,31
2291                sthbrx r3,REG
2292                NEXT
2293
2294bsfl:           lwbrx result,MEM
2295                SET_FLAGS(FLAGS_BSRCH(L))
2296                neg r3,result
2297                cmpwi cr6,result,0              # sets ZF
2298                and r3,r3,result                # keep only LSB
2299                cntlzw r3,r3
2300                subfic r3,r3,31
2301                stwbrx r3,REG
2302                NEXT
2303
2304bsrw:           lhbrx result,MEM
2305                SET_FLAGS(FLAGS_BSRCH(W))
2306                cntlzw r3,result
2307                cmpwi cr6,result,0
2308                subfic r3,r3,31
2309                sthbrx r3,REG
2310                NEXT
2311
2312bsrl:           lwbrx result,MEM
2313                SET_FLAGS(FLAGS_BSRCH(L))
2314                cntlzw r3,result
2315                cmpwi cr6,result,0
2316                subfic r3,r3,31
2317                stwbrx r3,REG
2318                NEXT
2319
2320/* Unconditional jumps, first the indirect than relative */
2321jmpw:           lhbrx eip,MEM
2322                lbzux opcode,eip,csb
2323                GOTNEXT
2324
2325jmpl:           lwbrx eip,MEM
2326                lbzux opcode,eip,csb
2327                GOTNEXT
2328
2329sjmp_w:         lbz r3,1(eip)
2330                sub eip,eip,csb
2331                addi eip,eip,2                  # EIP after instruction
2332                extsb r3,r3
2333                add eip,eip,r3
2334                clrlwi eip,eip,16               # module 64k
2335                lbzux opcode,eip,csb
2336                GOTNEXT
2337
2338jmp_w:          lhbrx r3,eip,one                # eip now off by 3
2339                sub eip,eip,csb
2340                addi r3,r3,3                    # compensate
2341                add eip,eip,r3
2342                clrlwi eip,eip,16
2343                lbzux opcode,eip,csb
2344                GOTNEXT
2345
2346sjmp_l:         lbz r3,1(eip)
2347                addi eip,eip,2
2348                extsb r3,r3
2349                lbzux opcode,eip,r3
2350                GOTNEXT
2351
2352jmp_l:          lwbrx r3,eip,one                # Simple
2353                addi eip,eip,5
2354                lbzux opcode,eip,r3
2355                GOTNEXT
2356
2357/*  The conditional jumps: although it should not happen,
2358byte relative jumps (sjmp) may wrap around in 16 bit mode */
2359       
2360#define NOTTAKEN_S lbzu opcode,2(eip); GOTNEXT
2361#define NOTTAKEN_W lbzu opcode,3(eip); GOTNEXT
2362#define NOTTAKEN_L lbzu opcode,5(eip); GOTNEXT
2363
2364#define CONDJMP(cond, eval, flag) \
2365sj##cond##_w:   EVAL_##eval; bt flag,sjmp_w; NOTTAKEN_S; \
2366j##cond##_w:    EVAL_##eval; bt flag,jmp_w; NOTTAKEN_W; \
2367sj##cond##_l:   EVAL_##eval; bt flag,sjmp_l; NOTTAKEN_S; \
2368j##cond##_l:    EVAL_##eval; bt flag,jmp_l; NOTTAKEN_L; \
2369sjn##cond##_w:  EVAL_##eval; bf flag,sjmp_w; NOTTAKEN_S; \
2370jn##cond##_w:   EVAL_##eval; bf flag,jmp_w; NOTTAKEN_W; \
2371sjn##cond##_l:  EVAL_##eval; bf flag,sjmp_l; NOTTAKEN_S; \
2372jn##cond##_l:   EVAL_##eval; bf flag,jmp_l; NOTTAKEN_L
2373
2374                CONDJMP(o, OF, OF)
2375                CONDJMP(c, CF, CF)
2376                CONDJMP(z, ZF, ZF)
2377                CONDJMP(a, ABOVE, ABOVE)
2378                CONDJMP(s, SF, SF)
2379                CONDJMP(p, PF, PF)
2380                CONDJMP(g, SIGNED, SGT)
2381                CONDJMP(l, SIGNED, SLT)
2382
2383jcxz_w:         lhz r3,CX(state); cmpwi r3,0; beq- sjmp_w; NOTTAKEN_S
2384jcxz_l:         lhz r3,CX(state); cmpwi r3,0; beq- sjmp_l; NOTTAKEN_S
2385jecxz_w:        lwz r3,ECX(state); cmpwi r3,0; beq- sjmp_w; NOTTAKEN_S
2386jecxz_l:        lwz r3,ECX(state); cmpwi r3,0; beq- sjmp_l; NOTTAKEN_S
2387
2388/* Note that loop is somewhat strange, the data size attribute gives
2389the size of eip, and the address size whether the counter is cx or ecx.
2390This is the same for jcxz/jecxz. */
2391       
2392loopw_w:        li opreg,CX
2393                lhbrx r0,REG
2394                sub. r0,r0,one
2395                sthbrx r0,REG
2396                bne+ sjmp_w
2397                NOTTAKEN_S
2398       
2399loopl_w:        li opreg,ECX
2400                lwbrx r0,REG
2401                sub. r0,r0,one
2402                stwbrx r0,REG
2403                bne+ sjmp_w
2404                NOTTAKEN_S
2405       
2406loopw_l:        li opreg,CX
2407                lhbrx r0,REG
2408                sub. r0,r0,one
2409                sthbrx r0,REG
2410                bne+ sjmp_l
2411                NOTTAKEN_S
2412       
2413loopl_l:        li opreg,ECX
2414                lwbrx r0,REG
2415                sub. r0,r0,one
2416                stwbrx r0,REG
2417                bne+ sjmp_l
2418                NOTTAKEN_S
2419       
2420loopzw_w:       li opreg,CX
2421                lhbrx r0,REG
2422                EVAL_ZF
2423                sub. r0,r0,one
2424                sthbrx r0,REG
2425                bf ZF,1f
2426                bne+ sjmp_w
24271:              NOTTAKEN_S
2428       
2429loopzl_w:       li opreg,ECX
2430                lwbrx r0,REG
2431                EVAL_ZF
2432                sub. r3,r3,one
2433                stwbrx r3,REG
2434                bf ZF,1f
2435                bne+ sjmp_w
24361:              NOTTAKEN_S
2437       
2438loopzw_l:       li opreg,CX
2439                lhbrx r0,REG
2440                EVAL_ZF
2441                sub. r0,r0,one
2442                sthbrx r0,REG
2443                bf ZF,1f
2444                bne+ sjmp_l
24451:              NOTTAKEN_S
2446       
2447loopzl_l:       li opreg,ECX
2448                lwbrx r0,REG
2449                EVAL_ZF
2450                sub. r0,r0,one
2451                stwbrx r0,REG
2452                bf ZF,1f
2453                bne+ sjmp_l
24541:              NOTTAKEN_S
2455       
2456loopnzw_w:      li opreg,CX
2457                lhbrx r0,REG
2458                EVAL_ZF
2459                sub. r0,r0,one
2460                sthbrx r0,REG
2461                bt ZF,1f
2462                bne+ sjmp_w
24631:              NOTTAKEN_S
2464       
2465loopnzl_w:      li opreg,ECX
2466                lwbrx r0,REG
2467                EVAL_ZF
2468                sub. r0,r0,one
2469                stwbrx r0,REG
2470                bt ZF,1f
2471                bne+ sjmp_w
24721:              NOTTAKEN_S
2473       
2474loopnzw_l:      li opreg,CX
2475                lhbrx r0,REG
2476                EVAL_ZF
2477                sub. r0,r0,one
2478                sthbrx r0,REG
2479                bt ZF,1f
2480                bne+ sjmp_l
24811:              NOTTAKEN_S
2482       
2483loopnzl_l:      li opreg,ECX
2484                lwbrx r0,REG
2485                EVAL_ZF
2486                sub. r0,r0,one
2487                stwbrx r0,REG
2488                bt ZF,1f
2489                bne+ sjmp_l
24901:              NOTTAKEN_S
2491
2492/* Memory indirect calls are rare enough to limit code duplication */   
2493callw_sp_mem:   lhbrx r3,MEM
2494                sub r4,eip,csb
2495                addi r4,r4,1                    # r4 is now return address
2496                b 1f
2497                .equ calll_sp_mem, unimpl
2498
2499callw_sp:       lhbrx r3,eip,one
2500                sub r4,eip,csb
2501                addi r4,r4,3                    # r4 is return address
2502                add r3,r4,r3
25031:              clrlwi eip,r3,16
2504                li r5,SP
2505                lhbrx r6,state,r5               # get sp
2506                addi r6,r6,-2
2507                lbzux opcode,eip,csb
2508                sthbrx r6,state,r5              # update sp
2509                clrlwi r6,r6,16
2510                sthbrx r4,ssb,r6                # push return address
2511                GOTNEXT
2512                .equ calll_sp, unimpl
2513
2514retw_sp_imm:    li opreg,SP
2515                lhbrx r4,REG
2516                lhbrx r6,eip,one
2517                addi r5,r4,2
2518                lhbrx eip,ssb,r4
2519                lbzux opcode,eip,csb
2520                add r5,r5,r6
2521                sthbrx r5,REG
2522                GOTNEXT
2523
2524                .equ retl_sp_imm, unimpl
2525       
2526retw_sp:        li opreg,SP
2527                lhbrx r4,REG
2528                addi r5,r4,2
2529                lhbrx eip,ssb,r4
2530                lbzux opcode,eip,csb
2531                sthbrx r5,REG
2532                GOTNEXT
2533
2534                .equ retl_sp, unimpl
2535
2536/* Enter is a mess, and the description in Intel documents is actually wrong
2537 * in most revisions (all PPro/PII I have but the old Pentium is Ok) !
2538 */     
2539               
2540enterw_sp:      lhbrx r0,eip,one                # Stack space to allocate
2541                li opreg,SP
2542                lhbrx r3,REG                    # SP
2543                li r7,BP
2544                lbzu r4,3(eip)                  # nesting level
2545                addi r3,r3,-2
2546                lhbrx r5,state,r7               # Original BP
2547                clrlwi r3,r3,16
2548                sthbrx r5,ssb,r3                # Push BP
2549                andi. r4,r4,31                  # modulo 32 and test
2550                mr r6,r3                        # Save frame pointer to temp
2551                beq 3f
2552                mtctr r4                        # iterate level-1 times
2553                b 2f
25541:              addi r5,r5,-2                   # copy list of frame pointers
2555                clrlwi r5,r5,16
2556                lhzx r4,ssb,r5
2557                addi r3,r3,-2
2558                clrlwi r3,r3,16
2559                sthx r4,ssb,r3
25602:              bdnz 1b
2561                addi r3,r3,-2                   # save current frame pointer
2562                clrlwi r3,r3,16
2563                sthbrx r6,ssb,r3
25643:              sthbrx r6,state,r7              # New BP
2565                sub r3,r3,r0                   
2566                sthbrx r3,REG                   # Save new stack pointer
2567                NEXT
2568
2569                .equ enterl_sp, unimpl
2570
2571leavew_sp:      li opreg,BP
2572                lhbrx r3,REG                    # Stack = BP
2573                addi r4,r3,2                    #
2574                lhzx r3,ssb,r3
2575                li opreg,SP
2576                sthbrx r4,REG                   # New Stack
2577                sth r3,BP(state)                # Popped BP
2578                NEXT
2579                       
2580                .equ leavel_sp, unimpl
2581
2582/* String instructions: first a generic setup routine, which exits early
2583if there is a repeat prefix with a count of 0 */
2584#define STRINGSRC base,offset
2585#define STRINGDST esb,opreg
2586
2587_setup_stringw: li offset,SI                    #
2588                rlwinm. r3,opcode,19,0,1        # lt=repnz, gt= repz, eq none
2589                li opreg,DI
2590                lhbrx offset,state,offset       # load si
2591                li r3,1                         # no repeat
2592                lhbrx opreg,state,opreg         # load di
2593                beq 1f                          # no repeat
2594                li r3,CX
2595                lhbrx r3,state,r3               # load CX
2596                cmpwi r3,0
2597                beq nop                         # early exit here !
25981:              mtctr r3                        # ctr=CX or 1
2599                li r7,1                         # stride               
2600                bflr+ DF
2601                li r7,-1                        # change stride sign
2602                blr
2603               
2604/* Ending routine to update all changed registers (goes directly to NEXT) */
2605_finish_strw:   li r4,SI
2606                sthbrx offset,state,r4          # update si
2607                li r4,DI
2608                sthbrx opreg,state,r4           # update di
2609                beq nop
2610                mfctr r3
2611                li r4,CX
2612                sthbrx r3,state,r4              # update cx
2613                NEXT
2614
2615
2616lodsb_a16:      bl _setup_stringw
26171:              lbzx r0,STRINGSRC               # [rep] lodsb
2618                add offset,offset,r7
2619                clrlwi offset,offset,16
2620                bdnz 1b
2621                stb r0,AL(state)
2622                b _finish_strw
2623               
2624lodsw_a16:      bl _setup_stringw
2625                slwi r7,r7,1
26261:              lhzx r0,STRINGSRC               # [rep] lodsw
2627                add offset,offset,r7
2628                clrlwi offset,offset,16
2629                bdnz 1b
2630                sth r0,AX(state)
2631                b _finish_strw
2632       
2633lodsl_a16:      bl _setup_stringw
2634                slwi r7,r7,2
26351:              lwzx r0,STRINGSRC               # [rep] lodsl
2636                add offset,offset,r7
2637                clrlwi offset,offset,16
2638                bdnz 1b
2639                stw r0,EAX(state)
2640                b _finish_strw
2641       
2642stosb_a16:      bl _setup_stringw
2643                lbz r0,AL(state)
26441:              stbx r0,STRINGDST               # [rep] stosb
2645                add opreg,opreg,r7
2646                clrlwi opreg,opreg,16
2647                bdnz 1b
2648                b _finish_strw
2649       
2650stosw_a16:      bl _setup_stringw
2651                lhz r0,AX(state)
2652                slwi r7,r7,1
26531:              sthx r0,STRINGDST               # [rep] stosw
2654                add opreg,opreg,r7
2655                clrlwi opreg,opreg,16
2656                bdnz 1b
2657                b _finish_strw
2658       
2659stosl_a16:      bl _setup_stringw
2660                lwz r0,EAX(state)
2661                slwi r7,r7,2
26621:              stwx r0,STRINGDST               # [rep] stosl
2663                add opreg,opreg,r7
2664                clrlwi opreg,opreg,16
2665                bdnz 1b
2666                b _finish_strw
2667       
2668movsb_a16:      bl _setup_stringw
26691:              lbzx r0,STRINGSRC               # [rep] movsb
2670                add offset,offset,r7
2671                stbx r0,STRINGDST
2672                clrlwi offset,offset,16
2673                add opreg,opreg,r7
2674                clrlwi opreg,opreg,16
2675                bdnz 1b
2676                b _finish_strw
2677       
2678movsw_a16:      bl _setup_stringw
2679                slwi r7,r7,1
26801:              lhzx r0,STRINGSRC               # [rep] movsw
2681                add offset,offset,r7
2682                sthx r0,STRINGDST
2683                clrlwi offset,offset,16
2684                add opreg,opreg,r7
2685                clrlwi opreg,opreg,16
2686                bdnz 1b
2687                b _finish_strw
2688       
2689movsl_a16:      bl _setup_stringw
2690                slwi r7,r7,2
26911:              lwzx r0,STRINGSRC               # [rep] movsl
2692                add offset,offset,r7
2693                stwx r0,STRINGDST
2694                clrlwi offset,offset,16
2695                add opreg,opreg,r7
2696                clrlwi opreg,opreg,16
2697                bdnz 1b
2698                b _finish_strw
2699       
2700/* At least on a Pentium, repeated string I/O instructions check for
2701access port permission even if count is 0 ! So the order of the check is not
2702important. */
2703insb_a16:       li r4,DX
2704                li r3,code_insb_a16
2705                lhbrx r4,state,r4
2706                bl _check_port         
2707                bl _setup_stringw
2708                lwz base,iobase(state)
27091:              lbzx r0,base,r4                 # [rep] insb
2710                eieio
2711                stbx r0,STRINGDST
2712                add opreg,opreg,r7
2713                clrlwi opreg,opreg,16
2714                bdnz 1b
2715                b _finish_strw
2716       
2717insw_a16:       li r4,DX
2718                li r3,code_insw_a16
2719                lhbrx r4,state,r4
2720                bl _check_port         
2721                bl _setup_stringw
2722                lwz base,iobase(state)
2723                slwi r7,r7,1
27241:              lhzx r0,base,r4                 # [rep] insw
2725                eieio
2726                sthx r0,STRINGDST
2727                add opreg,opreg,r7
2728                clrlwi opreg,opreg,16
2729                bdnz 1b
2730                b _finish_strw
2731       
2732insl_a16:       li r4,DX
2733                li r3,code_insl_a16
2734                lhbrx r4,state,r4
2735                bl _check_port         
2736                bl _setup_stringw
2737                lwz base,iobase(state)
2738                slwi r7,r7,2
27391:              lwzx r0,base,r4                 # [rep] insl
2740                eieio
2741                stwx r0,STRINGDST
2742                add opreg,opreg,r7
2743                clrlwi opreg,opreg,16
2744                bdnz 1b
2745                b _finish_strw
2746       
2747outsb_a16:      li r4,DX
2748                li r3,code_outsb_a16
2749                lhbrx r4,state,r4
2750                bl _check_port         
2751                bl _setup_stringw
2752                lwz r6,iobase(state)
27531:              lbzx r0,STRINGSRC               # [rep] outsb
2754                add offset,offset,r7
2755                stbx r0,r6,r4
2756                clrlwi offset,offset,16
2757                eieio
2758                bdnz 1b
2759                b _finish_strw
2760
2761outsw_a16:      li r4,DX
2762                li r3,code_outsw_a16
2763                lhbrx r4,state,r4
2764                bl _check_port         
2765                bl _setup_stringw
2766                li r5,DX
2767                lwz r6,iobase(state)
2768                slwi r7,r7,1
27691:              lhzx r0,STRINGSRC               # [rep] outsw
2770                add offset,offset,r7
2771                sthx r0,r6,r4
2772                clrlwi offset,offset,16
2773                eieio
2774                bdnz 1b
2775                b _finish_strw
2776
2777outsl_a16:      li r4,DX
2778                li r3,code_outsl_a16
2779                lhbrx r4,state,r4
2780                bl _check_port         
2781                bl _setup_stringw
2782                lwz r6,iobase(state)
2783                slwi r7,r7,2
27841:              lwzx r0,STRINGSRC               # [rep] outsl
2785                add offset,offset,r7
2786                stwx r0,r6,r4
2787                clrlwi offset,offset,16
2788                eieio
2789                bdnz 1b
2790                b _finish_strw
2791
2792cmpsb_a16:      bl _setup_stringw
2793                SET_FLAGS(FLAGS_CMP(B))
2794                blt 3f                          # repnz prefix
27951:              lbzx op1,STRINGSRC              # [repz] cmpsb
2796                add offset,offset,r7
2797                lbzx op2,STRINGDST
2798                add opreg,opreg,r7
2799                cmplw cr4,op1,op2
2800                clrlwi offset,offset,16
2801                clrlwi opreg,opreg,16
2802                bdnzt CF+2,1b
28032:              extsb r3,op1
2804                extsb r4,op2
2805                cmpw cr6,r3,r4
2806                sub result,op1,op2
2807                b _finish_strw
2808
28093:              lbzx op1,STRINGSRC              # repnz cmpsb
2810                add offset,offset,r7
2811                lbzx op2,STRINGDST
2812                add opreg,opreg,r7
2813                cmplw cr4,op1,op2
2814                clrlwi offset,offset,16
2815                clrlwi opreg,opreg,16
2816                bdnzf CF+2,3b
2817                b 2b
2818
2819cmpsw_a16:      bl _setup_stringw
2820                SET_FLAGS(FLAGS_CMP(W))
2821                slwi r7,r7,1
2822                blt 3f                          # repnz prefix
28231:              lhbrx op1,STRINGSRC             # [repz] cmpsb
2824                add offset,offset,r7
2825                lhbrx op2,STRINGDST
2826                add opreg,opreg,r7
2827                cmplw cr4,op1,op2
2828                clrlwi offset,offset,16
2829                clrlwi opreg,opreg,16
2830                bdnzt CF+2,1b
28312:              extsh r3,op1
2832                extsh r4,op2
2833                cmpw cr6,r3,r4
2834                sub result,op1,op2
2835                b _finish_strw
2836
28373:              lhbrx op1,STRINGSRC             # repnz cmpsw
2838                add offset,offset,r7
2839                lhbrx op2,STRINGDST
2840                add opreg,opreg,r7
2841                cmplw cr4,op1,op2
2842                clrlwi offset,offset,16
2843                clrlwi opreg,opreg,16
2844                bdnzf CF+2,3b
2845                b 2b
2846
2847cmpsl_a16:      bl _setup_stringw
2848                SET_FLAGS(FLAGS_CMP(L))
2849                slwi r7,r7,2
2850                blt 3f                          # repnz prefix
28511:              lwbrx op1,STRINGSRC             # [repz] cmpsl
2852                add offset,offset,r7
2853                lwbrx op2,STRINGDST
2854                add opreg,opreg,r7
2855                cmplw cr4,op1,op2
2856                clrlwi offset,offset,16
2857                clrlwi opreg,opreg,16
2858                bdnzt CF+2,1b
28592:              cmpw cr6,op1,op2
2860                sub result,op1,op2
2861                b _finish_strw
2862
28633:              lwbrx op1,STRINGSRC             # repnz cmpsl
2864                add offset,offset,r7
2865                lwbrx op2,STRINGDST
2866                add opreg,opreg,r7
2867                cmplw cr4,op1,op2
2868                clrlwi offset,offset,16
2869                clrlwi opreg,opreg,16
2870                bdnzf CF+2,3b
2871                b 2b
2872       
2873scasb_a16:      bl _setup_stringw
2874                lbzx op1,AL,state               # AL
2875                SET_FLAGS(FLAGS_CMP(B))
2876                bgt 3f                          # repz prefix
28771:              lbzx op2,STRINGDST              # [repnz] scasb
2878                add opreg,opreg,r7
2879                cmplw cr4,op1,op2
2880                clrlwi opreg,opreg,16
2881                bdnzf CF+2,1b
28822:              extsb r3,op1
2883                extsb r4,op2
2884                cmpw cr6,r3,r4
2885                sub result,op1,op2
2886                b _finish_strw
2887
28883:              lbzx op2,STRINGDST              # repz scasb
2889                add opreg,opreg,r7
2890                cmplw cr4,op1,op2
2891                clrlwi opreg,opreg,16
2892                bdnzt CF+2,3b
2893                b 2b
2894
2895scasw_a16:      bl _setup_stringw
2896                lhbrx op1,AX,state
2897                SET_FLAGS(FLAGS_CMP(W))
2898                slwi r7,r7,1
2899                bgt 3f                          # repz prefix
29001:              lhbrx op2,STRINGDST             # [repnz] scasw
2901                add opreg,opreg,r7
2902                cmplw cr4,op1,op2
2903                clrlwi opreg,opreg,16
2904                bdnzf CF+2,1b
29052:              extsh r3,op1
2906                extsh r4,op2
2907                cmpw cr6,r3,r4
2908                sub result,op1,op2
2909                b _finish_strw
2910
29113:              lhbrx op2,STRINGDST             # repz scasw
2912                add opreg,opreg,r7
2913                cmplw cr4,op1,op2
2914                clrlwi opreg,opreg,16
2915                bdnzt CF+2,3b
2916                b 2b
2917
2918scasl_a16:      bl _setup_stringw
2919                lwbrx op1,EAX,state
2920                SET_FLAGS(FLAGS_CMP(L))
2921                slwi r7,r7,2
2922                bgt 3f                          # repz prefix
29231:              lwbrx op2,STRINGDST             # [repnz] scasl
2924                add opreg,opreg,r7
2925                cmplw cr4,op1,op2
2926                clrlwi opreg,opreg,16
2927                bdnzf CF+2,1b
29282:              cmpw cr6,op1,op2
2929                sub result,op1,op2
2930                b _finish_strw
2931
29323:              lwbrx op2,STRINGDST             # repz scasl
2933                add opreg,opreg,r7
2934                cmplw cr4,op1,op2
2935                clrlwi opreg,opreg,16
2936                bdnzt CF+2,3b
2937                b 2b
2938
2939                .equ lodsb_a32, unimpl
2940                .equ lodsw_a32, unimpl
2941                .equ lodsl_a32, unimpl
2942                .equ stosb_a32, unimpl         
2943                .equ stosw_a32, unimpl
2944                .equ stosl_a32, unimpl
2945                .equ movsb_a32, unimpl
2946                .equ movsw_a32, unimpl
2947                .equ movsl_a32, unimpl
2948                .equ insb_a32, unimpl
2949                .equ insw_a32, unimpl
2950                .equ insl_a32, unimpl
2951                .equ outsb_a32, unimpl
2952                .equ outsw_a32, unimpl
2953                .equ outsl_a32, unimpl
2954                .equ cmpsb_a32, unimpl
2955                .equ cmpsw_a32, unimpl
2956                .equ cmpsl_a32, unimpl
2957                .equ scasb_a32, unimpl
2958                .equ scasw_a32, unimpl
2959                .equ scasl_a32, unimpl
2960
2961xlatb_a16:      li offset,BX
2962                lbz r3,AL(state)
2963                lhbrx offset,offset,state
2964                add r3,r3,base
2965                lbzx r3,r3,offset
2966                stb r3,AL(state)
2967                NEXT           
2968
2969                .equ xlatb_a32, unimpl
2970
2971/*
2972 * Shift and rotates: note the oddity that rotates do not affect SF/ZF/AF/PF
2973 * but shifts do. Also testing has indicated that rotates with a count of zero
2974 * do not affect any flag. The documentation specifies this for shifts but
2975 * is more obscure for rotates. The overflow flag setting is only specified
2976 * when count is 1, otherwise OF is undefined which simplifies emulation.
2977 */
2978
2979/*
2980 * The rotates through carry are among the most difficult instructions,
2981 * they are implemented as a shift of 2*n+some bits depending on case.
2982 * First the left rotates through carry.
2983 */
2984
2985/* Byte rcl is performed on 18 bits (17 actually used) in a single register */
2986rclb_imm:       NEXTBYTE(r3)
2987                b 1f
2988rclb_cl:        lbz r3,CL(state)
2989                b 1f
2990rclb_1:         li r3,1
29911:              lbzx r0,MEM
2992                andi. r3,r3,31                  # count%32
2993                addc r4,flags,flags             # CF_IN->xer[ca]
2994                RES2CF(r6)
2995                subfe r4,result,op1
2996                mulli r5,r3,29                  # 29=ceil(256/9)
2997                CF_ROTCNT(r7)
2998                addze r6,r6
2999                CF_POL_INSERT(r0,23)
3000                srwi r5,r5,8                    # count/9
3001                rlwnm r6,r6,r7,0x100
3002                xor r0,r0,r6                    # (23)0:CF:data8
3003                rlwimi r5,r5,3,26,28            # 9*(count/9)
3004                rlwimi r0,r0,23,0,7             # CF:(data8):(14)0:CF:data8
3005                sub r3,r3,r5                    # count%9
3006                beq- nop                        # no flags changed if count 0
3007                ROTATE_FLAGS
3008                rlwnm r0,r0,r3,0x000001ff       # (23)0:NewCF:Result8
3009                rlwimi flags,r0,19,CF_VALUE
3010                stbx r0,MEM
3011                rlwimi flags,r0,18,OF_XOR       
3012                NEXT
3013
3014/* Word rcl is performed on 33 bits (CF:data16:CF:(15 MSB of data16) */
3015rclw_imm:       NEXTBYTE(r3)
3016                b 1f
3017rclw_cl:        lbz r3,CL(state)
3018                b 1f
3019rclw_1:         li r3,1
30201:              lhbrx r0,MEM
3021                andi. r3,r3,31                  # count=count%32
3022                addc r4,flags,flags
3023                RES2CF(r6)
3024                subfe r4,result,op1
3025                addi r5,r3,15                   # modulo 17: >=32 if >=17
3026                CF_ROTCNT(r7)
3027                addze r6,r6
3028                addi r7,r7,8
3029                CF_POL_INSERT(r0,15)
3030                srwi r5,r5,5                    # count/17
3031                rlwnm r6,r6,r7,0x10000
3032                rlwimi r5,r5,4,27,27            # 17*(count/17)
3033                xor r0,r0,r6                    # (15)0:CF:data16
3034                sub r3,r3,r5                    # count%17
3035                rlwinm r4,r0,15,0xffff0000      # CF:(15 MSB of data16):(16)0
3036                slw r0,r0,r3                    # New carry and MSBs
3037                rlwnm r4,r4,r3,16,31            # New LSBs
3038                beq- nop                        # no flags changed if count 0
3039                ROTATE_FLAGS
3040                add r0,r0,r4                    # result
3041                rlwimi flags,r0,11,CF_VALUE
3042                sthbrx r0,MEM
3043                rlwimi flags,r0,10,OF_XOR       
3044                NEXT
3045
3046/* Longword rcl only needs 64 bits because the maximum rotate count is 31 ! */
3047rcll_imm:       NEXTBYTE(r3)
3048                b 1f
3049rcll_cl:        lbz r3,CL(state)
3050                b 1f
3051rcll_1:         li r3,1
30521:              lwbrx r0,MEM
3053                andi. r3,r3,31                  # count=count%32
3054                addc r4,r4,flags                # ~XER[CA]
3055                RES2CF(r6)
3056                subfe r4,result,op1
3057                CF_ROTCNT(r7)
3058                addze r6,r6
3059                srwi r4,r0,1                    # 0:(31 MSB of data32)
3060                addi r7,r7,23
3061                CF_POL_INSERT(r4,0)
3062                rlwnm r6,r6,r7,0,0
3063                beq- nop                        # no flags changed if count 0
3064                subfic r5,r3,32
3065                xor r4,r4,r6
3066                ROTATE_FLAGS
3067                slw r0,r0,r3                    # New MSBs
3068                srw r5,r4,r5                    # New LSBs
3069                rlwnm r4,r4,r3,0,0              # New Carry
3070                add r0,r0,r5                    # result
3071                rlwimi flags,r4,28,CF_VALUE
3072                rlwimi flags,r0,27,OF_XOR
3073                stwbrx r0,MEM
3074                NEXT
3075
3076/* right rotates through carry are even worse because PPC only has a left
3077rotate instruction. Somewhat tough when combined with modulo 9, 17, or
307833 operation and the rules of OF and CF flag settings. */
3079/* Byte rcr is performed on 17 bits */
3080rcrb_imm:       NEXTBYTE(r3)
3081                b 1f
3082rcrb_cl:        lbz r3,CL(state)
3083                b 1f
3084rcrb_1:         li r3,1
30851:              lbzx r0,MEM
3086                andi. r3,r3,31                  # count%32
3087                addc r4,flags,flags             # cf_in->xer[ca]
3088                RES2CF(r6)
3089                mulli r5,r3,29                  # 29=ceil(256/9)
3090                subfe r4,result,op1
3091                CF_ROTCNT(r7)
3092                addze r6,r6
3093                CF_POL_INSERT(r0,23)
3094                srwi r5,r5,8                    # count/9
3095                rlwimi r0,r0,9,0x0001fe00       # (15)0:data8:0:data8
3096                rlwnm r6,r6,r7,0x100
3097                rlwimi r5,r5,3,26,28            # 9*(count/9)
3098                xor r0,r0,r6                    # (15)0:data8:CF:data8
3099                sub r3,r3,r5                    # count%9
3100                beq- nop                        # no flags changed if count 0
3101                ROTATE_FLAGS
3102                srw r0,r0,r3                    # (23)junk:NewCF:Result8
3103                rlwimi flags,r0,19,CF_VALUE|OF_XOR
3104                stbx r0,MEM
3105                NEXT
3106
3107/* Word rcr is a 33 bit right shift with a quirk, because the 33rd bit
3108is only needed when the rotate count is 16 and rotating left or right
3109by 16 a 32 bit quantity is the same ! */       
3110rcrw_imm:       NEXTBYTE(r3)
3111                b 1f
3112rcrw_cl:        lbz r3,CL(state)
3113                b 1f
3114rcrw_1:         li r3,1
31151:              lhbrx r0,MEM
3116                andi. r3,r3,31                  # count%32
3117                addc r4,flags,flags             # cf_in->xer[ca]
3118                RES2CF(r6)
3119                subfe r4,result,op1
3120                addi r5,r3,15                   # >=32 if >=17
3121                CF_ROTCNT(r7)
3122                addze r6,r6
3123                addi r7,r7,8
3124                CF_POL_INSERT(r0,15)
3125                srwi r5,r5,5                    # count/17
3126                rlwnm r6,r6,r7,0x10000
3127                rlwinm r7,r0,16,0x01            # MSB of data16
3128                rlwimi r0,r0,17,0xfffe0000      # (15 MSB of data16):0:data16
3129                rlwimi r5,r5,4,27,27            # 17*(count/17)
3130                xor r0,r0,r6                    # (15 MSB of data16):CF:data16
3131                sub r3,r3,r5                    # count%17
3132                beq- nop                        # no flags changed if count 0
3133                srw r0,r0,r3                    # shift right
3134                rlwnm r7,r7,r3,0x10000          # just in case count=16
3135                ROTATE_FLAGS
3136                add r0,r0,r7                    # junk15:NewCF:result16
3137                rlwimi flags,r0,11,CF_VALUE|OF_XOR
3138                sthbrx r0,MEM
3139                NEXT
3140
3141/* Longword rcr need only 64 bits since the rotate count is limited to 31 */
3142rcrl_imm:       NEXTBYTE(r3)
3143                b 1f
3144rcrl_cl:        lbz r3,CL(state)
3145                b 1f
3146rcrl_1:         li r3,1
31471:              lwbrx r0,MEM
3148                andi. r3,r3,31                  # count%32
3149                addc r4,flags,flags
3150                RES2CF(r6)
3151                subfe r4,result,op1
3152                CF_ROTCNT(r7)
3153                slwi r4,r0,1                    # (31MSB of data32):0
3154                addze r6,r6
3155                addi r7,r7,24
3156                CF_POL_INSERT(r4,31)
3157                rlwnm r6,r6,r7,0x01
3158                beq- nop                        # no flags changed if count 0
3159                subfic r7,r3,32
3160                xor r4,r4,r6
3161                srw r0,r0,r3                    # Result LSB
3162                slw r5,r4,r7                    # Result MSB
3163                srw r4,r4,r3                    # NewCF in LSB
3164                add r0,r0,r5                    # result
3165                rlwimi flags,r4,27,CF_VALUE
3166                stwbrx r0,MEM
3167                rlwimi flags,r0,27,OF_XOR
3168                NEXT
3169
3170/* After the rotates through carry, normal rotates are so simple ! */
3171rolb_imm:       NEXTBYTE(r3)
3172                b 1f
3173rolb_cl:        lbz r3,CL(state)
3174                b 1f
3175rolb_1:         li r3,1
31761:              lbzx r0,MEM
3177                andi. r4,r3,31                  # count%32 == 0 ?
3178                clrlwi r3,r3,29                 # count%8
3179                rlwimi r0,r0,24,0xff000000      # replicate for shift in
3180                beq- nop                        # no flags changed if count 0
3181                ROTATE_FLAGS
3182                rotlw r0,r0,r3         
3183                rlwimi flags,r0,27,CF_VALUE     # New CF
3184                stbx r0,MEM
3185                rlwimi flags,r0,26,OF_XOR       # New OF (CF xor MSB)
3186                NEXT
3187
3188rolw_imm:       NEXTBYTE(r3)
3189                b 1f
3190rolw_cl:        lbz r3,CL(state)
3191                b 1f
3192rolw_1:         li r3,1
31931:              lhbrx r0,MEM
3194                andi. r3,r3,31
3195                rlwimi r0,r0,16,0,15            # duplicate
3196                beq- nop                        # no flags changed if count 0
3197                ROTATE_FLAGS
3198                rotlw r0,r0,r3                  # result word duplicated
3199                rlwimi flags,r0,27,CF_VALUE     # New CF
3200                sthbrx r0,MEM
3201                rlwimi flags,r0,26,OF_XOR       # New OF (CF xor MSB)
3202                NEXT
3203
3204roll_imm:       NEXTBYTE(r3)
3205                b 1f
3206roll_cl:        lbz r3,CL(state)
3207                b 1f
3208roll_1:         li r3,1
32091:              lwbrx r0,MEM
3210                andi. r3,r3,31
3211                beq- nop                        # no flags changed if count 0
3212                ROTATE_FLAGS
3213                rotlw r0,r0,r3                  # result
3214                rlwimi flags,r0,27,CF_VALUE     # New CF
3215                stwbrx r0,MEM
3216                rlwimi flags,r0,26,OF_XOR       # New OF (CF xor MSB)
3217                NEXT
3218
3219rorb_imm:       NEXTBYTE(r3)
3220                b 1f
3221rorb_cl:        lbz r3,CL(state)
3222                b 1f
3223rorb_1:         li r3,1
32241:              lbzx r0,MEM
3225                andi. r4,r3,31                  # count%32 == 0 ?
3226                clrlwi r3,r3,29                 # count%8
3227                rlwimi r0,r0,8,0x0000ff00       # replicate for shift in
3228                beq- nop                        # no flags changed if count 0
3229                ROTATE_FLAGS
3230                srw r0,r0,r3
3231                rlwimi flags,r0,20,CF_VALUE
3232                stbx r0,MEM
3233                rlwimi flags,r0,19,OF_XOR
3234                NEXT
3235
3236rorw_imm:       NEXTBYTE(r3)
3237                b 1f
3238rorw_cl:        lbz r3,CL(state)
3239                b 1f
3240rorw_1:         li r3,1
32411:              lhbrx r0,MEM
3242                andi. r4,r3,31
3243                clrlwi r3,r3,28                 # count %16
3244                rlwimi r0,r0,16,0xffff0000      # duplicate
3245                beq- nop                        # no flags changed if count 0
3246                ROTATE_FLAGS
3247                srw r0,r0,r3                    # junk16:result16
3248                rlwimi flags,r0,12,CF_VALUE
3249                sthbrx r0,MEM
3250                rlwimi flags,r0,11,OF_XOR
3251                NEXT
3252
3253rorl_imm:       NEXTBYTE(r3)
3254                b 1f
3255rorl_cl:        lbz r3,CL(state)
3256                b 1f
3257rorl_1:         li r3,1
32581:              lwbrx r0,MEM
3259                andi. r4,r3,31
3260                neg r3,r3
3261                beq- nop                        # no flags changed if count 0
3262                ROTATE_FLAGS
3263                rotlw r0,r0,r3                  # result
3264                rlwimi flags,r0,28,CF_VALUE
3265                stwbrx r0,MEM
3266                rlwimi flags,r0,27,OF_XOR
3267                NEXT
3268
3269/* Right arithmetic shifts: they clear OF whenever count!=0 */
3270#define SAR_FLAGS       CF_ZERO|OF_ZERO|RESL
3271sarb_imm:       NEXTBYTE(r3)
3272                b 1f
3273sarb_cl:        lbz r3,CL(state)
3274                b 1f
3275sarb_1:         li r3,1
32761:              lbzx r4,MEM
3277                andi. r3,r3,31
3278                addi r5,r3,-1
3279                extsb r4,r4
3280                beq- nop                        # no flags changed if count 0
3281                SET_FLAGS(SAR_FLAGS)
3282                sraw result,r4,r3
3283                srw r5,r4,r5
3284                stbx result,MEM
3285                rlwimi flags,r5,27,CF_VALUE
3286                NEXT
3287
3288sarw_imm:       NEXTBYTE(r3)
3289                b 1f
3290sarw_cl:        lbz r3,CL(state)
3291                b 1f
3292sarw_1:         li r3,1
32931:              lhbrx r4,MEM
3294                andi. r3,r3,31
3295                addi r5,r3,-1
3296                extsh r4,r4
3297                beq- nop                        # no flags changed if count 0
3298                SET_FLAGS(SAR_FLAGS)
3299                sraw result,r4,r3
3300                srw r5,r4,r5
3301                sthbrx result,MEM
3302                rlwimi flags,r5,27,CF_VALUE
3303                NEXT
3304
3305sarl_imm:       NEXTBYTE(r3)
3306                b 1f
3307sarl_cl:        lbz r3,CL(state)
3308                b 1f
3309sarl_1:         li r3,1
33101:              lwbrx r4,MEM
3311                andi. r3,r3,31
3312                addi r5,r3,-1
3313                beq- nop                        # no flags changed if count 0
3314                SET_FLAGS(SAR_FLAGS)
3315                sraw result,r4,r3
3316                srw r5,r4,r5
3317                stwbrx result,MEM
3318                rlwimi flags,r5,27,CF_VALUE
3319                NEXT
3320
3321/* Left shifts are quite easy: they use the flag mechanism of add */
3322shlb_imm:       NEXTBYTE(r3)
3323                b 1f
3324shlb_cl:        lbz r3,CL(state)
3325                b 1f
3326shlb_1:         li r3,1
33271:              andi. r3,r3,31
3328                beq- nop                        # no flags changed if count 0
3329                lbzx op1,MEM
3330                SET_FLAGS(FLAGS_ADD(B))
3331                slw result,op1,r3
3332                addi op2,op1,0                  # for OF computation only !
3333                stbx result,MEM
3334                NEXT
3335
3336shlw_imm:       NEXTBYTE(r3)
3337                b 1f
3338shlw_cl:        lbz r3,CL(state)
3339                b 1f
3340shlw_1:         li r3,1
33411:              andi. r3,r3,31
3342                beq- nop                        # no flags changed if count 0
3343                lhbrx op1,MEM
3344                SET_FLAGS(FLAGS_ADD(W))
3345                slw result,op1,r3
3346                addi op2,op1,0                  # for OF computation only !
3347                sthbrx result,MEM
3348                NEXT
3349
3350/* That one may be wrong */
3351shll_imm:       NEXTBYTE(r3)
3352                b 1f
3353shll_cl:        lbz r3,CL(state)
3354                b 1f
3355shll_1:         li r3,1
33561:              andi. r3,r3,31
3357                beq- nop                        # no flags changed if count 0
3358                lwbrx op1,MEM
3359                addi r4,r3,-1
3360                SET_FLAGS(FLAGS_ADD(L))
3361                slw result,op1,r3
3362                addi op2,op1,0                  # for OF computation only !
3363                slw op1,op1,r4                  # for CF computation
3364                stwbrx result,MEM
3365                NEXT
3366
3367/* Right shifts are quite complex, because of funny flag rules ! */
3368shrb_imm:       NEXTBYTE(r3)
3369                b 1f
3370shrb_cl:        lbz r3,CL(state)
3371                b 1f
3372shrb_1:         li r3,1
33731:              andi. r3,r3,31
3374                beq- nop                        # no flags changed if count 0
3375                lbzx op1,MEM
3376                addi r4,r3,-1
3377                SET_FLAGS(FLAGS_SHR(B))
3378                srw result,op1,r3
3379                srw r4,op1,r4
3380                li op2,-1                       # for OF computation only !
3381                stbx result,MEM
3382                rlwimi flags,r4,27,CF_VALUE     # Set CF
3383                NEXT
3384
3385shrw_imm:       NEXTBYTE(r3)
3386                b 1f
3387shrw_cl:        lbz r3,CL(state)
3388                b 1f
3389shrw_1:         li r3,1
33901:              andi. r3,r3,31
3391                beq- nop                        # no flags changed if count 0
3392                lhbrx op1,MEM
3393                addi r4,r3,-1
3394                SET_FLAGS(FLAGS_SHR(W))
3395                srw result,op1,r3
3396                srw r4,op1,r4
3397                li op2,-1                       # for OF computation only !
3398                sthbrx result,MEM
3399                rlwimi flags,r4,27,CF_VALUE     # Set CF
3400                NEXT
3401
3402shrl_imm:       NEXTBYTE(r3)
3403                b 1f
3404shrl_cl:        lbz r3,CL(state)
3405                b 1f
3406shrl_1:         li r3,1
34071:              andi. r3,r3,31
3408                beq- nop                        # no flags changed if count 0
3409                lwbrx op1,MEM
3410                addi r4,r3,-1
3411                SET_FLAGS(FLAGS_SHR(L))
3412                srw result,op1,r3
3413                srw r4,op1,r4
3414                li op2,-1                       # for OF computation only !
3415                stwbrx result,MEM
3416                rlwimi flags,r4,27,CF_VALUE     # Set CF
3417                NEXT
3418
3419/* Double length shifts, shldw uses FLAGS_ADD for simplicity */
3420shldw_imm:      NEXTBYTE(r3)
3421                b 1f
3422shldw_cl:       lbz r3,CL(state)
34231:              andi. r3,r3,31
3424                beq- nop
3425                lhbrx op1,MEM
3426                SET_FLAGS(FLAGS_ADD(W))
3427                lhbrx op2,REG
3428                rlwimi op1,op2,16,0,15          # op2:op1
3429                addi op2,op1,0
3430                rotlw result,op1,r3
3431                sthbrx result,MEM
3432                NEXT
3433
3434shldl_imm:      NEXTBYTE(r3)
3435                b 1f
3436shldl_cl:       lbz r3,CL(state)
34371:              andi. r3,r3,31
3438                beq- nop
3439                lwbrx op1,MEM
3440                SET_FLAGS(FLAGS_DBLSH(L))
3441                lwbrx op2,REG
3442                subfic r4,r3,32
3443                slw result,op1,r3
3444                srw r4,op2,r4
3445                rotlw r3,op1,r3
3446                or result,result,r4
3447                addi op2,op1,0
3448                rlwimi flags,r3,27,CF_VALUE
3449                stwbrx result,MEM
3450                NEXT
3451
3452shrdw_imm:      NEXTBYTE(r3)
3453                b 1f
3454shrdw_cl:       lbz r3,CL(state)
34551:              andi. r3,r3,31
3456                beq- nop
3457                lhbrx op1,MEM
3458                SET_FLAGS(FLAGS_DBLSH(W))
3459                lhbrx op2,REG
3460                addi r4,r3,-1
3461                rlwimi op1,op2,16,0,15          # op2:op1
3462                addi op2,op1,0
3463                srw result,op1,r3
3464                srw r4,op1,r4
3465                sthbrx result,MEM
3466                rlwimi flags,r4,27,CF_VALUE
3467                NEXT
3468
3469shrdl_imm:      NEXTBYTE(r3)
3470                b 1f
3471shrdl_cl:       lbz r3,CL(state)
34721:              andi. r3,r3,31
3473                beq- nop
3474                lwbrx op1,MEM
3475                SET_FLAGS(FLAGS_DBLSH(L))
3476                lwbrx op2,REG
3477                subfic r4,r3,32
3478                srw result,op1,r3
3479                addi r3,r3,-1
3480                slw r4,op2,r4
3481                srw r3,op1,r3
3482                or result,result,r4
3483                addi op2,op1,0
3484                rlwimi flags,r3,27,CF_VALUE
3485                stwbrx result,MEM
3486                NEXT
3487
3488/* One operand multiplies: with result double the operand size, unsigned */
3489mulb:           lbzx op2,MEM
3490                lbz op1,AL(state)
3491                mullw result,op1,op2
3492                SET_FLAGS(FLAGS_MUL)
3493                subfic r3,result,255
3494                sthbrx result,AX,state
3495                rlwimi flags,r3,0,CF_VALUE|OF_VALUE
3496                NEXT
3497
3498mulw:           lhbrx op2,MEM
3499                lhbrx op1,AX,state
3500                mullw result,op1,op2
3501                SET_FLAGS(FLAGS_MUL)
3502                li r4,DX
3503                srwi r3,result,16
3504                sthbrx result,AX,state
3505                neg r5,r3
3506                sthbrx r3,r4,state              # DX
3507                rlwimi flags,r5,0,CF_VALUE|OF_VALUE
3508                NEXT
3509
3510mull:           lwbrx op2,MEM
3511                lwbrx op1,EAX,state
3512                mullw result,op1,op2
3513                mulhwu. r3,op1,op2
3514                SET_FLAGS(FLAGS_MUL)
3515                stwbrx result,EAX,state
3516                li r4,EDX
3517                stwbrx r3,r4,state
3518                beq+ nop
3519                oris flags,flags,(CF_SET|OF_SET)>>16
3520                NEXT
3521
3522/* One operand multiplies: with result double the operand size, signed */
3523imulb:          lbzx op2,MEM
3524                extsb op2,op2
3525                lbz op1,AL(state)
3526                extsb op1,op1
3527                mullw result,op1,op2
3528                SET_FLAGS(FLAGS_MUL)
3529                extsb r3,result
3530                sthbrx result,AX,state
3531                cmpw r3,result
3532                beq+ nop
3533                oris flags,flags,(CF_SET|OF_SET)>>16
3534                NEXT
3535
3536imulw:          lhbrx op2,MEM
3537                extsh op2,op2
3538                lhbrx op1,AX,state
3539                extsh op1,op1
3540                mullw result,op1,op2
3541                SET_FLAGS(FLAGS_MUL)
3542                li r3,DX
3543                extsh r4,result
3544                srwi r5,result,16
3545                sthbrx result,AX,state
3546                cmpw r4,result
3547                sthbrx r5,r3,state
3548                beq+ nop
3549                oris flags,flags,(CF_SET|OF_SET)>>16
3550                NEXT
3551
3552imull:          lwbrx op2,MEM
3553                SET_FLAGS(FLAGS_MUL)
3554                lwbrx op1,EAX,state
3555                li r3,EDX
3556                mulhw r4,op1,op2
3557                mullw result,op1,op2
3558                stwbrx r4,r3,state
3559                srawi r3,result,31
3560                cmpw r3,r4
3561                beq+ nop
3562                oris flags,flags,(CF_SET|OF_SET)>>16
3563                NEXT
3564
3565/* Other multiplies */
3566imulw_mem_reg:  lhbrx op2,REG
3567                extsh op2,op2
3568                b 1f
3569
3570imulw_imm:      NEXTWORD(op2)
3571                extsh op2,op2
3572                b 1f
3573
3574imulw_imm8:     NEXTBYTE(op2)
3575                extsb op2,op2
35761:              lhbrx op1,MEM
3577                extsh op1,op1
3578                mullw result,op1,op2
3579                SET_FLAGS(FLAGS_MUL)
3580                extsh r3,result
3581                sthbrx result,REG
3582                cmpw r3,result
3583                beq+ nop
3584                oris flags,flags,(CF_SET|OF_SET)>>16
3585                NEXT                    # SF/ZF/AF/PF undefined !
3586
3587imull_mem_reg:  lwbrx op2,REG
3588                b 1f
3589
3590imull_imm:      NEXTDWORD(op2)
3591                b 1f
3592
3593imull_imm8:     NEXTBYTE(op2)
3594                extsb op2,op2
35951:              lwbrx op1,MEM
3596                mullw result,op1,op2
3597                SET_FLAGS(FLAGS_MUL)
3598                mulhw r3,op1,op2
3599                srawi r4,result,31
3600                stwbrx result,REG
3601                cmpw r3,r4
3602                beq+ nop
3603                oris flags,flags,(CF_SET|OF_SET)>>16
3604                NEXT                    # SF/ZF/AF/PF undefined !
3605
3606/* aad is indeed a multiply */
3607aad:            NEXTBYTE(r3)
3608                lbz op1,AH(state)
3609                lbz op2,AL(state)
3610                mullw result,op1,r3             # AH*imm
3611                SET_FLAGS(FLAGS_LOG(B))         # SF/ZF/PF from result
3612                add result,result,op2           # AH*imm+AL
3613                slwi r3,result,8
3614                sth r3,AX(state)                        # AH=0
3615                NEXT                            # OF/AF/CF undefined
3616
3617/* Unsigned divides: we may destroy all flags */
3618divb:           lhbrx r4,AX,state
3619                lbzx r3,MEM
3620                srwi r5,r4,8
3621                cmplw r5,r3
3622                bnl- _divide_error
3623                divwu r5,r4,r3
3624                mullw r3,r5,r3
3625                sub r3,r4,r3
3626                stb r5,AL(state)
3627                stb r3,AH(state)
3628                NEXT
3629
3630divw:           li opreg,DX
3631                lhbrx r4,AX,state
3632                lhbrx r5,REG
3633                lhbrx r3,MEM
3634                insrwi r4,r5,16,0
3635                cmplw r5,r3
3636                bnl- _divide_error
3637                divwu r5,r4,r3
3638                mullw r3,r5,r3
3639                sub r3,r4,r3
3640                sthbrx r5,AX,state
3641                sthbrx r3,REG
3642                NEXT
3643
3644divl:           li opreg,EDX                    # Not yet fully implemented
3645                lwbrx r3,MEM
3646                lwbrx r4,REG
3647                lwbrx r5,EAX,state
3648                cmplw r4,r3
3649                bnl- _divide_error
3650                cmplwi r4,0
3651                bne- 1f
3652                divwu r4,r5,r3
3653                mullw r3,r4,r3
3654                stwbrx r4,EAX,state
3655                sub r3,r5,r3
3656                stwbrx r3,REG
3657                NEXT
3658/* full implementation of 64:32 unsigned divide, slow but rarely used */
36591:              bl _div_64_32
3660                stwbrx r5,EAX,state
3661                stwbrx r4,REG
3662                NEXT
3663/*
3664 * Divide r4:r5 by r3, quotient in r5, remainder in r4.
3665 * The algorithm is stupid because it won't be used very often.
3666 */
3667_div_64_32:     li r7,32
3668                mtctr r7
36691:              cmpwi r4,0                      # always subtract in case
3670                addc r5,r5,r5                   # MSB is set
3671                adde r4,r4,r4
3672                blt 2f
3673                cmplw r4,r3
3674                blt 3f
36752:              sub r4,r4,r3
3676                addi r5,r5,1
36773:              bdnz 1b
3678
3679/* Signed divides: we may destroy all flags */
3680idivb:          lbzx r3,MEM
3681                lhbrx r4,AX,state
3682                cmpwi r3,0
3683                beq- _divide_error
3684                divw r5,r4,r3
3685                extsb r7,r5
3686                mullw r3,r5,r3
3687                cmpw r5,r7
3688                sub r3,r4,r3
3689                bne- _divide_error
3690                stb r5,AL(state)
3691                stb r3,AH(state)
3692                NEXT
3693
3694idivw:          li opreg,DX
3695                lhbrx r4,AX,state
3696                lhbrx r5,REG
3697                lhbrx r3,MEM
3698                insrwi r4,r5,16,0
3699                cmpwi r3,0
3700                beq- _divide_error
3701                divw r5,r4,r3
3702                extsh r7,r5
3703                mullw r3,r5,r3
3704                cmpw r5,r7
3705                sub r3,r4,r3
3706                bne- _divide_error
3707                sthbrx r5,AX,state
3708                sthbrx r3,REG
3709                NEXT
3710
3711idivl:          li opreg,EDX                    # Not yet fully implemented
3712                lwbrx r3,MEM
3713                lwbrx r5,EAX,state
3714                cmpwi cr1,r3,0
3715                lwbrx r4,REG
3716                srwi  r7,r5,31
3717                beq- _divide_error
3718                add. r7,r7,r4
3719                bne- 1f                         # EDX not sign extension of EAX
3720                divw r4,r5,r3
3721                xoris r7,r5,0x8000              # only overflow case is
3722                orc. r7,r7,r3                   # 0x80000000 divided by -1
3723                mullw r3,r4,r3
3724                beq- _divide_error
3725                stwbrx r4,EAX,state
3726                sub r3,r5,r3
3727                stwbrx r3,REG
3728                NEXT
3729
3730/* full 64 by 32 signed divide, checks for overflow might be right now */
37311:              srawi r6,r4,31                  # absolute value of r4:r5
3732                srawi r0,r3,31                  # absolute value of r3
3733                xor r5,r5,r6
3734                xor r3,r3,r0
3735                subfc r5,r6,r5
3736                xor r4,r4,r6
3737                sub r3,r3,r0
3738                subfe r4,r6,r4
3739                xor r0,r0,r6                    # sign of result
3740                cmplw r4,r3                     # coarse overflow detection
3741                bnl- _divide_error              # (probably not necessary)
3742                bl _div_64_32
3743                xor r5,r5,r0                    # apply sign to result
3744                sub r5,r5,r0
3745                xor. r7,r0,r5                   # wrong sign: overflow
3746                xor r4,r4,r6                    # apply sign to remainder
3747                blt- _divide_error
3748                stwbrx r5,EAX,state
3749                sub r4,r4,r6
3750                stwbrx r4,REG
3751                NEXT
3752
3753/* aam is indeed a divide */
3754aam:            NEXTBYTE(r3)
3755                lbz r4,AL(state)
3756                cmpwi r3,0
3757                beq- _divide_error              # zero divide
3758                divwu op2,r4,r3                 # AL/imm8
3759                SET_FLAGS(FLAGS_LOG(B))         # SF/ZF/PF from AL
3760                mullw r3,op2,r3                 # (AL/imm8)*imm8
3761                stb op2,AH(state)
3762                sub result,r4,r3                # AL-imm8*(AL/imm8)
3763                stb result,AL(state)
3764                NEXT                            # OF/AF/CF undefined
3765
3766_divide_error:  li r3,code_divide_err
3767                b complex
3768
3769/* Instructions dealing with segment registers */
3770pushw_sp_sr:    li r3,SP
3771                rlwinm opreg,opcode,31,27,29
3772                addi r5,state,SELECTORS+2
3773                lhbrx r4,state,r3
3774                lhzx r0,r5,opreg
3775                addi r4,r4,-2
3776                sthbrx r4,state,r3
3777                clrlwi r4,r4,16
3778                sthbrx r0,r4,ssb
3779                NEXT
3780
3781pushl_sp_sr:    li r3,SP
3782                rlwinm opreg,opcode,31,27,29
3783                addi r5,state,SELECTORS+2
3784                lhbrx r4,state,r3
3785                lhzx r0,r5,opreg
3786                addi r4,r4,-4
3787                sthbrx r4,state,r3
3788                clrlwi r4,r4,16
3789                stwbrx r0,r4,ssb
3790                NEXT
3791
3792movl_sr_mem:    cmpwi opreg,20
3793                addi opreg,opreg,SELECTORS+2
3794                cmpw cr1,base,state             # Only registers are sensitive
3795                bgt- ud                         # to word/longword difference
3796                lhzx r0,REG
3797                bne cr1,1f
3798                stwbrx r0,MEM                   # Actually a register
3799                NEXT
3800
3801movw_sr_mem:    cmpwi opreg,20                  # SREG 0 to 5 only
3802                addi opreg,opreg,SELECTORS+2
3803                bgt- ud
3804                lhzx r0,REG
38051:              sthbrx r0,MEM
3806                NEXT
3807
3808/* Now the instructions that modify the segment registers, note that
3809move/pop to ss disable interrupts and traps for one instruction ! */
3810popl_sp_sr:     li r6,4
3811                b 1f
3812popw_sp_sr:     li r6,2
38131:              li r7,SP
3814                rlwinm opreg,opcode,31,27,29
3815                lhbrx offset,state,r7
3816                addi opreg,opreg,SELBASES
3817                lhbrx r4,ssb,offset             # new selector
3818                add offset,offset,r6
3819                bl _segment_load
3820                sthbrx offset,state,r7          # update sp
3821                cmpwi opreg,8                   # is ss ?
3822                stwux r3,REG
3823                stw r4,SELECTORS-SELBASES(opreg)
3824                lwz esb,esbase(state)
3825                bne+ nop
3826                lwz ssb,ssbase(state)           # pop ss
3827                crmove RF,TF                    # prevent traps
3828                NEXT
3829       
3830movw_mem_sr:    cmpwi opreg,20
3831                addi r7,state,SELBASES
3832                bgt- ud
3833                cmpwi opreg,4                   # CS illegal
3834                beq- ud
3835                lhbrx r4,MEM
3836                bl _segment_load
3837                stwux r3,r7,opreg
3838                cmpwi opreg,8
3839                stw r4,SELECTORS-SELBASES(r7)
3840                lwz esb,esbase(state)
3841                bne+ nop
3842                lwz ssb,ssbase(state)
3843                crmove RF,TF                    # prevent traps
3844                NEXT   
3845       
3846                .equ movl_mem_sr, movw_mem_sr
3847
3848/* The encoding of les/lss/lds/lfs/lgs is strange, opcode is c4/b2/c5/b4/b5
3849for es/ss/ds/fs/gs which are sreg 0/2/3/4/5. And obviously there is
3850no lcs instruction, it's called a far jump. */
3851
3852ldlptrl:        lwzux r7,MEM
3853                li r4,4
3854                bl 1f
3855                stwx r7,REG
3856                NEXT
3857ldlptrw:        lhzux r7,MEM
3858                li r4,2
3859                bl 1f
3860                sthx r7,REG
3861                NEXT
3862       
38631:              cmpw base,state
3864                lis r3,0xc011                   # es/ss/ds/fs/gs
3865                rlwinm r5,opcode,2,0x0c         # 00/08/04/00/04
3866                mflr r0
3867                addi r3,r3,0x4800               # r4=0xc0114800
3868                rlwimi r5,opcode,0,0x10         # 00/18/04/10/14
3869                lhbrx r4,r4,offset
3870                rlwnm opcode,r3,r5,0x1c         # 00/08/0c/10/14 = sreg*4 !
3871                beq- ud                         # Only mem operands allowed !
3872                bl _segment_load
3873                addi r5,opcode,SELBASES
3874                stwux r3,r5,state
3875                mtlr r0
3876                stw r4,SELECTORS-SELBASES(r5)
3877                lwz esb,esbase(state)           # keep shadow state in sync
3878                lwz ssb,ssbase(state)
3879                blr
3880
3881
3882/* Intructions that may modify the current code segment: the next optimization
3883 * might be to avoid calling C code when the code segment does not change. But
3884 * it's probably not worth the effort.
3885 */
3886/* Far calls, jumps and returns */
3887lcall_w:        NEXTWORD(r4)
3888                NEXTWORD(r5)
3889                li r3,code_lcallw
3890                b complex
3891
3892lcall_l:        NEXTDWORD(r4)
3893                NEXTWORD(r5)
3894                li r3,code_lcalll
3895                b complex
3896
3897lcallw:         lhbrx r4,MEM
3898                addi offset,offset,2
3899                lhbrx r5,MEM
3900                li r3,code_lcallw
3901                b complex
3902
3903lcalll:         lwbrx r4,MEM
3904                addi offset,offset,4
3905                lhbrx r5,MEM
3906                li r3,code_lcalll
3907                b complex
3908
3909ljmp_w:         NEXTWORD(r4)
3910                NEXTWORD(r5)
3911                li r3,code_ljmpw
3912                b complex
3913
3914ljmp_l:         NEXTDWORD(r4)
3915                NEXTWORD(r5)
3916                li r3,code_ljmpl
3917                b complex
3918
3919ljmpw:          lhbrx r4,MEM
3920                addi offset,offset,2
3921                lhbrx r5,MEM
3922                li r3,code_ljmpw
3923                b complex
3924
3925ljmpl:          lwbrx r4,MEM
3926                addi offset,offset,4
3927                lhbrx r5,MEM
3928                li r3,code_ljmpl
3929                b complex
3930
3931lretw_imm:      NEXTWORD(r4)
3932                b 1f
3933lretw:          li r4,0
39341:              li r3,code_lretw
3935                b complex
3936
3937lretl_imm:      NEXTWORD(r4)
3938                b 1f
3939lretl:          li r4,0
39401:              li r3,code_lretl
3941                b complex
3942
3943/* Interrupts */
3944int:            li r3,code_softint              # handled by C code
3945                NEXTBYTE(r4)
3946                b complex
3947
3948int3:           li r3,code_int3                 # handled by C code
3949                b complex
3950
3951into:           EVAL_OF
3952                bf+ OF,nop
3953                li r3,code_into
3954                b complex                       # handled by C code
3955
3956iretw:          li r3,code_iretw                # handled by C code
3957                b complex
3958
3959iretl:          li r3,code_iretl
3960                b complex
3961
3962/* Miscellaneous flag control instructions */
3963clc:            oris flags,flags,(CF_IN_CR|CF_STATE_MASK|ABOVE_IN_CR)>>16
3964                xoris flags,flags,(CF_IN_CR|CF_STATE_MASK|ABOVE_IN_CR)>>16
3965                NEXT
3966
3967cmc:            oris flags,flags,(CF_IN_CR|ABOVE_IN_CR)>>16
3968                xoris flags,flags,(CF_IN_CR|CF_COMPLEMENT|ABOVE_IN_CR)>>16
3969                NEXT
3970
3971stc:            oris flags,flags,\
3972                        (CF_IN_CR|CF_LOCATION|CF_COMPLEMENT|ABOVE_IN_CR)>>16
3973                xoris flags,flags,(CF_IN_CR|CF_LOCATION|ABOVE_IN_CR)>>16
3974                NEXT
3975               
3976cld:            crclr DF
3977                NEXT
3978
3979std:            crset DF
3980                NEXT
3981       
3982cli:            crclr IF
3983                NEXT
3984
3985sti:            crset IF
3986                NEXT
3987
3988lahf:           bl _eval_flags
3989                stb r3,AH(state)
3990                NEXT
3991
3992sahf:           andis. r3,flags,OF_EXPLICIT>>16
3993                lbz r0,AH(state)
3994                beql+ _eval_of                  # save OF just in case
3995                rlwinm op1,r0,31,0x08           # AF
3996                rlwinm flags,flags,0,OF_STATE_MASK
3997                extsb result,r0                 # SF/PF
3998                ZF862ZF(r0)
3999                oris flags,flags,(ZF_PROTECT|ZF_IN_CR|SF_IN_CR)>>16
4000                addi op2,op1,0                  # AF
4001                ori result,result,0x00fb        # set all except PF
4002                mtcrf 0x02,r0                   # SF/ZF
4003                rlwimi flags,r0,27,CF_VALUE     # CF
4004                xori result,result,0x00ff       # 00 if PF set, 04 if clear
4005                NEXT
4006
4007pushfw_sp:      bl _eval_flags
4008                li r4,SP
4009                lhbrx r5,r4,state
4010                addi r5,r5,-2
4011                sthbrx r5,r4,state
4012                clrlwi r5,r5,16
4013                sthbrx r3,ssb,r5
4014                NEXT
4015
4016pushfl_sp:      bl _eval_flags
4017                li r4,SP
4018                lhbrx r5,r4,state
4019                addi r5,r5,-4
4020                sthbrx r5,r4,state
4021                clrlwi r5,r5,16
4022                stwbrx r3,ssb,r5
4023                NEXT
4024
4025popfl_sp:       li r4,SP
4026                lhbrx r5,r4,state
4027                lwbrx r3,ssb,r5
4028                addi r5,r5,4
4029                stw r3,eflags(state)
4030                sthbrx r5,r4,state
4031                b 1f
4032               
4033popfw_sp:       li r4,SP
4034                lhbrx r5,r4,state
4035                lhbrx r3,ssb,r5
4036                addi r5,r5,2
4037                sth r3,eflags+2(state)
4038                sthbrx r5,r4,state
40391:              rlwinm op1,r3,31,0x08                   # AF
4040                xori result,r3,4                        # PF
4041                ZF862ZF(r3)                             # cr6
4042                lis flags,(OF_EXPLICIT|ZF_PROTECT|ZF_IN_CR|SF_IN_CR)>>16
4043                addi op2,op1,0                          # AF
4044                rlwinm result,result,0,0x04             # PF
4045                rlwimi flags,r3,27,CF_VALUE             # CF
4046                mtcrf 0x6,r3                            # IF,DF,TF,SF,ZF
4047                rlwimi result,r3,24,0,0                 # SF
4048                rlwimi flags,r3,15,OF_VALUE             # OF
4049                NEXT
4050
4051/* SETcc is slightly faster for setz/setnz */
4052setz:           EVAL_ZF
4053                bt ZF,1f
40540:              cmpwi opreg,0
4055                bne- ud
4056                stbx opreg,MEM
4057                NEXT
4058
4059setnz:          EVAL_ZF
4060                bt ZF,0b
40611:              cmpwi opreg,0
4062                bne- ud
4063                stbx one,MEM
4064                NEXT
4065
4066#define SETCC(cond, eval, flag) \
4067set##cond:      EVAL_##eval; bt flag,1b; b 0b; \
4068setn##cond:     EVAL_##eval; bt flag,0b; b 1b
4069       
4070                SETCC(c, CF, CF)
4071                SETCC(a, ABOVE, ABOVE)
4072                SETCC(s, SF, SF)
4073                SETCC(g, SIGNED, SGT)
4074                SETCC(l, SIGNED, SLT)
4075                SETCC(o, OF, OF)
4076                SETCC(p, PF, PF)
4077
4078/* No wait for a 486SX */
4079                .equ wait, nop
4080
4081/* ARPL is not recognized in real mode */
4082                .equ arpl, ud
4083
4084/* clts and in general control and debug registers are not implemented */
4085                .equ clts, unimpl
4086
4087aaa:            lhbrx r0,AX,state
4088                bl _eval_af
4089                rlwinm r3,r3,0,0x10
4090                SET_FLAGS(FLAGS_ADD(W))
4091                rlwimi r3,r0,0,0x0f
4092                li r4,0x106
4093                addi r3,r3,-10
4094                srwi r3,r3,16                   # carry ? 0 : 0xffff
4095                andc op1,r4,r3                  # carry ? 0x106 : 0
4096                add result,r0,op1
4097                rlwinm result,result,0,28,23    # clear high half of AL
4098                li op2,10                       # sets AF indirectly
4099                sthbrx r3,AX,state              # OF/SF/ZF/PF undefined !
4100                rlwimi result,op1,8,0x10000     # insert CF
4101                NEXT
4102
4103aas:            lhbrx r0,AX,state
4104                bl _eval_af
4105                rlwinm r3,r3,0,0x10
4106                SET_FLAGS(FLAGS_ADD(W))
4107                rlwimi r3,r0,0,0x0f             # AF:AL&0x0f
4108                li r4,0x106
4109                addi r3,r3,-10
4110                srwi r3,r3,16                   # carry ? 0 : 0xffff
4111                andc op1,r4,r3                  # carry ? 0x106 : 0
4112                sub result,r0,op1
4113                rlwinm result,result,0,28,23    # clear high half of AL
4114                li op2,10                       # sets AF indirectly
4115                sthbrx r3,AX,state              # OF/SF/ZF/PF undefined !
4116                rlwimi result,op1,8,0x10000     # insert CF
4117                NEXT
4118
4119daa:            lbz r0,AL(state)
4120                bl _eval_af
4121                rlwinm r7,r3,0,0x10
4122                bl _eval_cf                     # r3=CF<<8
4123                rlwimi r7,r0,0,0x0f
4124                SET_FLAGS(FLAGS_ADD(B))
4125                addi r4,r7,-10
4126                rlwinm r4,r4,3,0x06             # 6 if AF or >9, 0 otherwise
4127                srwi op1,r7,1                   # 0..4, no AF, 5..f AF set
4128                add r0,r0,r4                    # conditional add
4129                li op2,11                       # sets AF depnding on op1
4130                or r0,r0,r3
4131                subfic r3,r0,159
4132                rlwinm r3,r3,7,0x60             # mask value to add
4133                add result,r0,r3                # final result for SF/ZF/PF
4134                stb result,AL(state)
4135                rlwimi result,r3,2,0x100        # set CF if added
4136                NEXT
4137       
4138das:            lbz r0,AL(state)
4139                bl _eval_af
4140                rlwinm r7,r3,0,0x10
4141                bl _eval_cf
4142                rlwimi r7,r0,0,0x0f
4143                SET_FLAGS(FLAGS_ADD(B))
4144                addi r4,r7,-10
4145                rlwinm r4,r4,3,0x06
4146                srwi op1,r7,1                   # 0..4, no AF, 5..f AF set
4147                sub r0,r0,r4                    # conditional add
4148                li op2,11                       # sets AF depending on op1
4149                or r4,r0,r3                     # insert CF
4150                addi r3,r4,-160
4151                rlwinm r3,r3,7,0x60             # mask value to add
4152                sub result,r4,r3                # final result for SF/ZF/PF
4153                stb result,AL(state)
4154                rlwimi result,r3,2,0x100        # set CF
4155                NEXT
4156       
4157/* 486 specific instructions */
4158
4159/* For cmpxchg, only the zero flag is important */
4160
4161cmpxchgb:       lbz op1,AL(state)
4162                SET_FLAGS(FLAGS_SUB(B)|ZF_IN_CR)
4163                lbzx op2,MEM
4164                cmpw cr6,op1,op2
4165                sub result,op1,op2
4166                bne cr6,1f
4167                lbzx r3,REG                     # success: swap
4168                stbx r3,MEM
4169                NEXT
41701:              stb op2,AL(state)
4171                NEXT
4172
4173cmpxchgw:       lhbrx op1,AX,state
4174                SET_FLAGS(FLAGS_SUB(W)|ZF_IN_CR)
4175                lhbrx op2,MEM
4176                cmpw cr6,op1,op2
4177                sub result,op1,op2
4178                bne cr6,1f
4179                lhzx r3,REG                     # success: swap
4180                sthx r3,MEM
4181                NEXT
41821:              sthbrx op2,AX,state
4183                NEXT
4184
4185cmpxchgl:       lwbrx op1,EAX,state
4186                SET_FLAGS(FLAGS_SUB(L)|ZF_IN_CR|SIGNED_IN_CR)
4187                lwbrx op2,MEM
4188                cmpw cr6,op1,op2
4189                sub result,op1,op2
4190                bne cr6,1f
4191                lwzx r3,REG                     # success: swap
4192                stwx r3,MEM
4193                NEXT
41941:              stwbrx op2,EAX,state
4195                NEXT
4196
4197xaddb:          lbzx op2,MEM
4198                SET_FLAGS(FLAGS_ADD(B))
4199                lbzx op1,REG
4200                add result,op1,op2
4201                stbx result,MEM
4202                stbx op2,REG
4203                NEXT
4204
4205xaddw:          lhbrx op2,MEM
4206                SET_FLAGS(FLAGS_ADD(W))
4207                lhbrx op1,REG
4208                add result,op1,op2
4209                sthbrx result,MEM
4210                sthbrx op2,REG
4211                NEXT
4212
4213xaddl:          lwbrx op2,MEM
4214                SET_FLAGS(FLAGS_ADD(L))
4215                lwbrx op1,REG
4216                add result,op1,op2
4217                stwbrx result,MEM
4218                stwbrx op2,REG
4219                NEXT
4220
4221/* All FPU instructions skipped. This is a 486 SX ! */
4222esc:            li r3,code_dna                  # DNA interrupt
4223                b complex
4224
4225                .equ hlt, unimpl                # Cannot stop
4226
4227                .equ invd, unimpl
4228
4229/* Undefined in real address mode */   
4230                .equ lar, ud
4231
4232                .equ lgdt, unimpl
4233                .equ lidt, unimpl
4234                .equ lldt, ud
4235                .equ lmsw, unimpl
4236
4237/* protected mode only */
4238                .equ lsl, ud
4239                .equ ltr, ud
4240
4241                .equ movl_cr_reg, unimpl
4242                .equ movl_reg_cr, unimpl
4243                .equ movl_dr_reg, unimpl
4244                .equ movl_reg_dr, unimpl
4245
4246                .equ sgdt, unimpl
4247
4248                .equ sidt, unimpl
4249                .equ sldt, ud
4250                .equ smsw, unimpl
4251
4252                .equ str, ud
4253       
4254ud:             li r3,code_ud
4255                li r4,0
4256                b complex
4257
4258unimpl:         li r3,code_ud
4259                li r4,1
4260                b complex
4261
4262                .equ verr, ud
4263                .equ verw, ud
4264                .equ wbinvd, unimpl
4265
4266em86_end:
4267                .size em86_enter,em86_end-em86_enter
4268#ifdef  __BOOT__
4269                .data
4270#define ENTRY(x,t) .long x+t-_jtables
4271#else
4272                .section .rodata
4273#define ENTRY(x,t) .long x+t
4274#endif
4275       
4276#define BOP(x)  ENTRY(x,2)      /* Byte operation with mod/rm byte */
4277#define WLOP(x) ENTRY(x,3)      /* 16 or 32 bit operation with mod/rm byte */
4278#define EXTOP(x) ENTRY(x,0)     /* Opcode with extension in mod/rm byte */
4279#define OP(x)   ENTRY(x,1)      /* Direct one byte opcode/prefix */
4280
4281/* A few macros for the main table */
4282#define gen6(op, wl, axeax) \
4283                BOP(op##b##_reg_mem); WLOP(op##wl##_reg_mem); \
4284                BOP(op##b##_mem_reg); WLOP(op##wl##_mem_reg); \
4285                OP(op##b##_imm_al); OP(op##wl##_imm_##axeax)
4286
4287#define rep7(l,t) \
4288                ENTRY(l,t); ENTRY(l,t); ENTRY(l,t); ENTRY(l,t); \
4289                ENTRY(l,t); ENTRY(l,t); ENTRY(l,t)
4290
4291#define rep8(l) l ; l; l; l; l; l; l; l;
4292
4293#define allcond(pfx, sfx, t) \
4294                ENTRY(pfx##o##sfx, t); ENTRY(pfx##no##sfx, t); \
4295                ENTRY(pfx##c##sfx, t); ENTRY(pfx##nc##sfx, t); \
4296                ENTRY(pfx##z##sfx, t); ENTRY(pfx##nz##sfx, t); \
4297                ENTRY(pfx##na##sfx, t); ENTRY(pfx##a##sfx, t); \
4298                ENTRY(pfx##s##sfx, t); ENTRY(pfx##ns##sfx, t); \
4299                ENTRY(pfx##p##sfx, t); ENTRY(pfx##np##sfx, t); \
4300                ENTRY(pfx##l##sfx, t); ENTRY(pfx##nl##sfx, t); \
4301                ENTRY(pfx##ng##sfx, t); ENTRY(pfx##g##sfx, t)
4302
4303/* single/double register sign extensions and other oddities */
4304#define h2sextw cbw             /* Half to Single sign extension */
4305#define s2dextw cwd             /* Single to Double sign extension */
4306#define h2sextl cwde
4307#define s2dextl cdq
4308#define j_a16_cxz_w jcxz_w
4309#define j_a32_cxz_w jecxz_w
4310#define j_a16_cxz_l jcxz_l
4311#define j_a32_cxz_l jecxz_l
4312#define loopa16_w loopw_w
4313#define loopa16_l loopw_l
4314#define loopa32_w loopl_w
4315#define loopa32_l loopl_l
4316#define loopnza16_w loopnzw_w
4317#define loopnza16_l loopnzw_l
4318#define loopnza32_w loopnzl_w
4319#define loopnza32_l loopnzl_l
4320#define loopza16_w loopzw_w
4321#define loopza16_l loopzw_l
4322#define loopza32_w loopzl_w
4323#define loopza32_l loopzl_l
4324/* No FP support */
4325
4326/* Addressing mode table */
4327                .align 5
4328#                     (%bx,%si),    (%bx,%di),    (%bp,%si),    (%bp,%di)
4329adtable:        .long 0x00004360,   0x00004370,   0x80004560,   0x80004570
4330#                     (%si),        (%di),        o16,          (%bx)
4331                .long 0x00004600,   0x00004700,   0x00002000,   0x00004300
4332#                     o8(%bx,%si),  o8(%bx,%di),  o8(%bp,%si),  o8(%bp,%di)
4333                .long 0x00004360,   0x00004370,   0x80004560,   0x80004570
4334#                     o8(%si),      o8(%di),      o8(%bp),      o8(%bx)
4335                .long 0x00004600,   0x00004700,   0x80004500,   0x00004300
4336#                     o16(%bx,%si), o16(%bx,%di), o16(%bp,%si), o16(%bp,%di)
4337                .long 0x00004360,   0x00004370,   0x80004560,   0x80004570
4338#                     o16(%si),     o16(%di),     o16(%bp),     o16(%bx)
4339                .long 0x00004600,   0x00004700,   0x80004500,   0x00004300
4340#               register addressing modes do not use the table
4341                .long 0, 0, 0, 0, 0, 0, 0, 0
4342#now 32 bit modes
4343#                     (%eax),       (%ecx),       (%edx),       (%ebx)
4344                .long 0x00004090,   0x00004190,   0x00004290,   0x00004390
4345#                     sib,          o32,          (%esi),       (%edi)
4346                .long 0x00003090,   0x00002090,   0x00004690,   0x00004790
4347#                     o8(%eax),     o8(%ecx),     o8(%edx),     o8(%ebx)
4348                .long 0x00004090,   0x00004190,   0x00004290,   0x00004390
4349#                     sib,          o8(%ebp),     o8(%esi),     o8(%edi)
4350                .long 0x00003090,   0x80004590,   0x00004690,   0x00004790
4351#                     o32(%eax),    o32(%ecx),    o32(%edx),    o32(%ebx)
4352                .long 0x00004090,   0x00004190,   0x00004290,   0x00004390
4353#                     sib,          o32(%ebp),    o32(%esi),    o32(%edi)
4354                .long 0x00003090,   0x80004590,   0x00004690,   0x00004790
4355#               register addressing modes do not use the table
4356                .long 0, 0, 0, 0, 0, 0, 0, 0
4357
4358#define jtable(wl, awl, spesp, axeax, name ) \
4359                .align  5; \
4360jtab_##name:    gen6(add, wl, axeax); \
4361                OP(push##wl##_##spesp##_sr); \
4362                OP(pop##wl##_##spesp##_sr); \
4363                gen6(or, wl, axeax); \
4364                OP(push##wl##_##spesp##_sr); \
4365                OP(_twobytes); \
4366                gen6(adc, wl, axeax); \
4367                OP(push##wl##_##spesp##_sr); \
4368                OP(pop##wl##_##spesp##_sr); \
4369                gen6(sbb, wl, axeax); \
4370                OP(push##wl##_##spesp##_sr); \
4371                OP(pop##wl##_##spesp##_sr); \
4372                gen6(and, wl, axeax); OP(_es); OP(daa); \
4373                gen6(sub, wl, axeax); OP(_cs); OP(das); \
4374                gen6(xor, wl, axeax); OP(_ss); OP(aaa); \
4375                gen6(cmp, wl, axeax); OP(_ds); OP(aas); \
4376                rep8(OP(inc##wl##_reg)); \
4377                rep8(OP(dec##wl##_reg)); \
4378                rep8(OP(push##wl##_##spesp##_reg)); \
4379                rep8(OP(pop##wl##_##spesp##_reg)); \
4380                OP(pusha##wl##_##spesp); OP(popa##wl##_##spesp); \
4381                WLOP(bound##wl); WLOP(arpl); \
4382                OP(_fs); OP(_gs); OP(_opsize); OP(_adsize); \
4383                OP(push##wl##_##spesp##_imm); WLOP(imul##wl##_imm); \
4384                OP(push##wl##_##spesp##_imm8); WLOP(imul##wl##_imm8); \
4385                OP(insb_##awl); OP(ins##wl##_##awl); \
4386                OP(outsb_##awl); OP(outs##wl##_##awl); \
4387                allcond(sj,_##wl,1); \
4388                EXTOP(grp1b_imm); EXTOP(grp1##wl##_imm); \
4389                EXTOP(grp1b_imm); EXTOP(grp1##wl##_imm8); \
4390                BOP(testb_reg_mem); WLOP(test##wl##_reg_mem); \
4391                BOP(xchgb_reg_mem); WLOP(xchg##wl##_reg_mem); \
4392                BOP(movb_reg_mem); WLOP(mov##wl##_reg_mem); \
4393                BOP(movb_mem_reg); WLOP(mov##wl##_mem_reg); \
4394                WLOP(mov##wl##_sr_mem); WLOP(lea##wl); \
4395                WLOP(mov##wl##_mem_sr); WLOP(pop##wl##_##spesp##_##awl); \
4396                OP(nop); rep7(xchg##wl##_##axeax##_reg,1); \
4397                OP(h2sext##wl); OP(s2dext##wl); \
4398                OP(lcall_##wl); OP(wait); \
4399                OP(pushf##wl##_##spesp); OP(popf##wl##_##spesp); \
4400                OP(sahf); OP(lahf); \
4401                OP(movb_##awl##_al); OP(mov##wl##_##awl##_##axeax); \
4402                OP(movb_al_##awl); OP(mov##wl##_##axeax##_##awl); \
4403                OP(movsb_##awl); OP(movs##wl##_##awl); \
4404                OP(cmpsb_##awl); OP(cmps##wl##_##awl); \
4405                OP(testb_imm_al); OP(test##wl##_imm_##axeax); \
4406                OP(stosb_##awl); OP(stos##wl##_##awl); \
4407                OP(lodsb_##awl); OP(lods##wl##_##awl); \
4408                OP(scasb_##awl); OP(scas##wl##_##awl); \
4409                rep8(OP(movb_imm_reg)); \
4410                rep8(OP(mov##wl##_imm_reg)); \
4411                EXTOP(shiftb_imm); EXTOP(shift##wl##_imm); \
4412                OP(ret##wl##_##spesp##_imm); OP(ret##wl##_##spesp); \
4413                WLOP(ldlptr##wl); WLOP(ldlptr##wl); \
4414                BOP(movb_imm_mem); WLOP(mov##wl##_imm_mem); \
4415                OP(enter##wl##_##spesp); OP(leave##wl##_##spesp); \
4416                OP(lret##wl##_imm); OP(lret##wl); \
4417                OP(int3); OP(int); OP(into); OP(iret##wl); \
4418                EXTOP(shiftb_1); EXTOP(shift##wl##_1); \
4419                EXTOP(shiftb_cl); EXTOP(shift##wl##_cl); \
4420                OP(aam); OP(aad); OP(ud); OP(xlatb_##awl); \
4421                rep8(OP(esc)); \
4422                OP(loopnz##awl##_##wl); OP(loopz##awl##_##wl); \
4423                OP(loop##awl##_##wl); OP(j_##awl##_cxz_##wl); \
4424                OP(inb_port_al); OP(in##wl##_port_##axeax); \
4425                OP(outb_al_port); OP(out##wl##_##axeax##_port); \
4426                OP(call##wl##_##spesp); OP(jmp_##wl); \
4427                OP(ljmp_##wl); OP(sjmp_##wl); \
4428                OP(inb_dx_al); OP(in##wl##_dx_##axeax); \
4429                OP(outb_al_dx); OP(out##wl##_##axeax##_dx); \
4430                OP(_lock); OP(ud); OP(_repnz); OP(_repz); \
4431                OP(hlt); OP(cmc); \
4432                EXTOP(grp3b); EXTOP(grp3##wl); \
4433                OP(clc); OP(stc); OP(cli); OP(sti); \
4434                OP(cld); OP(std); \
4435                EXTOP(grp4b); EXTOP(grp5##wl##_##spesp); \
4436                /* Here we start the table for twobyte instructions */ \
4437                OP(ud); OP(ud); WLOP(lar); WLOP(lsl); \
4438                OP(ud); OP(ud); OP(clts); OP(ud); \
4439                OP(invd); OP(wbinvd); OP(ud); OP(ud); \
4440                OP(ud); OP(ud); OP(ud); OP(ud); \
4441                rep8(OP(ud)); \
4442                rep8(OP(ud)); \
4443                OP(movl_cr_reg); OP(movl_reg_cr); \
4444                OP(movl_dr_reg); OP(movl_reg_dr); \
4445                OP(ud); OP(ud); OP(ud); OP(ud); \
4446                rep8(OP(ud)); \
4447                /* .long        wrmsr, rdtsc, rdmsr, rdpmc; */\
4448                rep8(OP(ud)); \
4449                rep8(OP(ud)); \
4450                /* allcond(cmov, wl); */  \
4451                rep8(OP(ud)); rep8(OP(ud)); \
4452                rep8(OP(ud)); rep8(OP(ud)); \
4453                /* MMX Start */ \
4454                rep8(OP(ud)); rep8(OP(ud)); \
4455                rep8(OP(ud)); rep8(OP(ud)); \
4456                /* MMX End */ \
4457                allcond(j,_##wl, 1); \
4458                allcond(set,,2); \
4459                OP(push##wl##_##spesp##_sr); OP(pop##wl##_##spesp##_sr); \
4460                OP(ud) /* cpuid */; WLOP(bt##wl##_reg_mem); \
4461                WLOP(shld##wl##_imm); WLOP(shld##wl##_cl); \
4462                OP(ud); OP(ud); \
4463                OP(push##wl##_##spesp##_sr); OP(pop##wl##_##spesp##_sr); \
4464                OP(ud) /* rsm */; WLOP(bts##wl##_reg_mem); \
4465                WLOP(shrd##wl##_imm); WLOP(shrd##wl##_cl); \
4466                OP(ud); WLOP(imul##wl##_mem_reg); \
4467                BOP(cmpxchgb); WLOP(cmpxchg##wl); \
4468                WLOP(ldlptr##wl); WLOP(btr##wl##_reg_mem); \
4469                WLOP(ldlptr##wl); WLOP(ldlptr##wl); \
4470                WLOP(movzb##wl); WLOP(movzw##wl); \
4471                OP(ud); OP(ud); \
4472                EXTOP(grp8##wl); WLOP(btc##wl##_reg_mem); \
4473                WLOP(bsf##wl); WLOP(bsr##wl); \
4474                WLOP(movsb##wl); WLOP(movsw##wl); \
4475                BOP(xaddb); WLOP(xadd##wl); \
4476                OP(ud); OP(ud); \
4477                OP(ud); OP(ud); OP(ud); OP(ud); \
4478                rep8(OP(bswap)); \
4479                /* MMX Start */ \
4480                rep8(OP(ud)); rep8(OP(ud)); \
4481                rep8(OP(ud)); rep8(OP(ud)); \
4482                rep8(OP(ud)); rep8(OP(ud)); \
4483                /* MMX End */
4484                .align 5                /* 8kb of tables, 32 byte aligned */
4485_jtables:       jtable(w, a16, sp, ax, www)     /* data16, addr16 */
4486                jtable(l, a16, sp, eax, lww)    /* data32, addr16 */
4487                jtable(w, a32, sp, ax, wlw)     /* data16, addr32 */
4488                jtable(l, a32, sp, eax, llw)    /* data32, addr32 */
4489/* The other possible combinations are only required by protected mode
4490code using a big stack segment */
4491/* Here are the auxiliary tables for opcode extensions, note that
4492all entries get 2 or 3 added. */
4493#define grp1table(bwl,t,s8) \
4494grp1##bwl##_imm##s8:; \
4495                ENTRY(add##bwl##_imm##s8,t); ENTRY(or##bwl##_imm##s8,t); \
4496                ENTRY(adc##bwl##_imm##s8,t); ENTRY(sbb##bwl##_imm##s8,t); \
4497                ENTRY(and##bwl##_imm##s8,t); ENTRY(sub##bwl##_imm##s8,t); \
4498                ENTRY(xor##bwl##_imm##s8,t); ENTRY(cmp##bwl##_imm##s8,t)
4499
4500                grp1table(b,2,)
4501                grp1table(w,3,)
4502                grp1table(w,3,8)
4503                grp1table(l,3,)
4504                grp1table(l,3,8)
4505
4506#define shifttable(bwl,t,c) \
4507shift##bwl##_##c:; \
4508                ENTRY(rol##bwl##_##c,t); ENTRY(ror##bwl##_##c,t); \
4509                ENTRY(rcl##bwl##_##c,t); ENTRY(rcr##bwl##_##c,t); \
4510                ENTRY(shl##bwl##_##c,t); ENTRY(shr##bwl##_##c,t); \
4511                OP(ud); ENTRY(sar##bwl##_##c,t)
4512
4513                shifttable(b,2,1)
4514                shifttable(w,3,1)
4515                shifttable(l,3,1)
4516
4517                shifttable(b,2,cl)
4518                shifttable(w,3,cl)
4519                shifttable(l,3,cl)
4520
4521                shifttable(b,2,imm)
4522                shifttable(w,3,imm)
4523                shifttable(l,3,imm)
4524
4525#define grp3table(bwl,t) \
4526grp3##bwl:      ENTRY(test##bwl##_imm,t); OP(ud); \
4527                ENTRY(not##bwl,t); ENTRY(neg##bwl,t); \
4528                ENTRY(mul##bwl,t); ENTRY(imul##bwl,t); \
4529                ENTRY(div##bwl,t); ENTRY(idiv##bwl,t)
4530
4531                grp3table(b,2)
4532                grp3table(w,3)
4533                grp3table(l,3)
4534
4535
4536grp4b:          BOP(incb); BOP(decb); \
4537                OP(ud); OP(ud); \
4538                OP(ud); OP(ud); \
4539                OP(ud); OP(ud)
4540
4541#define grp5table(wl,spesp) \
4542grp5##wl##_##spesp: \
4543                WLOP(inc##wl); WLOP(dec##wl); \
4544                WLOP(call##wl##_##spesp##_mem); WLOP(lcall##wl##); \
4545                WLOP(jmp##wl); WLOP(ljmp##wl); \
4546                WLOP(push##wl##_##spesp); OP(ud)
4547
4548                grp5table(w,sp)
4549                grp5table(l,sp)
4550
4551#define grp8table(wl) \
4552grp8##wl:       OP(ud); OP(ud); OP(ud); OP(ud); \
4553                WLOP(bt##wl##_imm); WLOP(bts##wl##_imm); \
4554                WLOP(btr##wl##_imm); WLOP(btc##wl##_imm)
4555
4556                grp8table(w)
4557                grp8table(l)
4558#ifdef __BOOT__
4559_endjtables:    .long   0       /* Points to _jtables after relocation */
4560#endif
4561
Note: See TracBrowser for help on using the repository browser.