OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [shared/] [bootloader/] [em86real.S] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.