source: rtems/bsps/powerpc/motorola_powerpc/bootloader/em86real.S @ eb36d11

5
Last change on this file since eb36d11 was 03e1d837, checked in by Sebastian Huber <sebastian.huber@…>, on 04/24/18 at 05:06:36

bsps/powerpc: Move bootloader to bsps

This bootloader is only used by the motorola_powerpc BSP.

This patch is a part of the BSP source reorganization.

Update #3285.

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