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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_70/] [or1ksim/] [cpu/] [or32/] [dyn_rec.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1452 nogj
/* dyn_rec.c -- Dynamic recompiler implementation for or32
2
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <sys/mman.h>
24
#include <signal.h>
25
#include <errno.h>
26
#include <execinfo.h>
27
 
28
#include "config.h"
29
 
30
#ifdef HAVE_INTTYPES_H
31
#include <inttypes.h>
32
#endif
33
 
34
#include "port.h"
35
#include "arch.h"
36
#include "immu.h"
37
#include "abstract.h"
38
#include "opcode/or32.h"
39
#include "spr_defs.h"
40
#include "execute.h"
41
#include "except.h"
42
#include "spr_defs.h"
43
#include "sim-config.h"
44
#include "sched.h"
45
 
46
#include "rec_i386.h"
47
#include "i386_regs.h"
48
 
49
#include "dyn_rec.h"
50
#include "gen_ops.h"
51
 
52
#include "op_support.h"
53
 
54
/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
55
 
56
/* FIXME: Optimise sorted list adding */
57
 
58
/* FIXME: remove this and use config.immu.pagesize */
59
#define PAGE_LEN 8192
60
 
61
typedef void (*generic_gen_op)(struct op_queue *opq, int end);
62
typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
63
 
64
void gen_l_invalid(struct op_queue *opq, int param_t[3], orreg_t param[3],
65
                   int delay_slot);
66
 
67
static const generic_gen_op gen_op_move_gpr_t[NUM_T_REGS][32] = {
68
 { NULL,
69
   gen_op_move_gpr1_t0,
70
   gen_op_move_gpr2_t0,
71
   gen_op_move_gpr3_t0,
72
   gen_op_move_gpr4_t0,
73
   gen_op_move_gpr5_t0,
74
   gen_op_move_gpr6_t0,
75
   gen_op_move_gpr7_t0,
76
   gen_op_move_gpr8_t0,
77
   gen_op_move_gpr9_t0,
78
   gen_op_move_gpr10_t0,
79
   gen_op_move_gpr11_t0,
80
   gen_op_move_gpr12_t0,
81
   gen_op_move_gpr13_t0,
82
   gen_op_move_gpr14_t0,
83
   gen_op_move_gpr15_t0,
84
   gen_op_move_gpr16_t0,
85
   gen_op_move_gpr17_t0,
86
   gen_op_move_gpr18_t0,
87
   gen_op_move_gpr19_t0,
88
   gen_op_move_gpr20_t0,
89
   gen_op_move_gpr21_t0,
90
   gen_op_move_gpr22_t0,
91
   gen_op_move_gpr23_t0,
92
   gen_op_move_gpr24_t0,
93
   gen_op_move_gpr25_t0,
94
   gen_op_move_gpr26_t0,
95
   gen_op_move_gpr27_t0,
96
   gen_op_move_gpr28_t0,
97
   gen_op_move_gpr29_t0,
98
   gen_op_move_gpr30_t0,
99
   gen_op_move_gpr31_t0 },
100
 { NULL,
101
   gen_op_move_gpr1_t1,
102
   gen_op_move_gpr2_t1,
103
   gen_op_move_gpr3_t1,
104
   gen_op_move_gpr4_t1,
105
   gen_op_move_gpr5_t1,
106
   gen_op_move_gpr6_t1,
107
   gen_op_move_gpr7_t1,
108
   gen_op_move_gpr8_t1,
109
   gen_op_move_gpr9_t1,
110
   gen_op_move_gpr10_t1,
111
   gen_op_move_gpr11_t1,
112
   gen_op_move_gpr12_t1,
113
   gen_op_move_gpr13_t1,
114
   gen_op_move_gpr14_t1,
115
   gen_op_move_gpr15_t1,
116
   gen_op_move_gpr16_t1,
117
   gen_op_move_gpr17_t1,
118
   gen_op_move_gpr18_t1,
119
   gen_op_move_gpr19_t1,
120
   gen_op_move_gpr20_t1,
121
   gen_op_move_gpr21_t1,
122
   gen_op_move_gpr22_t1,
123
   gen_op_move_gpr23_t1,
124
   gen_op_move_gpr24_t1,
125
   gen_op_move_gpr25_t1,
126
   gen_op_move_gpr26_t1,
127
   gen_op_move_gpr27_t1,
128
   gen_op_move_gpr28_t1,
129
   gen_op_move_gpr29_t1,
130
   gen_op_move_gpr30_t1,
131
   gen_op_move_gpr31_t1 },
132
 { NULL,
133
   gen_op_move_gpr1_t2,
134
   gen_op_move_gpr2_t2,
135
   gen_op_move_gpr3_t2,
136
   gen_op_move_gpr4_t2,
137
   gen_op_move_gpr5_t2,
138
   gen_op_move_gpr6_t2,
139
   gen_op_move_gpr7_t2,
140
   gen_op_move_gpr8_t2,
141
   gen_op_move_gpr9_t2,
142
   gen_op_move_gpr10_t2,
143
   gen_op_move_gpr11_t2,
144
   gen_op_move_gpr12_t2,
145
   gen_op_move_gpr13_t2,
146
   gen_op_move_gpr14_t2,
147
   gen_op_move_gpr15_t2,
148
   gen_op_move_gpr16_t2,
149
   gen_op_move_gpr17_t2,
150
   gen_op_move_gpr18_t2,
151
   gen_op_move_gpr19_t2,
152
   gen_op_move_gpr20_t2,
153
   gen_op_move_gpr21_t2,
154
   gen_op_move_gpr22_t2,
155
   gen_op_move_gpr23_t2,
156
   gen_op_move_gpr24_t2,
157
   gen_op_move_gpr25_t2,
158
   gen_op_move_gpr26_t2,
159
   gen_op_move_gpr27_t2,
160
   gen_op_move_gpr28_t2,
161
   gen_op_move_gpr29_t2,
162
   gen_op_move_gpr30_t2,
163
   gen_op_move_gpr31_t2 } };
164
 
165
static const generic_gen_op gen_op_move_t_gpr[NUM_T_REGS][32] = {
166
 { NULL,
167
   gen_op_move_t0_gpr1,
168
   gen_op_move_t0_gpr2,
169
   gen_op_move_t0_gpr3,
170
   gen_op_move_t0_gpr4,
171
   gen_op_move_t0_gpr5,
172
   gen_op_move_t0_gpr6,
173
   gen_op_move_t0_gpr7,
174
   gen_op_move_t0_gpr8,
175
   gen_op_move_t0_gpr9,
176
   gen_op_move_t0_gpr10,
177
   gen_op_move_t0_gpr11,
178
   gen_op_move_t0_gpr12,
179
   gen_op_move_t0_gpr13,
180
   gen_op_move_t0_gpr14,
181
   gen_op_move_t0_gpr15,
182
   gen_op_move_t0_gpr16,
183
   gen_op_move_t0_gpr17,
184
   gen_op_move_t0_gpr18,
185
   gen_op_move_t0_gpr19,
186
   gen_op_move_t0_gpr20,
187
   gen_op_move_t0_gpr21,
188
   gen_op_move_t0_gpr22,
189
   gen_op_move_t0_gpr23,
190
   gen_op_move_t0_gpr24,
191
   gen_op_move_t0_gpr25,
192
   gen_op_move_t0_gpr26,
193
   gen_op_move_t0_gpr27,
194
   gen_op_move_t0_gpr28,
195
   gen_op_move_t0_gpr29,
196
   gen_op_move_t0_gpr30,
197
   gen_op_move_t0_gpr31 },
198
 { NULL,
199
   gen_op_move_t1_gpr1,
200
   gen_op_move_t1_gpr2,
201
   gen_op_move_t1_gpr3,
202
   gen_op_move_t1_gpr4,
203
   gen_op_move_t1_gpr5,
204
   gen_op_move_t1_gpr6,
205
   gen_op_move_t1_gpr7,
206
   gen_op_move_t1_gpr8,
207
   gen_op_move_t1_gpr9,
208
   gen_op_move_t1_gpr10,
209
   gen_op_move_t1_gpr11,
210
   gen_op_move_t1_gpr12,
211
   gen_op_move_t1_gpr13,
212
   gen_op_move_t1_gpr14,
213
   gen_op_move_t1_gpr15,
214
   gen_op_move_t1_gpr16,
215
   gen_op_move_t1_gpr17,
216
   gen_op_move_t1_gpr18,
217
   gen_op_move_t1_gpr19,
218
   gen_op_move_t1_gpr20,
219
   gen_op_move_t1_gpr21,
220
   gen_op_move_t1_gpr22,
221
   gen_op_move_t1_gpr23,
222
   gen_op_move_t1_gpr24,
223
   gen_op_move_t1_gpr25,
224
   gen_op_move_t1_gpr26,
225
   gen_op_move_t1_gpr27,
226
   gen_op_move_t1_gpr28,
227
   gen_op_move_t1_gpr29,
228
   gen_op_move_t1_gpr30,
229
   gen_op_move_t1_gpr31 },
230
 { NULL,
231
   gen_op_move_t2_gpr1,
232
   gen_op_move_t2_gpr2,
233
   gen_op_move_t2_gpr3,
234
   gen_op_move_t2_gpr4,
235
   gen_op_move_t2_gpr5,
236
   gen_op_move_t2_gpr6,
237
   gen_op_move_t2_gpr7,
238
   gen_op_move_t2_gpr8,
239
   gen_op_move_t2_gpr9,
240
   gen_op_move_t2_gpr10,
241
   gen_op_move_t2_gpr11,
242
   gen_op_move_t2_gpr12,
243
   gen_op_move_t2_gpr13,
244
   gen_op_move_t2_gpr14,
245
   gen_op_move_t2_gpr15,
246
   gen_op_move_t2_gpr16,
247
   gen_op_move_t2_gpr17,
248
   gen_op_move_t2_gpr18,
249
   gen_op_move_t2_gpr19,
250
   gen_op_move_t2_gpr20,
251
   gen_op_move_t2_gpr21,
252
   gen_op_move_t2_gpr22,
253
   gen_op_move_t2_gpr23,
254
   gen_op_move_t2_gpr24,
255
   gen_op_move_t2_gpr25,
256
   gen_op_move_t2_gpr26,
257
   gen_op_move_t2_gpr27,
258
   gen_op_move_t2_gpr28,
259
   gen_op_move_t2_gpr29,
260
   gen_op_move_t2_gpr30,
261
   gen_op_move_t2_gpr31 } };
262
 
263
static const imm_gen_op calc_insn_ea_table[NUM_T_REGS] =
264
 { gen_op_calc_insn_ea_t0, gen_op_calc_insn_ea_t1, gen_op_calc_insn_ea_t2 };
265
 
266
/* Linker stubs.  This will allow the linker to link in op.o.  The relocations
267
 * that the linker does for these will be irrelevent anyway, since we patch the
268
 * relocations during recompilation. */
269
uorreg_t __op_param1;
270
uorreg_t __op_param2;
271
uorreg_t __op_param3;
272
 
273
/* The number of bytes that a dynamicly recompiled page should be enlarged by */
274
#define RECED_PAGE_ENLARGE_BY 51200
275
 
276
/* The number of entries that the micro operations array in op_queue should be
277
 * enlarged by */
278
#define OPS_ENLARGE_BY 5
279
 
280
#define T_NONE (-1)
281
 
282
void *rec_stack_base;
283
 
284
/* FIXME: Put this into some header */
285
extern int do_stats;
286
 
287
static int sigsegv_state = 0;
288
static void *sigsegv_addr = NULL;
289
 
290
void dyn_ret_stack_prot(void);
291
void dump_held_xrefs(struct dyn_page *dp, FILE *f);
292
 
293
void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
294
{
295
  struct dyn_page *dp;
296
  FILE *f;
297
  char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
298
  void *stack;
299
  int i, j;
300
  void *trace[10];
301
  int num_trace;
302
  char **trace_names;
303
 
304
  if(!sigsegv_state) {
305
    sigsegv_addr = siginf->si_addr;
306
  } else {
307
    printf("Nested SIGSEGV occured, dumping next chuck of info\n");
308
    sigsegv_state++;
309
  }
310
 
311
  /* First dump all the data that does not need dereferenceing to get */
312
  switch(sigsegv_state) {
313
  case 0:
314
    fflush(stdout);
315
    printf("Segmentation fault at %p (or address: 0x%"PRIxADDR")\n\n",
316
           sigsegv_addr, get_pc());
317
    sigsegv_state++;
318
  case 1:
319
    /* Run through the recompiled pages, dumping them to disk as we go */
320
    for(dp = cpu_state.dyn_pages; dp; dp = dp->next) {
321
      printf("Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
322
             dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
323
             dp->host_len);
324
      fflush(stdout);
325
 
326
      sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
327
      if(!(f = fopen(filen, "w"))) {
328
        fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
329
                filen, strerror(errno));
330
        continue;
331
      }
332
      if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
333
        fprintf(stderr, "Unable to write recompiled data to file: %s\n",
334
                strerror(errno));
335
 
336
      fclose(f);
337
    }
338
    sigsegv_state++;
339
  case 2:
340
    /* Dump the x-refs to disk */
341
    for(dp = cpu_state.dyn_pages; dp; dp = dp->next) {
342
      printf("Dumping cross references of 0x%"PRIxADDR" to disk\n", dp->or_page);
343
 
344
      sprintf(filen, "or_xref.%"PRIxADDR, dp->or_page);
345
      if(!(f = fopen(filen, "w"))) {
346
        fprintf(stderr, "Unable to open %s to dump cross references to: %s\n",
347
                filen, strerror(errno));
348
        continue;
349
      }
350
 
351
      fprintf(f, "Cross references in the page:\n");
352
      dump_xrefs(dp, f);
353
 
354
      fprintf(f, "\nCross references held by this page:\n");
355
      dump_held_xrefs(dp, f);
356
 
357
      fclose(f);
358
    }
359
    sigsegv_state++;
360
  case 3:
361
    /* Dump the contents of the stack */
362
    printf("Stack dump: ");
363
    fflush(stdout);
364
 
365
    num_trace = backtrace(trace, 10);
366
 
367
    trace_names = backtrace_symbols(trace, num_trace);
368
 
369
    stack = get_sp();
370
    printf("(of stack at %p, base: %p)\n", stack, rec_stack_base);
371
    fflush(stdout);
372
    for(i = 0; stack < rec_stack_base; i++, stack += 4) {
373
      printf(" <%i> 0x%08x", i, *(uint32_t *)stack);
374
      /* Try to find a symbolic name with this entry */
375
      for(j = 0; j < num_trace; j++) {
376
        if(trace[j] == *(void **)stack)
377
          printf(" <%s>", trace_names[j]);
378
      }
379
      printf("\n");
380
      fflush(stdout);
381
    }
382
    sigsegv_state++;
383
  case 4:
384
    sim_done();
385
  }
386
}
387
 
388
void dump_xrefs(struct dyn_page *dp, FILE *f)
389
{
390
  struct x_ref *xref;
391
 
392
  fprintf(f, "--- Cross reference dump for %"PRIxADDR" at %p ---\n",
393
          dp->or_page, dp->host_page);
394
  for(xref = dp->xrefs; xref; xref = xref->next) {
395
    fprintf(f, "x-refed or location: 0x%"PRIxADDR", host-location: %p, ref: %i\n",
396
            xref->or_addr, xref->dyn_addr, xref->ref);
397
  }
398
  fprintf(f, "--- Cross reference dump end ---\n");
399
}
400
 
401
void dump_held_xrefs(struct dyn_page *dp, FILE *f)
402
{
403
  struct x_ref **xrefs;
404
 
405
  fprintf(f, "--- Held cross reference dump for %"PRIxADDR" at %p ---\n",
406
          dp->or_page, dp->host_page);
407
  for(xrefs = dp->held_xrefs; *xrefs; xrefs++)
408
    fprintf(f, "Holds an x-ref to 0x%"PRIxADDR", host-location: %p, ref: %i\n",
409
            (*xrefs)->or_addr, (*xrefs)->dyn_addr, (*xrefs)->ref);
410
  fprintf(f, "--- Held cross reference dump end ---\n");
411
}
412
 
413
static void add_to_dp(struct dyn_page *new)
414
{
415
  struct dyn_page *cur;
416
  struct dyn_page *prev;
417
 
418
  /* Find the location to insert the address */
419
  for(cur = cpu_state.dyn_pages, prev = NULL; cur; prev = cur, cur = cur->next) {
420
    if(cur->or_page > new->or_page)
421
      break;
422
  }
423
 
424
  if(prev)
425
    prev->next = new;
426
  else
427
    cpu_state.dyn_pages = new;
428
  new->next = cur;
429
}
430
 
431
struct dyn_page *new_dp(oraddr_t page)
432
{
433
  struct dyn_page *dp = malloc(sizeof(struct dyn_page));
434
  dp->or_page = ADDR_PAGE(page);
435
 
436
  /* Allocate xref terminator */
437
  dp->xrefs = NULL;
438
 
439
  dp->held_xrefs = malloc(sizeof(struct x_ref *));
440
  dp->held_xrefs[0] = NULL;
441
 
442
  dp->host_len = 0;
443
  dp->host_page = NULL;
444
  dp->dirty = 1;
445
 
446
  add_to_dp(dp);
447
  return dp;
448
}
449
 
450
struct dyn_page *find_dynd_page(oraddr_t addr)
451
{
452
  struct dyn_page *cur = cpu_state.dyn_pages;
453
 
454
  addr &= ~(ADDR_C(PAGE_LEN) - 1);
455
  while(cur) {
456
    if(cur->or_page == addr)
457
      return cur;
458
    if(cur->or_page > addr)
459
      return NULL; /* The dyn_page linked list is ordered */
460
    cur = cur->next;
461
  }
462
  return NULL;
463
}
464
 
465
/* Finds the dynamicly recompiled location of the given or address */
466
struct x_ref *find_host_x_ref(struct x_ref *x_refs, oraddr_t addr)
467
{
468
  /* FIXME: Optimise this by knowing that the x_refs array is orderd */
469
  while(x_refs && (x_refs->or_addr != addr)) x_refs = x_refs->next;
470
 
471
  return x_refs;
472
}
473
 
474
static void remove_xref(struct dyn_page *dp, struct x_ref *xref)
475
{
476
  struct x_ref *prev_xref;
477
 
478
  if(dp->xrefs == xref) {
479
    dp->xrefs = xref->next;
480
    free(xref);
481
    return;
482
  }
483
 
484
  prev_xref = dp->xrefs;
485
  while(prev_xref->next != xref)
486
    prev_xref = prev_xref->next;
487
 
488
  prev_xref->next = xref->next;
489
  free(xref);
490
}
491
 
492
struct x_ref *find_held_x_ref(struct x_ref **held_xrefs, oraddr_t or_addr)
493
{
494
  /* FIXME: Order this list in add_to_held_xrefs below and optimise this */
495
  while(*held_xrefs && ((*held_xrefs)->or_addr != or_addr)) held_xrefs++;
496
  return *held_xrefs;
497
}
498
 
499
void add_to_held_xrefs(struct dyn_page *dp, struct x_ref *xref)
500
{
501
  unsigned int i;
502
 
503
  for(i = 0; dp->held_xrefs[i]; i++);
504
 
505
  dp->held_xrefs = realloc(dp->held_xrefs, sizeof(struct x_ref *) * (i + 2));
506
  dp->held_xrefs[i] = xref;
507
  dp->held_xrefs[++i] = NULL;
508
}
509
 
510
/* This is called whenever the immu is either enabled/disabled or reconfigured
511
 * while enabled.  This checks if an itlb miss would occour and updates the immu
512
 * hit delay counter */
513
void recheck_immu(int got_en_dis)
514
{
515
  oraddr_t addr = get_pc();
516
  extern int immu_ex_from_insn;
517
 
518
  if(cpu_state.delay_insn) {
519
    /* If an instruction pagefault or ITLB would occur, it must appear to have
520
     * come from the jumped-to address */
521
    if(ADDR_PAGE(addr) == ADDR_PAGE(cpu_state.pc_delay)) {
522
      immu_ex_from_insn = 1;
523
      immu_translate(addr + 4);
524
      immu_ex_from_insn = 0;
525
      runtime.sim.mem_cycles = 0;
526
    }
527
    return;
528
  }
529
 
530
  if(ADDR_PAGE(addr) == ADDR_PAGE(addr + 4)) {
531
    /* If the next instruction is on another page then the immu will be checked
532
     * when the jump to the next page happens */
533
    immu_ex_from_insn = 1;
534
    immu_translate(addr + 4);
535
    immu_ex_from_insn = 0;
536
    /* If we had am immu hit then runtime.sim.mem_cycles will hold the value
537
     * config.immu.hitdelay, but this value is added to the cycle when the next
538
     * instruction is run */
539
    runtime.sim.mem_cycles = 0;
540
  }
541
  /* Only update the cycle decrementer if the mmu got enabled or disabled */
542
  if(got_en_dis == IMMU_GOT_ENABLED)
543
    /* Add the mmu hit delay to the cycle counter */
544
    upd_cycles_dec(cpu_state.curr_page->delayr - config.immu.hitdelay);
545
  else if(got_en_dis == IMMU_GOT_DISABLED) {
546
    upd_cycles_dec(cpu_state.curr_page->delayr);
547
    /* Since we updated the cycle decrementer above the immu hit delay will not
548
     * be added to the cycle counter for this instruction.  Compensate for this
549
     * by adding it now */
550
    /* FIXME: This is not correct here.  In the complex execution model the hit
551
     * delay is added to runtime.sim.mem_cycles which is only joined with the
552
     * cycle counter after analysis() and before the scheduler would run.
553
     * Therefore the scheduler will still be correct but analysis() will produce
554
     * wrong results just for this one instruction. */
555
    add_to_cycles(config.immu.hitdelay);
556
  }
557
}
558
 
559
/* Runs the scheduler.  Called from except_handler (and dirtyfy_page below) */
560
void run_sched_out_of_line(int add_normal)
561
{
562
  int brk;
563
  oraddr_t pc = get_pc();
564
 
565
  if(!cpu_state.ts_current)
566
    upd_reg_from_t(pc);
567
 
568
  if(add_normal && do_stats) {
569
    cpu_state.iqueue.insn_addr = pc;
570
    cpu_state.iqueue.insn = eval_insn_direct(pc, &brk, 1);
571
    cpu_state.iqueue.insn_index = insn_decode(cpu_state.iqueue.insn);
572
    analysis(&cpu_state.iqueue);
573
  }
574
 
575
  /* Run the scheduler */
576
  if(add_normal)
577
    sched_add_cycles();
578
 
579
  op_join_mem_cycles();
580
  upd_sim_cycles();
581
  if(scheduler.job_queue->time <= 0)
582
    do_scheduler();
583
}
584
 
585
/* Signals a page as dirty */
586
void dirtyfy_page(struct dyn_page *dp)
587
{
588
  struct x_ref **held_xrefs;
589
  struct x_ref *xref;
590
  oraddr_t check;
591
 
592
  printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
593
 
594
  /* decrease the reference counts of the xrefs that we hold */
595
  for(held_xrefs = dp->held_xrefs; *held_xrefs; held_xrefs++)
596
    (*held_xrefs)->ref--;
597
  dp->held_xrefs = realloc(dp->held_xrefs, sizeof(struct x_ref *));
598
  dp->held_xrefs[0] = NULL;
599
 
600
  dp->dirty = 1;
601
 
602
  /* If the execution is currently in the page that was touched then recompile
603
   * it now and jump back to the point of execution */
604
  check = cpu_state.delay_insn ? cpu_state.pc_delay : get_pc() + 4;
605
  if(ADDR_PAGE(check) == dp->or_page) {
606
    run_sched_out_of_line(1);
607
    if(!(xref = find_host_x_ref(dp->xrefs, check))) {
608
      xref = add_to_xrefs(dp, check);
609
      add_to_held_xrefs(dp, xref);
610
    } else {
611
      if(!find_held_x_ref(dp->held_xrefs, check)) {
612
        add_to_held_xrefs(dp, xref);
613
        xref->ref++;
614
      }
615
    }
616
    recompile_page(dp);
617
 
618
    cpu_state.delay_insn = 0;
619
 
620
    /* Jump out to the next instruction */
621
    or_longjmp(xref->dyn_addr);
622
  }
623
}
624
 
625
static void ship_gprs_out_t(struct op_queue *opq, int end, unsigned int *reg_t)
626
{
627
  int i;
628
 
629
  for(i = 0; i < NUM_T_REGS; i++) {
630
    if(reg_t[i] < 32)
631
      gen_op_move_gpr_t[i][reg_t[i]](opq, end);
632
  }
633
}
634
 
635
static int find_unused_t(unsigned int *pres_t, unsigned int *reg_t)
636
{
637
  int empty = -1; /* Invalid */
638
  int i;
639
 
640
  /* Try to find a temporary that does not contain a register and is not
641
   * needed to be preserved */
642
  for(i = 0; i < NUM_T_REGS; i++) {
643
    if(!pres_t[i]) {
644
      empty = i;
645
      if(reg_t[i] > 31)
646
        return i;
647
    }
648
  }
649
  return empty;
650
}
651
 
652
/* Checks if there is enough space in dp->host_page, if not grow it */
653
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
654
                       unsigned int amount)
655
{
656
  unsigned int used = cur - dp->host_page;
657
 
658
  /* The array is long enough */
659
  if((used + amount) <= *len)
660
    return cur;
661
 
662
  /* Reallocate */
663
  *len += RECED_PAGE_ENLARGE_BY;
664
 
665
  if(!(dp->host_page = realloc(dp->host_page, *len))) {
666
    fprintf(stderr, "OOM\n");
667
    exit(1);
668
  }
669
 
670
  return dp->host_page + used;
671
}
672
 
673
/* Adds an operation to the opq */
674
void add_to_opq(struct op_queue *opq, int end, int op)
675
{
676
  if(opq->num_ops == opq->ops_len) {
677
    opq->ops_len += OPS_ENLARGE_BY;
678
    if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
679
      fprintf(stderr, "OOM\n");
680
      exit(1);
681
    }
682
  }
683
 
684
  if(end)
685
    opq->ops[opq->num_ops] = op;
686
  else {
687
    /* Shift everything over by one */
688
    memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
689
    opq->ops[0] = op;
690
  }
691
 
692
  opq->num_ops++;
693
}
694
 
695
/* Adds a parameter to the opq */
696
void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
697
{
698
  if(opq->num_ops_param == opq->ops_param_len) {
699
    opq->ops_param_len += OPS_ENLARGE_BY * sizeof(int);
700
    if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len))) {
701
      fprintf(stderr, "OOM\n");
702
      exit(1);
703
    }
704
  }
705
 
706
  if(end)
707
    opq->ops_param[opq->num_ops_param] = param;
708
  else {
709
    /* Shift everything over by one */
710
    memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
711
    opq->ops_param[0] = param;
712
  }
713
 
714
  opq->num_ops_param++;
715
}
716
 
717
/* Function to guard against rogue ret instructions in the operations */
718
void dyn_ret_stack_prot(void)
719
{
720
  fprintf(stderr, "An operation (I have no clue which) has a ret statement in it\n");
721
  fprintf(stderr, "Good luck debugging it!\n");
722
 
723
  exit(1);
724
}
725
 
726
/* Jumps out to some Openrisc address */
727
void jump_dyn_code(oraddr_t addr)
728
{
729
  set_pc(addr);
730
  do_jump(addr);
731
}
732
 
733
/* Initialises the recompiler */
734
void init_dyn_recomp(void)
735
{
736
  struct sigaction sigact;
737
  struct op_queue *opq;
738
  struct x_ref *xref;
739
  unsigned int i;
740
 
741
  cpu_state.opqs = NULL;
742
 
743
  /* Allocate the operation queue list (+1 for the page chaining) */
744
  for(i = 0; i < (PAGE_LEN / 4) + 1; i++) {
745
    if(!(opq = malloc(sizeof(struct op_queue)))) {
746
      fprintf(stderr, "OOM\n");
747
      exit(1);
748
    }
749
 
750
    /* initialise some fields */
751
    opq->ops_len = 0;
752
    opq->ops = NULL;
753
    opq->ops_param_len = 0;
754
    opq->ops_param = NULL;
755
 
756
    if(cpu_state.opqs)
757
      cpu_state.opqs->prev = opq;
758
 
759
    opq->next = cpu_state.opqs;
760
    cpu_state.opqs = opq;
761
  }
762
 
763
  opq->prev = NULL;
764
 
765
  /* Allocate the x-ref structures that will be used for the infinite loop
766
   * instruction (l.j 0).  Allocate a whole page's worth just to make sure that
767
   * we will have enough */
768
  for(i = 0; i < (PAGE_LEN / 4); i++) {
769
    if(!(xref = malloc(sizeof(struct x_ref)))) {
770
      fprintf(stderr, "Out-of-memory while allocateing x-ref structures\n");
771
      exit(1);
772
    }
773
    xref->next = cpu_state.inf_xrefs;
774
    cpu_state.inf_xrefs = xref;
775
  }
776
 
777
  /* Just some value that we'll use as the base for our stack */
778
  rec_stack_base = get_sp();
779
 
780
  cpu_state.curr_page = NULL;
781
  cpu_state.dyn_pages = NULL;
782
 
783
  /* Register our segmentation fault handler */
784
  sigact.sa_sigaction = dyn_sigsegv_debug;
785
  memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
786
  sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
787
  if(sigaction(SIGSEGV, &sigact, NULL))
788
    printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
789
 
790
  /* Allocate memory for the rfe corss reference cache */
791
  if(!(cpu_state.rfe_held_xrefs = malloc(sizeof(struct xref *) * NUM_RFE_HELD))) {
792
    printf("OOM\n");
793
    exit(1);
794
  }
795
  cpu_state.rfe_held_xref_pos = 0;
796
  memset(cpu_state.rfe_held_xrefs, 0, sizeof(struct xref *) * NUM_RFE_HELD);
797
 
798
  init_dyn_rec();
799
 
800
  /* FIXME: Find a better place for this */
801
    { /* Needed by execution */
802
      extern int do_stats;
803
      do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
804
              || config.sim.history || config.sim.exe_log;
805
    }
806
 
807
  printf("Recompile engine up and running\n");
808
}
809
 
810
/* rec_page is a physical address */
811
void recompile_page(struct dyn_page *dyn)
812
{
813
  unsigned int j, k;
814
  unsigned int reg_t[NUM_T_REGS];
815
  unsigned int pres_t[NUM_T_REGS]; /* Which temporary to preserve */
816
  unsigned int insn_index;
817
  int delay_insn = 0; /* Is the next instruction to be decoded in a delay slot*/
818
  enum insn_type delay_insn_type = 0;
819
  uint32_t insn;
820
  int param_t[3]; /* Which temporary the parameters reside in */
821
  int param_r[3]; /* is parameter a register */
822
  orreg_t param[3];
823
  int param_num;
824
  struct op_queue *opq = NULL;
825
  oraddr_t rec_addr = dyn->or_page;
826
  oraddr_t rec_page = dyn->or_page;
827
  struct x_ref *xref;
828
  int breakp;
829
  struct dyn_page *prev_dp;
830
 
831
  struct insn_op_struct *opd;
832
 
833
  /* The start of the next page */
834
  rec_page += PAGE_LEN;
835
 
836
  printf("Recompileing page %"PRIxADDR"\n", rec_addr);
837
  fflush(stdout);
838
 
839
  /* Mark all temporaries as not containing a register */
840
  for(j = 0; j < NUM_T_REGS; j++)
841
    reg_t[j] = 32; /* Out-of-range registers */
842
 
843
  dyn->delayr = -verify_memoryarea(rec_addr)->delayr;
844
 
845
  dyn->carrys_delay_slot = 0;
846
 
847
  /* Check if the previous page carries a delay slot over to this page */
848
  if((prev_dp = find_dynd_page(rec_addr - PAGE_LEN)))
849
    delay_insn = prev_dp->carrys_delay_slot;
850
 
851
  for(opq = cpu_state.opqs; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
852
    opq->num_ops = 0;
853
    opq->num_ops_param = 0;
854
    opq->jump_local = 0;
855
 
856
    opq->insn_addr = rec_addr;
857
 
858
    breakp = 0;
859
    insn = eval_insn(rec_addr, &breakp);
860
 
861
    /* FIXME: If a breakpoint is set at this location, insert exception code */
862
    if(breakp) {
863
      fprintf(stderr, "FIXME: Insert breakpoint code\n");
864
    }
865
 
866
    insn_index = insn_decode(insn);
867
 
868
    /* FIXME: Optimise this by knowing that dyn->x_refs is ordered (ie. Don't
869
     *        call find_host_x_ref) */
870
    /* Check if this location is cross referenced */
871
    if((xref = find_host_x_ref(dyn->xrefs, rec_addr))) {
872
      /* If the x-refs reference count reached zero remove it */
873
      if(xref->ref) {
874
        /* If the current address is cross-referenced, the temporaries shall be
875
         * in an undefined state, so we must assume that no registers reside in
876
         * them */
877
        /* Ship out the current set of registers from the temporaries */
878
        if(opq->prev) {
879
          ship_gprs_out_t(opq->prev, 1, reg_t);
880
        }
881
        for(j = 0; j < NUM_T_REGS; j++)
882
          reg_t[j] = 32;
883
      } else {
884
        /* Remove x-ref */
885
        remove_xref(dyn, xref);
886
      }
887
    }
888
 
889
    memcpy(opq->reg_t, reg_t, sizeof(reg_t));
890
 
891
    /* Check if we have an illegal instruction */
892
    if(insn_index == -1) {
893
      gen_l_invalid(opq, param_t, param, delay_insn);
894
      if(delay_insn) {
895
        /* There is no need to do any jump handleing stuff as the instruction
896
         * will generate an exception */
897
        if(opq->prev->jump_local == 2) {
898
          opq->prev->xref->next = cpu_state.inf_xrefs;
899
          cpu_state.inf_xrefs = opq->prev->xref;
900
        }
901
        opq->prev->jump_local = 0;
902
        delay_insn = 0;
903
      }
904
      continue;
905
    }
906
 
907
    /* figure out instruction operands */
908
    for(j = 0; j < NUM_T_REGS; j++)
909
      pres_t[j] = 0;
910
 
911
    param_t[0] = T_NONE;
912
    param_t[1] = T_NONE;
913
    param_t[2] = T_NONE;
914
    param_r[0] = 0;
915
    param_r[1] = 0;
916
    param_r[2] = 0;
917
    param_num = 0;
918
 
919
    opd = op_start[insn_index];
920
    while(1) {
921
      param[param_num] = eval_operand_val(insn, opd);
922
 
923
      if(opd->type & OPTYPE_REG) {
924
        /* check which temporary the register is in, if any */
925
        for(j = 0; j < NUM_T_REGS; j++) {
926
          if(reg_t[j] == param[param_num]) {
927
            param_t[param_num] = j;
928
            pres_t[j] = 1;
929
          }
930
        }
931
      }
932
 
933
      param_num++;
934
      while(!(opd->type & OPTYPE_OP)) opd++;
935
      if(opd->type & OPTYPE_LAST)
936
        break;
937
      opd++;
938
    }
939
 
940
    opd = op_start[insn_index];
941
 
942
    /* Before an exception takes place, all registers must be stored. */
943
    if((or32_opcodes[insn_index].func_unit == it_exception)) {
944
      if(opq->prev) {
945
        ship_gprs_out_t(opq->prev, 1, reg_t);
946
        for(j = 0; j < NUM_T_REGS; j++) {
947
          opq->prev->reg_t[j] = 32;
948
          reg_t[j] = 32;
949
        }
950
      }
951
    }
952
 
953
    for(j = 0; j < param_num; j++, opd++) {
954
      while(!(opd->type & OPTYPE_OP)) opd++;
955
      if(!(opd->type & OPTYPE_REG))
956
        continue;
957
 
958
      /* Never, ever, move r0 into a temporary */
959
      if(!param[j])
960
        continue;
961
 
962
      /* Check if this register has been moved into a temporary in a previous
963
       * operand */
964
      for(k = 0; k < NUM_T_REGS; k++) {
965
        if(reg_t[k] == param[j]) {
966
          /* Yes, this register is already in a temporary */
967
          pres_t[k] = 1;
968
          reg_t[k] = param[j];
969
          param_t[j] = k;
970
          break;
971
        }
972
      }
973
      if(k != NUM_T_REGS)
974
        continue;
975
 
976
      if((param_t[j] != T_NONE))
977
        continue;
978
 
979
      /* Search for an unused temporary */
980
      k = find_unused_t(pres_t, reg_t);
981
      if(reg_t[k] < 32) {
982
        gen_op_move_gpr_t[k][reg_t[k]](opq->prev, 1);
983
        opq->reg_t[k] = 32;
984
      }
985
      pres_t[k] = 1;
986
      reg_t[k] = param[j];
987
      param_t[j] = k;
988
      /* FIXME: Only generate code to move the register into a temporary if it
989
       *        is used as a source operand */
990
      gen_op_move_t_gpr[k][reg_t[k]](opq, 1);
991
    }
992
 
993
    /* FIXME: Do this in a more elegent way */
994
    if(!strncmp(or32_opcodes[insn_index].name, "l.jal", 5)) {
995
      /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
996
       * a temporary.  The problem is that the l.jal(r) instruction stores the
997
       * `return address' in LINK_REGNO.  The temporaries are shiped out only
998
       * after the delay slot instruction has executed and so it overwrittes the
999
       * `return address'. */
1000
      for(k = 0; k < NUM_T_REGS; k++) {
1001
        if(reg_t[k] == LINK_REGNO) {
1002
          gen_op_move_gpr_t[k][LINK_REGNO](opq, 1);
1003
          reg_t[k] = 32;
1004
          opq->reg_t[k] = 32;
1005
          break;
1006
        }
1007
      }
1008
    }
1009
 
1010
    /* Store the state of the temporaries into dyn->ts */
1011
    dyn->ts[(rec_addr & (PAGE_LEN - 1)) / 2] = 0;
1012
    if(reg_t[0] < 32)
1013
      dyn->ts[(rec_addr & (PAGE_LEN - 1)) / 2] = reg_t[0];
1014
    if(reg_t[1] < 32)
1015
      dyn->ts[(rec_addr & (PAGE_LEN - 1)) / 2] |= reg_t[1] << 5;
1016
    if(reg_t[2] < 32)
1017
      dyn->ts[(rec_addr & (PAGE_LEN - 1)) / 2] |= reg_t[2] << 10;
1018
 
1019
    /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
1020
     * effective address needs to be calculated before the instruction is
1021
     * simulated */
1022
    if(do_stats) {
1023
      /* Find any disposition in the instruction */
1024
      opd = op_start[insn_index];
1025
      for(j = 0; j < param_num; j++, opd++) {
1026
        while(!(opd->type & OPTYPE_OP)) opd++;
1027
        if(!(opd->type & OPTYPE_DIS))
1028
          continue;
1029
 
1030
        if(!param[j + 1])
1031
          gen_op_store_insn_ea(opq, 1, param[j]);
1032
        else
1033
          calc_insn_ea_table[param_t[j + 1]](opq, 1, param[j]);
1034
      }
1035
    }
1036
 
1037
    or32_opcodes[insn_index].exec(opq, param_t, param, delay_insn);
1038
 
1039
    /* If any sort of analysis is done, store all temporaries and run
1040
     * analysis() */
1041
    if(do_stats) {
1042
      ship_gprs_out_t(opq, 1, reg_t);
1043
      for(j = 0; j < NUM_T_REGS; j++)
1044
        reg_t[j] = 32;
1045
 
1046
      gen_op_analysis(opq, 1, insn_index, insn);
1047
    }
1048
 
1049
    /* The call to join_mem_cycles() could be put into the individual operations
1050
     * that emulate the load/store instructions, but then it would be added to
1051
     * the cycle counter before analysis() is called, which not how the complex
1052
     * execution modell does it. */
1053
    if((or32_opcodes[insn_index].func_unit == it_load) ||
1054
       (or32_opcodes[insn_index].func_unit == it_store))
1055
      gen_op_join_mem_cycles(opq, 1);
1056
 
1057
    /* If a delay sloted instruction is in the delay slot, avoid doing a jump on
1058
     * the first delay sloted instruction.  The problem with not doing the above
1059
     * is that the 0x00000000 instruction is a jump instruction, which is used
1060
     * for padding, and if there ends up being a jump instruction directly after
1061
     * some padding and the code jumps to this location (as with the mmu test)
1062
     * the jump instruction will set cpu_state.pc_delay but code will get
1063
     * generated after the jump instruction and before the delay slot
1064
     * instruciton to check cpu_state.pc_delay and jump out if it is set and so
1065
     * we end up jumping out to the padding instruction.  With some thought, the
1066
     * 0x00000000 opcode could really have been encoded to some arithmetic
1067
     * operation that would end up nop-ing (or better yet, to the l.nop 0
1068
     * instruction itself) */
1069
    /* If we came up to a page local jump and because it is the delay slot of
1070
     * another delay sloted instruction the case below is skipped and
1071
     * opq->prev->jump_local will remain set to 1, fix this by reseting it now*/
1072
    if(delay_insn && ((or32_opcodes[insn_index].func_unit == it_jump) ||
1073
                      (or32_opcodes[insn_index].func_unit == it_branch))) {
1074
      /* We don't generate code to do the relocation so there will be none.
1075
       * Avoid haveing a reference to it */
1076
      /* Also remove the cross reference to it */
1077
      if(opq->prev) {
1078
        if(opq->prev->jump_local == 2) {
1079
          opq->prev->xref->next = cpu_state.inf_xrefs;
1080
          cpu_state.inf_xrefs = opq->prev->xref;
1081
        }
1082
        opq->prev->jump_local = 0;
1083
      }
1084
      delay_insn = 0;
1085
    }
1086
 
1087
    /* In the case of an instruction in the delay slot the pc must be updated
1088
     * before op_do_sched runs because if it so happens to generate an exception
1089
     * it will think that we are still executeing the delay slot instruction
1090
     * which infact we have just executed and then SPR_EPCR_BASE will end up
1091
     * pointing to the delay slot instruction, which is wrong.  If the delay
1092
     * slot instruction is an exception instruction (l.trap/l.sys) the exception
1093
     * must appear to have been generated in the delay slot */
1094
    if(delay_insn && (or32_opcodes[insn_index].func_unit != it_exception)) {
1095
      if(xref || (delay_insn_type == it_branch))
1096
        gen_op_set_pc_preemt_check(opq, 1);
1097
      else /* delay_insn_tyte == it_jump */
1098
        gen_op_set_pc_preemt(opq, 1);
1099
      /* Move temporaries to their permanent storage */
1100
      ship_gprs_out_t(opq, 1, reg_t);
1101
    }
1102
 
1103
    /* Same reason as for the above case */
1104
    if(or32_opcodes[insn_index].func_unit == it_exception) {
1105
      /* FIXME: Do the instruction switch below in a more elegent way */
1106
      if(!strcmp(or32_opcodes[insn_index].name, "l.rfe")) {
1107
        gen_op_set_rfe_pc(opq, 1);
1108
      } else if(!strcmp(or32_opcodes[insn_index].name, "l.sys")) {
1109
        gen_op_set_except_pc(opq, 1, EXCEPT_SYSCALL - 4);
1110
      } else { /* or32_opcodes[insn_index].name == "l.trap" */
1111
        gen_op_set_except_pc(opq, 1, EXCEPT_TRAP - 4);
1112
      }
1113
      gen_op_set_ts_current(opq, 1);
1114
    }
1115
 
1116
    gen_op_do_sched(opq, 1);
1117
 
1118
    /* If this is an exception instruction then we still need to perform the
1119
     * exception */
1120
    if(or32_opcodes[insn_index].func_unit == it_exception) {
1121
      /* FIXME: Do the instruction switch below in a more elegent way */
1122
      if(!strcmp(or32_opcodes[insn_index].name, "l.rfe")) {
1123
        gen_op_rfe(opq, 1);
1124
      } else if(!strcmp(or32_opcodes[insn_index].name, "l.sys")) {
1125
        gen_op_do_except(opq, 1, EXCEPT_SYSCALL);
1126
      } else { /* or32_opcodes[insn_index].name == "l.trap" */
1127
        gen_op_do_except(opq, 1, EXCEPT_TRAP);
1128
      }
1129
    }
1130
 
1131
    /* FIXME: If the delay slot is cross referenced after we have stuck the jump
1132
     * instruction in the operations queue we will genererate temporary->
1133
     * register code after the jump, which will be unreachable.  This is no
1134
     * problem as all temporaries are stored in anticipation for a jump. */
1135
    /* FIXME: If the delay slot is cross referenced we should generate the
1136
     * conditional jump code as we do below.  This will not happen if the delay
1137
     * slot is cross referenced after we generate the operations for the jump */
1138
    /* FIXME: If the instruction in the delay slot is an exception instruction
1139
     * the code that we generate below will be unreachable since the exception
1140
     * instruction jumps to the exection vector */
1141
    /* Generate code to jump out to the proper location */
1142
    if(delay_insn) {
1143
      for(j = 0; j < NUM_T_REGS; j++)
1144
        reg_t[j] = 32;
1145
 
1146
      if(xref || (delay_insn_type == it_branch)) {
1147
        /* If the delay-slot instruction is cross referenced, then we have to
1148
         * check env->delay_insn */
1149
        if(opq->prev && opq->prev->jump_local) {
1150
          gen_op_jmp_imm_check(opq, 1, 0);
1151
          opq->prev->jump_local_loc = &opq->ops_param[opq->num_ops_param - 1];
1152
        } else {
1153
          gen_op_do_jump_check(opq, 1);
1154
        }
1155
      } else if(delay_insn_type == it_jump) {
1156
        gen_op_clear_delay_insn(opq, 1);
1157
        if(opq->prev && opq->prev->jump_local) {
1158
          /* The 0 will get patched when the page-local jumps get patched */
1159
          gen_op_jmp_imm(opq, 1, 0);
1160
          /* FIXME: opq->ops_param is realloced with realloc and so we risk a
1161
           * reallocation in which the location ends up moveing in memory */
1162
          opq->prev->jump_local_loc = &opq->ops_param[opq->num_ops_param - 1];
1163
        } else {
1164
          gen_op_do_jump(opq, 1);
1165
        }
1166
      }
1167
      delay_insn = 0;
1168
    }
1169
 
1170
    /* Set flag for next instruction to be in a delay slot */
1171
    if((or32_opcodes[insn_index].func_unit == it_jump) ||
1172
       (or32_opcodes[insn_index].func_unit == it_branch)) {
1173
      delay_insn = 1;
1174
      delay_insn_type = or32_opcodes[insn_index].func_unit;
1175
    }
1176
  }
1177
 
1178
  if(delay_insn) {
1179
    dyn->carrys_delay_slot = 1;
1180
    /* Quick hack to avoid dereferencing an uninitialised pointer below with
1181
     * *opq->jump_local_loc */
1182
    if(opq->prev->jump_local == 2) {
1183
      /* FIXME: In this case the delay slot instruction won't get executed */
1184
      opq->prev->xref->next = cpu_state.inf_xrefs;
1185
      cpu_state.inf_xrefs = opq->prev->xref;
1186
    }
1187
    opq->prev->jump_local = 0;
1188
  }
1189
 
1190
  dyn->dirty = 0;
1191
 
1192
  /* Ship temporaries out to the corrisponding registers */
1193
  ship_gprs_out_t(opq->prev, 1, reg_t);
1194
 
1195
  opq->num_ops = 0;
1196
  opq->num_ops_param = 0;
1197
  opq->jump_local = 0;
1198
 
1199
  /* Insert code to jump to the next page */
1200
  gen_op_set_ts_current(opq, 1);
1201
  gen_op_do_jump_pc(opq, 1);
1202
 
1203
  /* Generate the code */
1204
  gen_code(cpu_state.opqs, dyn);
1205
 
1206
  /* Patch the x-ref table */
1207
  for(xref = dyn->xrefs; xref; xref = xref->next)
1208
    xref->dyn_addr = dyn->host_page + (unsigned int)xref->dyn_addr;
1209
 
1210
  /* Search for page-local jumps */
1211
  for(opq = cpu_state.opqs; opq; opq = opq->next) {
1212
    if(opq->jump_local) {
1213
      if(opq->jump_local == 2)
1214
        /* This cross reference was not patched above so patch it now */
1215
        opq->xref->dyn_addr = dyn->host_page + (unsigned int)opq->xref->dyn_addr;
1216
 
1217
      *opq->jump_local_loc = (unsigned int)opq->xref->dyn_addr;
1218
      if(opq->jump_local == 2) {
1219
        /* Return the xref to the pool of infinite loop cross references */
1220
        opq->xref->next = cpu_state.inf_xrefs;
1221
        cpu_state.inf_xrefs = opq->xref;
1222
      }
1223
    }
1224
  }
1225
 
1226
  /* Patch the relocations */
1227
  patch_relocs(cpu_state.opqs, dyn->host_page);
1228
 
1229
  /* FIXME: Fix the issue below in a more elegent way */
1230
  /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
1231
   * updated but the recompiler expectes it to start a 0, so reset it */
1232
  runtime.sim.mem_cycles = 0;
1233
 
1234
#if 0
1235
  This is very usefull during debuging
1236
  /* Count the number of infinite loop cross references (to make sure that we
1237
   * returned them all) */
1238
  for(j = 0, xref = cpu_state.inf_xrefs; xref; xref = xref->next) {
1239
    printf("Cross reference to %"PRIxADDR" is here\n", xref->or_addr);
1240
    j++;
1241
  }
1242
 
1243
  if(j != (PAGE_LEN / 4)) {
1244
    fprintf(stderr, "Infinite loop cross references are leaked!\n");
1245
    fprintf(stderr, "Number in free list now: %i, meant to be: %i\n", j, PAGE_LEN / 4);
1246
    exit(1);
1247
  }
1248
#endif
1249
 
1250
}
1251
 
1252
struct x_ref *add_to_xrefs(struct dyn_page *dp, oraddr_t addr)
1253
{
1254
  struct x_ref *new;
1255
  struct x_ref *cur;
1256
  struct x_ref *prev;
1257
 
1258
  new = malloc(sizeof(struct x_ref));
1259
 
1260
  new->ref = 1;
1261
  new->or_addr = addr;
1262
 
1263
  /* Find the location to insert the address */
1264
  for(cur = dp->xrefs, prev = NULL; cur; prev = cur, cur = cur->next) {
1265
    if(cur->or_addr > addr)
1266
      break;
1267
  }
1268
 
1269
  if(prev)
1270
    prev->next = new;
1271
  else
1272
    dp->xrefs = new;
1273
  new->next = cur;
1274
 
1275
  return new;
1276
}
1277
 
1278
/* Returns non-zero if the jump is into this page, 0 otherwise */
1279
static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
1280
{
1281
  struct dyn_page *dp;
1282
  int i;
1283
  struct x_ref *xref = NULL;
1284
  int *ops;
1285
 
1286
  /* Mark the jump as non page local if the delay slot instruction is on the
1287
   * next page to the jump instruction.  This should not be needed */
1288
  if((ADDR_PAGE(j_ea) != ADDR_PAGE(opq->insn_addr)) ||
1289
     (ADDR_PAGE(opq->insn_addr) != ADDR_PAGE(opq->insn_addr + 4)))
1290
    /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
1291
     * VIRTUAL offset and the next physical page may not be the next VIRTUAL
1292
     * page */
1293
    return 0;
1294
 
1295
  /* The jump is into the page currently undergoing dynamic recompilation */
1296
 
1297
  /* FIXME: It would be great if we didn't have to do this (find_dynd...) (it is
1298
   *        already passed to recompile_page) */
1299
  dp = find_dynd_page(j_ea);
1300
 
1301
  /* Check if we have already x-refed this location */
1302
  if((xref = find_host_x_ref(dp->xrefs, j_ea))) {
1303
    /* If we have already x-refed this location, don't x-ref it again */
1304
    if(!find_held_x_ref(dp->held_xrefs, j_ea)) {
1305
      xref->ref++;
1306
      add_to_held_xrefs(dp, xref);
1307
    }
1308
  } else {
1309
    /* Stick this address into the page's x-ref table */
1310
    xref = add_to_xrefs(dp, j_ea);
1311
    add_to_held_xrefs(dp, xref);
1312
  }
1313
 
1314
  opq->xref = xref;
1315
 
1316
  /* If we haven't got to the location of the jump, everything is ok */
1317
  if(j_ea > opq->insn_addr)
1318
    return 1;
1319
 
1320
  /* Insert temporary -> register code before the jump ea and register ->
1321
   * temporary at the x-ref address */
1322
  while(opq->insn_addr > j_ea) opq = opq->prev;
1323
  if(!opq->prev)
1324
    /* We're at the begining of a page, no need to do anything */
1325
    return 1;
1326
 
1327
  /* Found location, insert code */
1328
  ship_gprs_out_t(opq->prev, 1, opq->reg_t);
1329
 
1330
  for(i = 0; i < NUM_T_REGS; i++) {
1331
    if(opq->reg_t[i] < 32) {
1332
      gen_op_move_t_gpr[i][opq->reg_t[i]](opq, 0);
1333
      opq->reg_t[i] = 32;
1334
    }
1335
  }
1336
 
1337
  /* In the event of a page local jump that jumps backwards (l.j -4) the cross
1338
   * reference to the target may not have existed when the jump-ed to adress was
1339
   * recompiled and if the jump-ed to address is in the delay slot of another
1340
   * jump instruction an op_jmp_imm_check operation must be generated and not an
1341
   * op_jmp_imm operation */
1342
  for(ops = opq->ops, i = 0; i < opq->num_ops; i++, ops++) {
1343
    if(*ops == op_jmp_imm_indx)
1344
      *ops = op_jmp_imm_check_indx;
1345
    else if(*ops == op_set_pc_preemt_indx)
1346
      *ops = op_set_pc_preemt_check_indx;
1347
  }
1348
 
1349
  return 1;
1350
}
1351
 
1352
/*------------------------------[ Operation generation for an instruction ]---*/
1353
/* FIXME: Flag setting is not done in any instruction */
1354
/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
1355
 
1356
static const generic_gen_op clear_t[NUM_T_REGS] =
1357
 { gen_op_clear_t0, gen_op_clear_t1, gen_op_clear_t2 };
1358
 
1359
static const generic_gen_op move_t_t[NUM_T_REGS][NUM_T_REGS] = {
1360
/* param0 -> t0 */ { NULL, gen_op_move_t0_t1, gen_op_move_t0_t2 },
1361
/* param0 -> t1 */ { gen_op_move_t1_t0, NULL, gen_op_move_t1_t2 },
1362
/* param0 -> t2 */ { gen_op_move_t2_t0, gen_op_move_t2_t1, NULL } };
1363
 
1364
static const imm_gen_op mov_t_imm[NUM_T_REGS] =
1365
 { gen_op_t0_imm, gen_op_t1_imm, gen_op_t2_imm };
1366
 
1367
static const imm_gen_op l_add_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
1368
/* param0 -> t0 */ { gen_op_add_imm_t0_t0, gen_op_add_imm_t0_t1, gen_op_add_imm_t0_t2 },
1369
/* param0 -> t1 */ { gen_op_add_imm_t1_t0, gen_op_add_imm_t1_t1, gen_op_add_imm_t1_t2 },
1370
/* param0 -> t2 */ { gen_op_add_imm_t2_t0, gen_op_add_imm_t2_t1, gen_op_add_imm_t2_t2 } };
1371
 
1372
static const generic_gen_op l_add_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1373
/* param0 -> t0 */              {
1374
/* param0 -> t0, param1 -> t0 */ { gen_op_add_t0_t0_t0, gen_op_add_t0_t0_t1, gen_op_add_t0_t0_t2 },
1375
/* param0 -> t0, param1 -> t1 */ { gen_op_add_t0_t1_t0, gen_op_add_t0_t1_t1, gen_op_add_t0_t1_t2 },
1376
/* param0 -> t0, param1 -> t2 */ { gen_op_add_t0_t2_t0, gen_op_add_t0_t2_t1, gen_op_add_t0_t2_t2 } },
1377
/* param0 -> t1 */              {
1378
/* param0 -> t1, param1 -> t0 */ { gen_op_add_t1_t0_t0, gen_op_add_t1_t0_t1, gen_op_add_t1_t0_t2 },
1379
/* param0 -> t1, param1 -> t1 */ { gen_op_add_t1_t1_t0, gen_op_add_t1_t1_t1, gen_op_add_t1_t1_t2 },
1380
/* param0 -> t1, param1 -> t2 */ { gen_op_add_t1_t2_t0, gen_op_add_t1_t2_t1, gen_op_add_t1_t2_t2 } },
1381
/* param0 -> t2 */              {
1382
/* param0 -> t2, param1 -> t0 */ { gen_op_add_t2_t0_t0, gen_op_add_t2_t0_t1, gen_op_add_t2_t0_t2 },
1383
/* param0 -> t2, param1 -> t1 */ { gen_op_add_t2_t1_t0, gen_op_add_t2_t1_t1, gen_op_add_t2_t1_t2 },
1384
/* param0 -> t2, param1 -> t2 */ { gen_op_add_t2_t2_t0, gen_op_add_t2_t2_t1, gen_op_add_t2_t2_t2 } } };
1385
 
1386
void gen_l_add(struct op_queue *opq, int param_t[3], orreg_t param[3],
1387
               int delay_slot)
1388
{
1389
  if(!param[0])
1390
    /* Screw this, the operation shall do nothing */
1391
    return;
1392
 
1393
  if(!param[1] && !param[2]) {
1394
    /* Just clear param_t[0] */
1395
    clear_t[param_t[0]](opq, 1);
1396
    return;
1397
  }
1398
 
1399
  if(!param[2]) {
1400
    if(param[0] != param[1])
1401
      /* This just moves a register */
1402
      move_t_t[param_t[0]][param_t[1]](opq, 1);
1403
    return;
1404
  }
1405
 
1406
  if(!param[1]) {
1407
    /* Check if we are moveing an immediate */
1408
    if(param_t[2] == T_NONE) {
1409
      /* Yep, an immediate */
1410
      mov_t_imm[param_t[0]](opq, 1, param[2]);
1411
      return;
1412
    }
1413
    /* Just another move */
1414
    if(param[0] != param[2])
1415
      move_t_t[param_t[0]][param_t[2]](opq, 1);
1416
    return;
1417
  }
1418
 
1419
  /* Ok, This _IS_ an add... */
1420
  if(param_t[2] == T_NONE)
1421
    /* immediate */
1422
    l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
1423
  else
1424
    l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1425
}
1426
 
1427
static const generic_gen_op l_addc_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1428
/* param0 -> t0 */              {
1429
/* param0 -> t0, param1 -> t0 */ { gen_op_addc_t0_t0_t0, gen_op_addc_t0_t0_t1, gen_op_addc_t0_t0_t2 },
1430
/* param0 -> t0, param1 -> t1 */ { gen_op_addc_t0_t1_t0, gen_op_addc_t0_t1_t1, gen_op_addc_t0_t1_t2 },
1431
/* param0 -> t0, param1 -> t2 */ { gen_op_addc_t0_t2_t0, gen_op_addc_t0_t2_t1, gen_op_addc_t0_t2_t2 } },
1432
/* param0 -> t1 */              {
1433
/* param0 -> t1, param1 -> t0 */ { gen_op_addc_t1_t0_t0, gen_op_addc_t1_t0_t1, gen_op_addc_t1_t0_t2 },
1434
/* param0 -> t1, param1 -> t1 */ { gen_op_addc_t1_t1_t0, gen_op_addc_t1_t1_t1, gen_op_addc_t1_t1_t2 },
1435
/* param0 -> t1, param1 -> t2 */ { gen_op_addc_t1_t2_t0, gen_op_addc_t1_t2_t1, gen_op_addc_t1_t2_t2 } },
1436
/* param0 -> t2 */              {
1437
/* param0 -> t2, param1 -> t0 */ { gen_op_addc_t2_t0_t0, gen_op_addc_t2_t0_t1, gen_op_addc_t2_t0_t2 },
1438
/* param0 -> t2, param1 -> t1 */ { gen_op_addc_t2_t1_t0, gen_op_addc_t2_t1_t1, gen_op_addc_t2_t1_t2 },
1439
/* param0 -> t2, param1 -> t2 */ { gen_op_addc_t2_t2_t0, gen_op_addc_t2_t2_t1, gen_op_addc_t2_t2_t2 } } };
1440
 
1441
void gen_l_addc(struct op_queue *opq, int param_t[3], orreg_t param[3],
1442
                int delay_slot)
1443
{
1444
  if(!param[0])
1445
    /* Screw this, the operation shall do nothing */
1446
    return;
1447
 
1448
  /* FIXME: More optimisations !! (...and immediate...) */
1449
  l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1450
}
1451
 
1452
static const imm_gen_op l_and_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
1453
/* param0 -> t0 */ { gen_op_and_imm_t0_t0, gen_op_and_imm_t0_t1, gen_op_and_imm_t0_t2 },
1454
/* param0 -> t1 */ { gen_op_and_imm_t1_t0, gen_op_and_imm_t1_t1, gen_op_and_imm_t1_t2 },
1455
/* param0 -> t2 */ { gen_op_and_imm_t2_t0, gen_op_and_imm_t2_t1, gen_op_and_imm_t2_t2 } };
1456
 
1457
static const generic_gen_op l_and_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1458
/* param0 -> t0 */              {
1459
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_and_t0_t0_t1, gen_op_and_t0_t0_t2 },
1460
/* param0 -> t0, param1 -> t1 */ { gen_op_and_t0_t1_t0, gen_op_and_t0_t1_t1, gen_op_and_t0_t1_t2 },
1461
/* param0 -> t0, param1 -> t2 */ { gen_op_and_t0_t2_t0, gen_op_and_t0_t2_t1, gen_op_and_t0_t2_t2 } },
1462
/* param0 -> t1 */              {
1463
/* param0 -> t1, param1 -> t0 */ { gen_op_and_t1_t0_t0, gen_op_and_t1_t0_t1, gen_op_and_t1_t0_t2 },
1464
/* param0 -> t1, param1 -> t1 */ { gen_op_and_t1_t1_t0, NULL, gen_op_and_t1_t1_t2 },
1465
/* param0 -> t1, param1 -> t2 */ { gen_op_and_t1_t2_t0, gen_op_and_t1_t2_t1, gen_op_and_t1_t2_t2 } },
1466
/* param0 -> t2 */              {
1467
/* param0 -> t2, param1 -> t0 */ { gen_op_and_t2_t0_t0, gen_op_and_t2_t0_t1, gen_op_and_t2_t0_t2 },
1468
/* param0 -> t2, param1 -> t1 */ { gen_op_and_t2_t1_t0, gen_op_and_t2_t1_t1, gen_op_and_t2_t1_t2 },
1469
/* param0 -> t2, param1 -> t2 */ { gen_op_and_t2_t2_t0, gen_op_and_t2_t2_t1, NULL } } };
1470
 
1471
void gen_l_and(struct op_queue *opq, int param_t[3], orreg_t param[3],
1472
               int delay_slot)
1473
{
1474
  if(!param[0])
1475
    /* Screw this, the operation shall do nothing */
1476
    return;
1477
 
1478
  if(!param[1] || !param[2]) {
1479
    /* Just clear param_t[0] */
1480
    clear_t[param_t[0]](opq, 1);
1481
    return;
1482
  }
1483
 
1484
  if((param[0] == param[1] == param[2]) && (param_t[2] != T_NONE))
1485
    return;
1486
 
1487
  if(param_t[2] == T_NONE)
1488
    l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
1489
  else
1490
    l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1491
}
1492
 
1493
void gen_l_bf(struct op_queue *opq, int param_t[3], orreg_t param[3],
1494
              int delay_slot)
1495
{
1496
  opq->jump_local = find_jump_loc(opq->insn_addr + (orreg_t)(param[0] << 2), opq);
1497
  gen_op_check_flag(opq, 1, param[0] << 2);
1498
}
1499
 
1500
void gen_l_bnf(struct op_queue *opq, int param_t[3], orreg_t param[3],
1501
               int delay_slot)
1502
{
1503
  opq->jump_local = find_jump_loc(opq->insn_addr + (orreg_t)(param[0] << 2), opq);
1504
  gen_op_check_not_flag(opq, 1, param[0] << 2);
1505
}
1506
 
1507
static const generic_gen_op l_cmov_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1508
/* param0 -> t0 */              {
1509
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_cmov_t0_t0_t1, gen_op_cmov_t0_t0_t2 },
1510
/* param0 -> t0, param1 -> t1 */ { gen_op_cmov_t0_t1_t0, NULL, gen_op_cmov_t0_t1_t2 },
1511
/* param0 -> t0, param1 -> t2 */ { gen_op_cmov_t0_t2_t0, gen_op_cmov_t0_t2_t1, NULL } },
1512
/* param0 -> t1 */              {
1513
/* param0 -> t1, param1 -> t0 */ { NULL, gen_op_cmov_t1_t0_t1, gen_op_cmov_t1_t0_t2 },
1514
/* param0 -> t1, param1 -> t1 */ { gen_op_cmov_t1_t1_t0, NULL, gen_op_cmov_t1_t1_t2 },
1515
/* param0 -> t1, param1 -> t2 */ { gen_op_cmov_t1_t2_t0, gen_op_cmov_t1_t2_t1, NULL } },
1516
/* param0 -> t2 */              {
1517
/* param0 -> t2, param1 -> t0 */ { NULL, gen_op_cmov_t2_t0_t1, gen_op_cmov_t2_t0_t2 },
1518
/* param0 -> t2, param1 -> t1 */ { gen_op_cmov_t2_t1_t0, NULL, gen_op_cmov_t2_t1_t2 },
1519
/* param0 -> t2, param1 -> t2 */ { gen_op_cmov_t2_t2_t0, gen_op_cmov_t2_t2_t1, NULL } } };
1520
 
1521
/* FIXME: Check if either opperand 1 or 2 is r0 */
1522
void gen_l_cmov(struct op_queue *opq, int param_t[3], orreg_t param[3],
1523
                int delay_slot)
1524
{
1525
  if(!param[0])
1526
    return;
1527
 
1528
  if(!param[1] && !param[2]) {
1529
    clear_t[param_t[0]](opq, 1);
1530
    return;
1531
  }
1532
 
1533
  if(param[1] == param[2]) {
1534
    move_t_t[param_t[0]][param_t[1]](opq, 1);
1535
    return;
1536
  }
1537
 
1538
  if((param[1] == param[2]) && (param[0] == param[1]))
1539
    return;
1540
 
1541
  l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1542
}
1543
 
1544
void gen_l_cust1(struct op_queue *opq, int param_t[3], orreg_t param[3],
1545
                 int delay_slot)
1546
{
1547
}
1548
 
1549
void gen_l_cust2(struct op_queue *opq, int param_t[3], orreg_t param[3],
1550
                 int delay_slot)
1551
{
1552
}
1553
 
1554
void gen_l_cust3(struct op_queue *opq, int param_t[3], orreg_t param[3],
1555
                 int delay_slot)
1556
{
1557
}
1558
 
1559
void gen_l_cust4(struct op_queue *opq, int param_t[3], orreg_t param[3],
1560
                 int delay_slot)
1561
{
1562
}
1563
 
1564
void gen_l_cust5(struct op_queue *opq, int param_t[3], orreg_t param[3],
1565
                 int delay_slot)
1566
{
1567
}
1568
 
1569
void gen_l_cust6(struct op_queue *opq, int param_t[3], orreg_t param[3],
1570
                 int delay_slot)
1571
{
1572
}
1573
 
1574
void gen_l_cust7(struct op_queue *opq, int param_t[3], orreg_t param[3],
1575
                 int delay_slot)
1576
{
1577
}
1578
 
1579
void gen_l_cust8(struct op_queue *opq, int param_t[3], orreg_t param[3],
1580
                 int delay_slot)
1581
{
1582
}
1583
 
1584
/* FIXME: All registers need to be stored before the div instructions as they
1585
 * have the potenticial to cause an exception */
1586
 
1587
static const generic_gen_op check_null_excpt[NUM_T_REGS] =
1588
 { gen_op_check_null_except_t0, gen_op_check_null_except_t1, gen_op_check_null_except_t2 };
1589
 
1590
static const generic_gen_op check_null_excpt_delay[NUM_T_REGS] = {
1591
 gen_op_check_null_except_t0_delay,
1592
 gen_op_check_null_except_t1_delay,
1593
 gen_op_check_null_except_t2_delay };
1594
 
1595
static const generic_gen_op l_div_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1596
/* param0 -> t0 */              {
1597
/* param0 -> t0, param1 -> t0 */ { gen_op_div_t0_t0_t0, gen_op_div_t0_t0_t1, gen_op_div_t0_t0_t2 },
1598
/* param0 -> t0, param1 -> t1 */ { gen_op_div_t0_t1_t0, gen_op_div_t0_t1_t1, gen_op_div_t0_t1_t2 },
1599
/* param0 -> t0, param1 -> t2 */ { gen_op_div_t0_t2_t0, gen_op_div_t0_t2_t1, gen_op_div_t0_t2_t2 } },
1600
/* param0 -> t1 */              {
1601
/* param0 -> t1, param1 -> t0 */ { gen_op_div_t1_t0_t0, gen_op_div_t1_t0_t1, gen_op_div_t1_t0_t2 },
1602
/* param0 -> t1, param1 -> t1 */ { gen_op_div_t1_t1_t0, gen_op_div_t1_t1_t1, gen_op_div_t1_t1_t2 },
1603
/* param0 -> t1, param1 -> t2 */ { gen_op_div_t1_t2_t0, gen_op_div_t1_t2_t1, gen_op_div_t1_t2_t2 } },
1604
/* param0 -> t2 */              {
1605
/* param0 -> t2, param1 -> t0 */ { gen_op_div_t2_t0_t0, gen_op_div_t2_t0_t1, gen_op_div_t2_t0_t2 },
1606
/* param0 -> t2, param1 -> t1 */ { gen_op_div_t2_t1_t0, gen_op_div_t2_t1_t1, gen_op_div_t2_t1_t2 },
1607
/* param0 -> t2, param1 -> t2 */ { gen_op_div_t2_t2_t0, gen_op_div_t2_t2_t1, gen_op_div_t2_t2_t2 } } };
1608
 
1609
void gen_l_div(struct op_queue *opq, int param_t[3], orreg_t param[3],
1610
               int delay_slot)
1611
{
1612
  /* Cross reference this location, since an ILLEGAL exception may happen */
1613
  find_jump_loc(opq->insn_addr, opq);
1614
  if(!param[2]) {
1615
    /* There is no option.  This _will_ cause an illeagal exception */
1616
    if(!delay_slot)
1617
      gen_op_illegal(opq, 1);
1618
    else
1619
      gen_op_illegal(opq, 1);
1620
    return;
1621
  }
1622
 
1623
  if(!delay_slot)
1624
    check_null_excpt[param_t[2]](opq, 1);
1625
  else
1626
    check_null_excpt_delay[param_t[2]](opq, 1);
1627
 
1628
  if(!param[0])
1629
    return;
1630
 
1631
  if(!param[1]) {
1632
    /* Clear param_t[0] */
1633
    clear_t[param_t[0]](opq, 1);
1634
    return;
1635
  }
1636
 
1637
  l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1638
}
1639
 
1640
static const generic_gen_op l_divu_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1641
/* param0 -> t0 */              {
1642
/* param0 -> t0, param1 -> t0 */ { gen_op_divu_t0_t0_t0, gen_op_divu_t0_t0_t1, gen_op_divu_t0_t0_t2 },
1643
/* param0 -> t0, param1 -> t1 */ { gen_op_divu_t0_t1_t0, gen_op_divu_t0_t1_t1, gen_op_divu_t0_t1_t2 },
1644
/* param0 -> t0, param1 -> t2 */ { gen_op_divu_t0_t2_t0, gen_op_divu_t0_t2_t1, gen_op_divu_t0_t2_t2 } },
1645
/* param0 -> t1 */              {
1646
/* param0 -> t1, param1 -> t0 */ { gen_op_divu_t1_t0_t0, gen_op_divu_t1_t0_t1, gen_op_divu_t1_t0_t2 },
1647
/* param0 -> t1, param1 -> t1 */ { gen_op_divu_t1_t1_t0, gen_op_divu_t1_t1_t1, gen_op_divu_t1_t1_t2 },
1648
/* param0 -> t1, param1 -> t2 */ { gen_op_divu_t1_t2_t0, gen_op_divu_t1_t2_t1, gen_op_divu_t1_t2_t2 } },
1649
/* param0 -> t2 */              {
1650
/* param0 -> t2, param1 -> t0 */ { gen_op_divu_t2_t0_t0, gen_op_divu_t2_t0_t1, gen_op_divu_t2_t0_t2 },
1651
/* param0 -> t2, param1 -> t1 */ { gen_op_divu_t2_t1_t0, gen_op_divu_t2_t1_t1, gen_op_divu_t2_t1_t2 },
1652
/* param0 -> t2, param1 -> t2 */ { gen_op_divu_t2_t2_t0, gen_op_divu_t2_t2_t1, gen_op_divu_t2_t2_t2 } } };
1653
 
1654
void gen_l_divu(struct op_queue *opq, int param_t[3], orreg_t param[3],
1655
                int delay_slot)
1656
{
1657
  /* Cross reference this location, since an ILLEGAL exception may happen */
1658
  find_jump_loc(opq->insn_addr, opq);
1659
  if(!param[2]) {
1660
    /* There is no option.  This _will_ cause an illeagal exception */
1661
    if(!delay_slot)
1662
      gen_op_illegal(opq, 1);
1663
    else
1664
      gen_op_illegal(opq, 1);
1665
    return;
1666
  }
1667
 
1668
  if(!delay_slot)
1669
    check_null_excpt[param_t[2]](opq, 1);
1670
  else
1671
    check_null_excpt_delay[param_t[2]](opq, 1);
1672
 
1673
  if(!param[0])
1674
    return;
1675
 
1676
  if(!param[1]) {
1677
    /* Clear param_t[0] */
1678
    clear_t[param_t[0]](opq, 1);
1679
    return;
1680
  }
1681
 
1682
  l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1683
}
1684
 
1685
static const generic_gen_op l_extbs_t_table[NUM_T_REGS][NUM_T_REGS] = {
1686
/* param0 -> t0 */ { gen_op_extbs_t0_t0, gen_op_extbs_t0_t1, gen_op_extbs_t0_t2 },
1687
/* param0 -> t1 */ { gen_op_extbs_t1_t0, gen_op_extbs_t1_t1, gen_op_extbs_t1_t2 },
1688
/* param0 -> t2 */ { gen_op_extbs_t2_t0, gen_op_extbs_t2_t1, gen_op_extbs_t2_t2 } };
1689
 
1690
void gen_l_extbs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1691
                 int delay_slot)
1692
{
1693
  if(!param[0])
1694
    return;
1695
 
1696
  if(!param[1]) {
1697
    clear_t[param_t[0]](opq, 1);
1698
    return;
1699
  }
1700
 
1701
  l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
1702
}
1703
 
1704
static const generic_gen_op l_extbz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1705
/* param0 -> t0 */ { gen_op_extbz_t0_t0, gen_op_extbz_t0_t1, gen_op_extbz_t0_t2 },
1706
/* param0 -> t1 */ { gen_op_extbz_t1_t0, gen_op_extbz_t1_t1, gen_op_extbz_t1_t2 },
1707
/* param0 -> t2 */ { gen_op_extbz_t2_t0, gen_op_extbz_t2_t1, gen_op_extbz_t2_t2 } };
1708
 
1709
void gen_l_extbz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1710
                 int delay_slot)
1711
{
1712
  if(!param[0])
1713
    return;
1714
 
1715
  if(!param[1]) {
1716
    clear_t[param_t[0]](opq, 1);
1717
    return;
1718
  }
1719
 
1720
  l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
1721
}
1722
 
1723
static const generic_gen_op l_exths_t_table[NUM_T_REGS][NUM_T_REGS] = {
1724
/* param0 -> t0 */ { gen_op_exths_t0_t0, gen_op_exths_t0_t1, gen_op_exths_t0_t2 },
1725
/* param0 -> t1 */ { gen_op_exths_t1_t0, gen_op_exths_t1_t1, gen_op_exths_t1_t2 },
1726
/* param0 -> t2 */ { gen_op_exths_t2_t0, gen_op_exths_t2_t1, gen_op_exths_t2_t2 } };
1727
 
1728
void gen_l_exths(struct op_queue *opq, int param_t[3], orreg_t param[3],
1729
                 int delay_slot)
1730
{
1731
  if(!param[0])
1732
    return;
1733
 
1734
  if(!param[1]) {
1735
    clear_t[param_t[0]](opq, 1);
1736
    return;
1737
  }
1738
 
1739
  l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
1740
}
1741
 
1742
static const generic_gen_op l_exthz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1743
/* param0 -> t0 */ { gen_op_exthz_t0_t0, gen_op_exthz_t0_t1, gen_op_exthz_t0_t2 },
1744
/* param0 -> t1 */ { gen_op_exthz_t1_t0, gen_op_exthz_t1_t1, gen_op_exthz_t1_t2 },
1745
/* param0 -> t2 */ { gen_op_exthz_t2_t0, gen_op_exthz_t2_t1, gen_op_exthz_t2_t2 } };
1746
 
1747
void gen_l_exthz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1748
                 int delay_slot)
1749
{
1750
  if(!param[0])
1751
    return;
1752
 
1753
  if(!param[1]) {
1754
    clear_t[param_t[0]](opq, 1);
1755
    return;
1756
  }
1757
 
1758
  l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
1759
}
1760
 
1761
void gen_l_extws(struct op_queue *opq, int param_t[3], orreg_t param[3],
1762
                 int delay_slot)
1763
{
1764
  if(!param[0])
1765
    return;
1766
 
1767
  if(!param[1]) {
1768
    clear_t[param_t[0]](opq, 1);
1769
    return;
1770
  }
1771
 
1772
  if(param[0] == param[1])
1773
    return;
1774
 
1775
  /* In the 32-bit architechture this instruction reduces to a move */
1776
  move_t_t[param_t[0]][param_t[1]](opq, 1);
1777
}
1778
 
1779
void gen_l_extwz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1780
                 int delay_slot)
1781
{
1782
  if(!param[0])
1783
    return;
1784
 
1785
  if(!param[1]) {
1786
    clear_t[param_t[0]](opq, 1);
1787
    return;
1788
  }
1789
 
1790
  if(param[0] == param[1])
1791
    return;
1792
 
1793
  /* In the 32-bit architechture this instruction reduces to a move */
1794
  move_t_t[param_t[0]][param_t[1]](opq, 1);
1795
}
1796
 
1797
static const generic_gen_op l_ff1_t_table[NUM_T_REGS][NUM_T_REGS] = {
1798
/* param0 -> t0 */ { gen_op_ff1_t0_t0, gen_op_ff1_t0_t1, gen_op_ff1_t0_t2 },
1799
/* param0 -> t1 */ { gen_op_ff1_t1_t0, gen_op_ff1_t1_t1, gen_op_ff1_t1_t2 },
1800
/* param0 -> t2 */ { gen_op_ff1_t2_t0, gen_op_ff1_t2_t1, gen_op_ff1_t2_t2 } };
1801
 
1802
void gen_l_ff1(struct op_queue *opq, int param_t[3], orreg_t param[3],
1803
               int delay_slot)
1804
{
1805
  if(!param[0])
1806
    return;
1807
 
1808
  if(!param[1]) {
1809
    clear_t[param_t[0]](opq, 1);
1810
    return;
1811
  }
1812
 
1813
  l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
1814
}
1815
 
1816
void gen_l_j(struct op_queue *opq, int param_t[3], orreg_t param[3],
1817
             int delay_slot)
1818
{
1819
  gen_op_set_pc_delay_imm(opq, 1, param[0] << 2);
1820
 
1821
  /* Don't allocate a seporate x-ref structure for the infinite loop instruction
1822
   * (l.j 0) */
1823
  if(!param[0]) {
1824
    opq->jump_local = 2;
1825
    opq->xref = cpu_state.inf_xrefs;
1826
    opq->xref->or_addr = opq->insn_addr;
1827
    cpu_state.inf_xrefs = opq->xref->next;
1828
    return;
1829
  }
1830
 
1831
  opq->jump_local = find_jump_loc(opq->insn_addr + (orreg_t)(param[0] << 2), opq);
1832
}
1833
 
1834
void gen_l_jal(struct op_queue *opq, int param_t[3], orreg_t param[3],
1835
               int delay_slot)
1836
{
1837
  /* It is highly likely that the location that was jumped to will `return'.
1838
   * Therefore, insert a cross reference at that address */
1839
  find_jump_loc(opq->insn_addr + 8, opq);
1840
 
1841
  gen_l_j(opq, param_t, param, delay_slot);
1842
 
1843
  /* Store the return address */
1844
  gen_op_store_link_addr_gpr(opq, 1);
1845
}
1846
 
1847
static const generic_gen_op set_pc_delay_t[NUM_T_REGS] =
1848
 { gen_op_set_pc_delay_t0, gen_op_set_pc_delay_t1, gen_op_set_pc_delay_t2 };
1849
 
1850
void gen_l_jr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1851
              int delay_slot)
1852
{
1853
  /* Treat all jumps as non page-local */
1854
  opq->jump_local = 0;
1855
 
1856
  if(!param[0]) {
1857
    gen_op_clear_pc_delay(opq, 1);
1858
    return;
1859
  }
1860
 
1861
  set_pc_delay_t[param_t[0]](opq, 1);
1862
}
1863
 
1864
void gen_l_jalr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1865
                int delay_slot)
1866
{
1867
  /* It is highly likely that the location that was jumped to will `return'.
1868
   * Therefore, insert a cross reference at that address */
1869
  find_jump_loc(opq->insn_addr + 8, opq);
1870
 
1871
  gen_l_jr(opq, param_t, param, delay_slot);
1872
 
1873
  /* Store the return address */
1874
  gen_op_store_link_addr_gpr(opq, 1);
1875
}
1876
 
1877
/* FIXME: Optimise all load instruction when the disposition == 0 */
1878
 
1879
static const imm_gen_op l_lbs_imm_t_table[NUM_T_REGS] =
1880
 { gen_op_lbs_imm_t0, gen_op_lbs_imm_t1, gen_op_lbs_imm_t2 };
1881
 
1882
static const imm_gen_op l_lbs_t_table[3][3] = {
1883
/* param0 -> t0 */ { gen_op_lbs_t0_t0, gen_op_lbs_t0_t1, gen_op_lbs_t0_t2 },
1884
/* param0 -> t1 */ { gen_op_lbs_t1_t0, gen_op_lbs_t1_t1, gen_op_lbs_t1_t2 },
1885
/* param0 -> t2 */ { gen_op_lbs_t2_t0, gen_op_lbs_t2_t1, gen_op_lbs_t2_t2 } };
1886
 
1887
void gen_l_lbs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1888
               int delay_slot)
1889
{
1890
  if(!param[0]) {
1891
    /* FIXME: This will work, but the statistics need to be updated... */
1892
    return;
1893
  }
1894
 
1895
  if(!param[2]) {
1896
    /* Load the data from the immediate */
1897
    l_lbs_imm_t_table[param_t[0]](opq, 1, param[1]);
1898
    return;
1899
  }
1900
 
1901
  l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1902
}
1903
 
1904
static const imm_gen_op l_lbz_imm_t_table[NUM_T_REGS] =
1905
 { gen_op_lbz_imm_t0, gen_op_lbz_imm_t1, gen_op_lbz_imm_t2 };
1906
 
1907
static const imm_gen_op l_lbz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1908
/* param0 -> t0 */ { gen_op_lbz_t0_t0, gen_op_lbz_t0_t1, gen_op_lbz_t0_t2 },
1909
/* param0 -> t1 */ { gen_op_lbz_t1_t0, gen_op_lbz_t1_t1, gen_op_lbz_t1_t2 },
1910
/* param0 -> t2 */ { gen_op_lbz_t2_t0, gen_op_lbz_t2_t1, gen_op_lbz_t2_t2 } };
1911
 
1912
void gen_l_lbz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1913
               int delay_slot)
1914
{
1915
  if(!param[0]) {
1916
    /* FIXME: This will work, but the statistics need to be updated... */
1917
    return;
1918
  }
1919
 
1920
  if(!param[2]) {
1921
    /* Load the data from the immediate */
1922
    l_lbz_imm_t_table[param_t[0]](opq, 1, param[1]);
1923
    return;
1924
  }
1925
 
1926
  l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1927
}
1928
 
1929
static const imm_gen_op l_lhs_imm_t_table[NUM_T_REGS] =
1930
 { gen_op_lhs_imm_t0, gen_op_lhs_imm_t1, gen_op_lhs_imm_t2 };
1931
 
1932
static const imm_gen_op l_lhs_t_table[NUM_T_REGS][NUM_T_REGS] = {
1933
/* param0 -> t0 */ { gen_op_lhs_t0_t0, gen_op_lhs_t0_t1, gen_op_lhs_t0_t2 },
1934
/* param0 -> t1 */ { gen_op_lhs_t1_t0, gen_op_lhs_t1_t1, gen_op_lhs_t1_t2 },
1935
/* param0 -> t2 */ { gen_op_lhs_t2_t0, gen_op_lhs_t2_t1, gen_op_lhs_t2_t2 } };
1936
 
1937
void gen_l_lhs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1938
               int delay_slot)
1939
{
1940
  if(!param[0]) {
1941
    /* FIXME: This will work, but the statistics need to be updated... */
1942
    return;
1943
  }
1944
 
1945
  if(!param[2]) {
1946
    /* Load the data from the immediate */
1947
    l_lhs_imm_t_table[param_t[0]](opq, 1, param[1]);
1948
    return;
1949
  }
1950
 
1951
  l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1952
}
1953
 
1954
static const imm_gen_op l_lhz_imm_t_table[NUM_T_REGS] =
1955
 { gen_op_lhz_imm_t0, gen_op_lhz_imm_t1, gen_op_lhz_imm_t2 };
1956
 
1957
static const imm_gen_op l_lhz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1958
/* param0 -> t0 */ { gen_op_lhz_t0_t0, gen_op_lhz_t0_t1, gen_op_lhz_t0_t2 },
1959
/* param0 -> t1 */ { gen_op_lhz_t1_t0, gen_op_lhz_t1_t1, gen_op_lhz_t1_t2 },
1960
/* param0 -> t2 */ { gen_op_lhz_t2_t0, gen_op_lhz_t2_t1, gen_op_lhz_t2_t2 } };
1961
 
1962
void gen_l_lhz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1963
               int delay_slot)
1964
{
1965
  if(!param[0]) {
1966
    /* FIXME: This will work, but the statistics need to be updated... */
1967
    return;
1968
  }
1969
 
1970
  if(!param[2]) {
1971
    /* Load the data from the immediate */
1972
    l_lhz_imm_t_table[param_t[0]](opq, 1, param[1]);
1973
    return;
1974
  }
1975
 
1976
  l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1977
}
1978
 
1979
static const imm_gen_op l_lws_imm_t_table[NUM_T_REGS] =
1980
 { gen_op_lws_imm_t0, gen_op_lws_imm_t1, gen_op_lws_imm_t2 };
1981
 
1982
static const imm_gen_op l_lws_t_table[NUM_T_REGS][NUM_T_REGS] = {
1983
/* param0 -> t0 */ { gen_op_lws_t0_t0, gen_op_lws_t0_t1, gen_op_lws_t0_t2 },
1984
/* param0 -> t1 */ { gen_op_lws_t1_t0, gen_op_lws_t1_t1, gen_op_lws_t1_t2 },
1985
/* param0 -> t2 */ { gen_op_lws_t2_t0, gen_op_lws_t2_t1, gen_op_lws_t2_t2 } };
1986
 
1987
void gen_l_lws(struct op_queue *opq, int param_t[3], orreg_t param[3],
1988
               int delay_slot)
1989
{
1990
  if(!param[0]) {
1991
    /* FIXME: This will work, but the statistics need to be updated... */
1992
    return;
1993
  }
1994
 
1995
  if(!param[2]) {
1996
    /* Load the data from the immediate */
1997
    l_lws_imm_t_table[param_t[0]](opq, 1, param[1]);
1998
    return;
1999
  }
2000
 
2001
  l_lws_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
2002
}
2003
 
2004
static const imm_gen_op l_lwz_imm_t_table[NUM_T_REGS] =
2005
 { gen_op_lwz_imm_t0, gen_op_lwz_imm_t1, gen_op_lwz_imm_t2 };
2006
 
2007
static const imm_gen_op l_lwz_t_table[NUM_T_REGS][NUM_T_REGS] = {
2008
/* param0 -> t0 */ { gen_op_lwz_t0_t0, gen_op_lwz_t0_t1, gen_op_lwz_t0_t2 },
2009
/* param0 -> t1 */ { gen_op_lwz_t1_t0, gen_op_lwz_t1_t1, gen_op_lwz_t1_t2 },
2010
/* param0 -> t2 */ { gen_op_lwz_t2_t0, gen_op_lwz_t2_t1, gen_op_lwz_t2_t2 } };
2011
 
2012
void gen_l_lwz(struct op_queue *opq, int param_t[3], orreg_t param[3],
2013
               int delay_slot)
2014
{
2015
  if(!param[0]) {
2016
    /* FIXME: This will work, but the statistics need to be updated... */
2017
    return;
2018
  }
2019
 
2020
  if(!param[2]) {
2021
    /* Load the data from the immediate */
2022
    l_lwz_imm_t_table[param_t[0]](opq, 1, param[1]);
2023
    return;
2024
  }
2025
 
2026
  l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
2027
}
2028
 
2029
static const imm_gen_op l_mac_imm_t_table[NUM_T_REGS] =
2030
 { gen_op_mac_imm_t0, gen_op_mac_imm_t1, gen_op_mac_imm_t2 };
2031
 
2032
static const generic_gen_op l_mac_t_table[NUM_T_REGS][NUM_T_REGS] = {
2033
/* param0 -> t0 */ { gen_op_mac_t0_t0, gen_op_mac_t0_t1, gen_op_mac_t0_t2 },
2034
/* param0 -> t1 */ { gen_op_mac_t0_t1, gen_op_mac_t1_t1, gen_op_mac_t1_t2 },
2035
/* param0 -> t2 */ { gen_op_mac_t0_t2, gen_op_mac_t1_t2, gen_op_mac_t2_t2 } };
2036
 
2037
void gen_l_mac(struct op_queue *opq, int param_t[3], orreg_t param[3],
2038
               int delay_slot)
2039
{
2040
  if(!param[0] || !param[1])
2041
    return;
2042
 
2043
  if(param_t[1] == T_NONE)
2044
    l_mac_imm_t_table[param_t[0]](opq, 1, param[1]);
2045
  else
2046
    l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
2047
}
2048
 
2049
static const generic_gen_op l_macrc_t_table[NUM_T_REGS] =
2050
 { gen_op_macrc_t0, gen_op_macrc_t1, gen_op_macrc_t2 };
2051
 
2052
void gen_l_macrc(struct op_queue *opq, int param_t[3], orreg_t param[3],
2053
                 int delay_slot)
2054
{
2055
  if(!param[0]) {
2056
    gen_op_macc(opq, 1);
2057
    return;
2058
  }
2059
 
2060
  l_macrc_t_table[param_t[0]](opq, 1);
2061
}
2062
 
2063
static const imm_gen_op l_mfspr_imm_t_table[NUM_T_REGS] =
2064
 { gen_op_mfspr_t0_imm, gen_op_mfspr_t1_imm, gen_op_mfspr_t2_imm };
2065
 
2066
static const imm_gen_op l_mfspr_t_table[NUM_T_REGS][NUM_T_REGS] = {
2067
/* param0 -> t0 */ { gen_op_mfspr_t0_t0, gen_op_mfspr_t0_t1, gen_op_mfspr_t0_t2 },
2068
/* param0 -> t1 */ { gen_op_mfspr_t1_t0, gen_op_mfspr_t1_t1, gen_op_mfspr_t1_t2 },
2069
/* param0 -> t2 */ { gen_op_mfspr_t2_t0, gen_op_mfspr_t2_t1, gen_op_mfspr_t2_t2 } };
2070
 
2071
void gen_l_mfspr(struct op_queue *opq, int param_t[3], orreg_t param[3],
2072
                 int delay_slot)
2073
{
2074
  if(!param[0])
2075
    return;
2076
 
2077
  if(!param[1]) {
2078
    l_mfspr_imm_t_table[param_t[0]](opq, 1, param[2]);
2079
    return;
2080
  }
2081
 
2082
  l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2083
}
2084
 
2085
void gen_l_movhi(struct op_queue *opq, int param_t[3], orreg_t param[3],
2086
                 int delay_slot)
2087
{
2088
  if(!param[0])
2089
    return;
2090
 
2091
  if(!param[1]) {
2092
    clear_t[param_t[0]](opq, 1);
2093
    return;
2094
  }
2095
 
2096
  mov_t_imm[param_t[0]](opq, 1, param[1] << 16);
2097
}
2098
 
2099
static const generic_gen_op l_msb_t_table[NUM_T_REGS][NUM_T_REGS] = {
2100
/* param0 -> t0 */ { gen_op_msb_t0_t0, gen_op_msb_t0_t1, gen_op_msb_t0_t2 },
2101
/* param0 -> t1 */ { gen_op_msb_t0_t1, gen_op_msb_t1_t1, gen_op_msb_t1_t2 },
2102
/* param0 -> t2 */ { gen_op_msb_t0_t2, gen_op_msb_t1_t2, gen_op_msb_t2_t2 } };
2103
 
2104
void gen_l_msb(struct op_queue *opq, int param_t[3], orreg_t param[3],
2105
               int delay_slot)
2106
{
2107
  if(!param[0] || !param[1])
2108
    return;
2109
 
2110
  l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
2111
}
2112
 
2113
static const imm_gen_op l_mtspr_clear_t_table[NUM_T_REGS] =
2114
 { gen_op_mtspr_t0_clear, gen_op_mtspr_t1_clear, gen_op_mtspr_t2_clear };
2115
 
2116
static const imm_gen_op l_mtspr_imm_t_table[NUM_T_REGS] =
2117
 { gen_op_mtspr_imm_t0, gen_op_mtspr_imm_t1, gen_op_mtspr_imm_t2 };
2118
 
2119
static const imm_gen_op l_mtspr_t_table[NUM_T_REGS][NUM_T_REGS] = {
2120
/* param0 -> t0 */ { gen_op_mtspr_t0_t0, gen_op_mtspr_t0_t1, gen_op_mtspr_t0_t2 },
2121
/* param0 -> t1 */ { gen_op_mtspr_t1_t0, gen_op_mtspr_t1_t1, gen_op_mtspr_t1_t2 },
2122
/* param0 -> t2 */ { gen_op_mtspr_t2_t0, gen_op_mtspr_t2_t1, gen_op_mtspr_t2_t2 } };
2123
 
2124
void gen_l_mtspr(struct op_queue *opq, int param_t[3], orreg_t param[3],
2125
                 int delay_slot)
2126
{
2127
  if(!param[0]) {
2128
    if(!param[1]) {
2129
      /* Clear the immediate SPR */
2130
      gen_op_mtspr_imm_clear(opq, 1, param[2]);
2131
      return;
2132
    }
2133
    l_mtspr_imm_t_table[param_t[1]](opq, 1, param[2]);
2134
    return;
2135
  }
2136
 
2137
  if(!param[1]) {
2138
    l_mtspr_clear_t_table[param_t[0]](opq, 1, param[2]);
2139
    return;
2140
  }
2141
 
2142
  l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2143
}
2144
 
2145
static const imm_gen_op l_mul_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2146
/* param0 -> t0 */ { gen_op_mul_imm_t0_t0, gen_op_mul_imm_t0_t1, gen_op_mul_imm_t0_t2 },
2147
/* param0 -> t1 */ { gen_op_mul_imm_t1_t0, gen_op_mul_imm_t1_t1, gen_op_mul_imm_t1_t2 },
2148
/* param0 -> t2 */ { gen_op_mul_imm_t2_t0, gen_op_mul_imm_t2_t1, gen_op_mul_imm_t2_t2 } };
2149
 
2150
static const generic_gen_op l_mul_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2151
/* param0 -> t0 */              {
2152
/* param0 -> t0, param1 -> t0 */ { gen_op_mul_t0_t0_t0, gen_op_mul_t0_t0_t1, gen_op_mul_t0_t0_t2 },
2153
/* param0 -> t0, param1 -> t1 */ { gen_op_mul_t0_t1_t0, gen_op_mul_t0_t1_t1, gen_op_mul_t0_t1_t2 },
2154
/* param0 -> t0, param1 -> t2 */ { gen_op_mul_t0_t2_t0, gen_op_mul_t0_t2_t1, gen_op_mul_t0_t2_t2 } },
2155
/* param0 -> t1 */              {
2156
/* param0 -> t1, param1 -> t0 */ { gen_op_mul_t1_t0_t0, gen_op_mul_t1_t0_t1, gen_op_mul_t1_t0_t2 },
2157
/* param0 -> t1, param1 -> t1 */ { gen_op_mul_t1_t1_t0, gen_op_mul_t1_t1_t1, gen_op_mul_t1_t1_t2 },
2158
/* param0 -> t1, param1 -> t2 */ { gen_op_mul_t1_t2_t0, gen_op_mul_t1_t2_t1, gen_op_mul_t1_t2_t2 } },
2159
/* param0 -> t2 */              {
2160
/* param0 -> t2, param1 -> t0 */ { gen_op_mul_t2_t0_t0, gen_op_mul_t2_t0_t1, gen_op_mul_t2_t0_t2 },
2161
/* param0 -> t2, param1 -> t1 */ { gen_op_mul_t2_t1_t0, gen_op_mul_t2_t1_t1, gen_op_mul_t2_t1_t2 },
2162
/* param0 -> t2, param1 -> t2 */ { gen_op_mul_t2_t2_t0, gen_op_mul_t2_t2_t1, gen_op_mul_t2_t2_t2 } } };
2163
 
2164
void gen_l_mul(struct op_queue *opq, int param_t[3], orreg_t param[3],
2165
               int delay_slot)
2166
{
2167
  if(!param[0])
2168
    return;
2169
 
2170
  if(!param[1] || !param[2]) {
2171
    clear_t[param_t[0]](opq, 1);
2172
    return;
2173
  }
2174
 
2175
  if(param_t[2] == T_NONE)
2176
    l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2177
  else
2178
    l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2179
}
2180
 
2181
static const generic_gen_op l_mulu_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2182
/* param0 -> t0 */              {
2183
/* param0 -> t0, param1 -> t0 */ { gen_op_mulu_t0_t0_t0, gen_op_mulu_t0_t0_t1, gen_op_mulu_t0_t0_t2 },
2184
/* param0 -> t0, param1 -> t1 */ { gen_op_mulu_t0_t1_t0, gen_op_mulu_t0_t1_t1, gen_op_mulu_t0_t1_t2 },
2185
/* param0 -> t0, param1 -> t2 */ { gen_op_mulu_t0_t2_t0, gen_op_mulu_t0_t2_t1, gen_op_mulu_t0_t2_t2 } },
2186
/* param0 -> t1 */              {
2187
/* param0 -> t1, param1 -> t0 */ { gen_op_mulu_t1_t0_t0, gen_op_mulu_t1_t0_t1, gen_op_mulu_t1_t0_t2 },
2188
/* param0 -> t1, param1 -> t1 */ { gen_op_mulu_t1_t1_t0, gen_op_mulu_t1_t1_t1, gen_op_mulu_t1_t1_t2 },
2189
/* param0 -> t1, param1 -> t2 */ { gen_op_mulu_t1_t2_t0, gen_op_mulu_t1_t2_t1, gen_op_mulu_t1_t2_t2 } },
2190
/* param0 -> t2 */              {
2191
/* param0 -> t2, param1 -> t0 */ { gen_op_mulu_t2_t0_t0, gen_op_mulu_t2_t0_t1, gen_op_mulu_t2_t0_t2 },
2192
/* param0 -> t2, param1 -> t1 */ { gen_op_mulu_t2_t1_t0, gen_op_mulu_t2_t1_t1, gen_op_mulu_t2_t1_t2 },
2193
/* param0 -> t2, param1 -> t2 */ { gen_op_mulu_t2_t2_t0, gen_op_mulu_t2_t2_t1, gen_op_mulu_t2_t2_t2 } } };
2194
 
2195
void gen_l_mulu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2196
                int delay_slot)
2197
{
2198
  if(!param[0])
2199
    return;
2200
 
2201
  if(!param[1] || !param[2]) {
2202
    clear_t[param_t[0]](opq, 1);
2203
    return;
2204
  }
2205
 
2206
  l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2207
}
2208
 
2209
void gen_l_nop(struct op_queue *opq, int param_t[3], orreg_t param[3],
2210
               int delay_slot)
2211
{
2212
  /* Do parameter switch now */
2213
  switch (param[0]) {
2214
  case NOP_NOP:
2215
    break;
2216
  case NOP_EXIT:
2217
    gen_op_nop_exit(opq, 1);
2218
    break;
2219
  case NOP_CNT_RESET:
2220
    /* FIXME: Since op_nop_reset calls handle_except, this instruction wont show
2221
     * up in the execution log, nor will the scheduler run */
2222
    gen_op_nop_reset(opq, 1);
2223
    break;
2224
  case NOP_PRINTF:
2225
    gen_op_nop_printf(opq, 1);
2226
    break;
2227
  case NOP_REPORT:
2228
    gen_op_nop_report(opq, 1);
2229
    break;
2230
  default:
2231
    if((param[0] >= NOP_REPORT_FIRST) && (param[0] <= NOP_REPORT_LAST))
2232
      gen_op_nop_report_imm(opq, 1, param[0] - NOP_REPORT_FIRST);
2233
    break;
2234
  }
2235
}
2236
 
2237
static const imm_gen_op l_or_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2238
/* param0 -> t0 */ { gen_op_or_imm_t0_t0, gen_op_or_imm_t0_t1, gen_op_or_imm_t0_t2 },
2239
/* param0 -> t1 */ { gen_op_or_imm_t1_t0, gen_op_or_imm_t1_t1, gen_op_or_imm_t1_t2 },
2240
/* param0 -> t2 */ { gen_op_or_imm_t2_t0, gen_op_or_imm_t2_t1, gen_op_or_imm_t2_t2 } };
2241
 
2242
static const generic_gen_op l_or_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2243
/* param0 -> t0 */              {
2244
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_or_t0_t0_t1, gen_op_or_t0_t0_t2 },
2245
/* param0 -> t0, param1 -> t1 */ { gen_op_or_t0_t1_t0, gen_op_or_t0_t1_t1, gen_op_or_t0_t1_t2 },
2246
/* param0 -> t0, param1 -> t2 */ { gen_op_or_t0_t2_t0, gen_op_or_t0_t2_t1, gen_op_or_t0_t2_t2 } },
2247
/* param0 -> t1 */              {
2248
/* param0 -> t1, param1 -> t0 */ { gen_op_or_t1_t0_t0, gen_op_or_t1_t0_t1, gen_op_or_t1_t0_t2 },
2249
/* param0 -> t1, param1 -> t1 */ { gen_op_or_t1_t1_t0, NULL, gen_op_or_t1_t1_t2 },
2250
/* param0 -> t1, param1 -> t2 */ { gen_op_or_t1_t2_t0, gen_op_or_t1_t2_t1, gen_op_or_t1_t2_t2 } },
2251
/* param0 -> t2 */              {
2252
/* param0 -> t2, param1 -> t0 */ { gen_op_or_t2_t0_t0, gen_op_or_t2_t0_t1, gen_op_or_t2_t0_t2 },
2253
/* param0 -> t2, param1 -> t1 */ { gen_op_or_t2_t1_t0, gen_op_or_t2_t1_t1, gen_op_or_t2_t1_t2 },
2254
/* param0 -> t2, param1 -> t2 */ { gen_op_or_t2_t2_t0, gen_op_or_t2_t2_t1, NULL } } };
2255
 
2256
void gen_l_or(struct op_queue *opq, int param_t[3], orreg_t param[3],
2257
              int delay_slot)
2258
{
2259
  if(!param[0])
2260
    return;
2261
 
2262
  if((param[0] == param[1] == param[2]) && (param_t[2] != T_NONE))
2263
    return;
2264
 
2265
  if(!param[1] && !param[2]) {
2266
    clear_t[param_t[0]](opq, 1);
2267
    return;
2268
  }
2269
 
2270
  if(!param[2]) {
2271
    if((param_t[2] == T_NONE) && (param[0] == param[1]))
2272
      return;
2273
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2274
    return;
2275
  }
2276
 
2277
  if(!param[1]) {
2278
    /* Check if we are moveing an immediate */
2279
    if(param_t[2] == T_NONE) {
2280
      /* Yep, an immediate */
2281
      mov_t_imm[param_t[0]](opq, 1, param[2]);
2282
      return;
2283
    }
2284
    /* Just another move */
2285
    move_t_t[param_t[0]][param_t[2]](opq, 1);
2286
    return;
2287
  }
2288
 
2289
  if(param_t[2] == T_NONE)
2290
    l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2291
  else
2292
    l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2293
}
2294
 
2295
void gen_l_rfe(struct op_queue *opq, int param_t[3], orreg_t param[3],
2296
               int delay_slot)
2297
{
2298
  gen_op_prep_rfe(opq, 1);
2299
}
2300
 
2301
/* FIXME: All store instructions should be optimised when the disposition = 0 */
2302
 
2303
static const imm_gen_op l_sb_clear_table[NUM_T_REGS] =
2304
 { gen_op_sb_clear_t0, gen_op_sb_clear_t1, gen_op_sb_clear_t2 };
2305
 
2306
static const imm_gen_op l_sb_imm_t_table[NUM_T_REGS] =
2307
 { gen_op_sb_imm_t0, gen_op_sb_imm_t1, gen_op_sb_imm_t2 };
2308
 
2309
static const imm_gen_op l_sb_t_table[NUM_T_REGS][NUM_T_REGS] = {
2310
/* param0 -> t0 */ { gen_op_sb_t0_t0, gen_op_sb_t0_t1, gen_op_sb_t0_t2 },
2311
/* param0 -> t1 */ { gen_op_sb_t1_t0, gen_op_sb_t1_t1, gen_op_sb_t1_t2 },
2312
/* param0 -> t2 */ { gen_op_sb_t2_t0, gen_op_sb_t2_t1, gen_op_sb_t2_t2 } };
2313
 
2314
void gen_l_sb(struct op_queue *opq, int param_t[3], orreg_t param[3],
2315
              int delay_slot)
2316
{
2317
  if(!param[2]) {
2318
    if(!param[1]) {
2319
      gen_op_sb_clear_imm(opq, 1, param[0]);
2320
      return;
2321
    }
2322
    l_sb_clear_table[param_t[1]](opq, 1, param[0]);
2323
    return;
2324
  }
2325
 
2326
  if(!param[1]) {
2327
    /* Store the data to the immediate */
2328
    l_sb_imm_t_table[param_t[2]](opq, 1, param[0]);
2329
    return;
2330
  }
2331
 
2332
  l_sb_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2333
}
2334
 
2335
static const imm_gen_op l_sh_clear_table[NUM_T_REGS] =
2336
 { gen_op_sh_clear_t0, gen_op_sh_clear_t1, gen_op_sh_clear_t2 };
2337
 
2338
static const imm_gen_op l_sh_imm_t_table[NUM_T_REGS] =
2339
 { gen_op_sh_imm_t0, gen_op_sh_imm_t1, gen_op_sh_imm_t2 };
2340
 
2341
static const imm_gen_op l_sh_t_table[NUM_T_REGS][NUM_T_REGS] = {
2342
/* param0 -> t0 */ { gen_op_sh_t0_t0, gen_op_sh_t0_t1, gen_op_sh_t0_t2 },
2343
/* param0 -> t1 */ { gen_op_sh_t1_t0, gen_op_sh_t1_t1, gen_op_sh_t1_t2 },
2344
/* param0 -> t2 */ { gen_op_sh_t2_t0, gen_op_sh_t2_t1, gen_op_sh_t2_t2 } };
2345
 
2346
void gen_l_sh(struct op_queue *opq, int param_t[3], orreg_t param[3],
2347
              int delay_slot)
2348
{
2349
  if(!param[2]) {
2350
    if(!param[1]) {
2351
      gen_op_sh_clear_imm(opq, 1, param[0]);
2352
      return;
2353
    }
2354
    l_sh_clear_table[param_t[1]](opq, 1, param[0]);
2355
    return;
2356
  }
2357
 
2358
  if(!param[1]) {
2359
    /* Store the data to the immediate */
2360
    l_sh_imm_t_table[param_t[2]](opq, 1, param[0]);
2361
    return;
2362
  }
2363
 
2364
  l_sh_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2365
}
2366
 
2367
static const imm_gen_op l_sw_clear_table[NUM_T_REGS] =
2368
 { gen_op_sw_clear_t0, gen_op_sw_clear_t1, gen_op_sw_clear_t2 };
2369
 
2370
static const imm_gen_op l_sw_imm_t_table[NUM_T_REGS] =
2371
 { gen_op_sw_imm_t0, gen_op_sw_imm_t1, gen_op_sw_imm_t2 };
2372
 
2373
static const imm_gen_op l_sw_t_table[NUM_T_REGS][NUM_T_REGS] = {
2374
/* param0 -> t0 */ { gen_op_sw_t0_t0, gen_op_sw_t0_t1, gen_op_sw_t0_t2 },
2375
/* param0 -> t1 */ { gen_op_sw_t1_t0, gen_op_sw_t1_t1, gen_op_sw_t1_t2 },
2376
/* param0 -> t2 */ { gen_op_sw_t2_t0, gen_op_sw_t2_t1, gen_op_sw_t2_t2 } };
2377
 
2378
void gen_l_sw(struct op_queue *opq, int param_t[3], orreg_t param[3],
2379
              int delay_slot)
2380
{
2381
  if(!param[2]) {
2382
    if(!param[1]) {
2383
      gen_op_sw_clear_imm(opq, 1, param[0]);
2384
      return;
2385
    }
2386
    l_sw_clear_table[param_t[1]](opq, 1, param[0]);
2387
    return;
2388
  }
2389
 
2390
  if(!param[1]) {
2391
    /* Store the data to the immediate */
2392
    l_sw_imm_t_table[param_t[2]](opq, 1, param[0]);
2393
    return;
2394
  }
2395
 
2396
  l_sw_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2397
}
2398
 
2399
static const generic_gen_op l_sfeq_null_t_table[NUM_T_REGS] =
2400
 { gen_op_sfeq_null_t0, gen_op_sfeq_null_t1, gen_op_sfeq_null_t2 };
2401
 
2402
static const imm_gen_op l_sfeq_imm_t_table[NUM_T_REGS] =
2403
 { gen_op_sfeq_imm_t0, gen_op_sfeq_imm_t1, gen_op_sfeq_imm_t2 };
2404
 
2405
static const generic_gen_op l_sfeq_t_table[NUM_T_REGS][NUM_T_REGS] = {
2406
/* param0 -> t0 */ { gen_op_sfeq_t0_t0, gen_op_sfeq_t0_t1, gen_op_sfeq_t0_t2 },
2407
/* param0 -> t1 */ { gen_op_sfeq_t1_t0, gen_op_sfeq_t1_t1, gen_op_sfeq_t1_t2 },
2408
/* param0 -> t2 */ { gen_op_sfeq_t2_t0, gen_op_sfeq_t2_t1, gen_op_sfeq_t2_t2 } };
2409
 
2410
void gen_l_sfeq(struct op_queue *opq, int param_t[3], orreg_t param[3],
2411
                int delay_slot)
2412
{
2413
  if(!param[0] && !param[1]) {
2414
    gen_op_set_flag(opq, 1);
2415
    return;
2416
  }
2417
 
2418
  if(!param[0]) {
2419
    if(param_t[1] == T_NONE) {
2420
      if(!param[1])
2421
        gen_op_set_flag(opq, 1);
2422
      else
2423
        gen_op_clear_flag(opq, 1);
2424
    } else
2425
      l_sfeq_null_t_table[param_t[1]](opq, 1);
2426
    return;
2427
  }
2428
 
2429
  if(!param[1]) {
2430
    l_sfeq_null_t_table[param_t[0]](opq, 1);
2431
    return;
2432
  }
2433
 
2434
  if(param_t[1] == T_NONE)
2435
    l_sfeq_imm_t_table[param_t[0]](opq, 1, param[1]);
2436
  else
2437
    l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
2438
}
2439
 
2440
static const generic_gen_op l_sfges_null_t_table[NUM_T_REGS] =
2441
 { gen_op_sfges_null_t0, gen_op_sfges_null_t1, gen_op_sfges_null_t2 };
2442
 
2443
static const generic_gen_op l_sfles_null_t_table[NUM_T_REGS] =
2444
 { gen_op_sfles_null_t0, gen_op_sfles_null_t1, gen_op_sfles_null_t2 };
2445
 
2446
static const imm_gen_op l_sfges_imm_t_table[NUM_T_REGS] =
2447
 { gen_op_sfges_imm_t0, gen_op_sfges_imm_t1, gen_op_sfges_imm_t2 };
2448
 
2449
static const generic_gen_op l_sfges_t_table[NUM_T_REGS][NUM_T_REGS] = {
2450
/* param0 -> t0 */ { gen_op_sfges_t0_t0, gen_op_sfges_t0_t1, gen_op_sfges_t0_t2 },
2451
/* param0 -> t1 */ { gen_op_sfges_t1_t0, gen_op_sfges_t1_t1, gen_op_sfges_t1_t2 },
2452
/* param0 -> t2 */ { gen_op_sfges_t2_t0, gen_op_sfges_t2_t1, gen_op_sfges_t2_t2 } };
2453
 
2454
void gen_l_sfges(struct op_queue *opq, int param_t[3], orreg_t param[3],
2455
                 int delay_slot)
2456
{
2457
  if(!param[0] && !param[1]) {
2458
    gen_op_set_flag(opq, 1);
2459
    return;
2460
  }
2461
 
2462
  if(!param[0]) {
2463
    /* sfles IS correct */
2464
    if(param_t[1] == T_NONE) {
2465
      if(0 >= (orreg_t)param[1])
2466
        gen_op_set_flag(opq, 1);
2467
      else
2468
        gen_op_clear_flag(opq, 1);
2469
    } else
2470
      l_sfles_null_t_table[param_t[1]](opq, 1);
2471
    return;
2472
  }
2473
 
2474
  if(!param[1]) {
2475
    l_sfges_null_t_table[param_t[0]](opq, 1);
2476
    return;
2477
  }
2478
 
2479
  if(param_t[1] == T_NONE)
2480
    l_sfges_imm_t_table[param_t[0]](opq, 1, param[1]);
2481
  else
2482
    l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
2483
}
2484
 
2485
static const generic_gen_op l_sfgeu_null_t_table[NUM_T_REGS] =
2486
 { gen_op_sfgeu_null_t0, gen_op_sfgeu_null_t1, gen_op_sfgeu_null_t2 };
2487
 
2488
static const generic_gen_op l_sfleu_null_t_table[NUM_T_REGS] =
2489
 { gen_op_sfleu_null_t0, gen_op_sfleu_null_t1, gen_op_sfleu_null_t2 };
2490
 
2491
static const imm_gen_op l_sfgeu_imm_t_table[NUM_T_REGS] =
2492
 { gen_op_sfgeu_imm_t0, gen_op_sfgeu_imm_t1, gen_op_sfgeu_imm_t2 };
2493
 
2494
static const generic_gen_op l_sfgeu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2495
/* param0 -> t0 */ { gen_op_sfgeu_t0_t0, gen_op_sfgeu_t0_t1, gen_op_sfgeu_t0_t2 },
2496
/* param0 -> t1 */ { gen_op_sfgeu_t1_t0, gen_op_sfgeu_t1_t1, gen_op_sfgeu_t1_t2 },
2497
/* param0 -> t2 */ { gen_op_sfgeu_t2_t0, gen_op_sfgeu_t2_t1, gen_op_sfgeu_t2_t2 } };
2498
 
2499
void gen_l_sfgeu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2500
                 int delay_slot)
2501
{
2502
  if(!param[0] && !param[1]) {
2503
    gen_op_set_flag(opq, 1);
2504
    return;
2505
  }
2506
 
2507
  if(!param[0]) {
2508
    /* sfleu IS correct */
2509
    if(param_t[1] == T_NONE) {
2510
      if(0 >= param[1])
2511
        gen_op_set_flag(opq, 1);
2512
      else
2513
        gen_op_clear_flag(opq, 1);
2514
    } else
2515
      l_sfleu_null_t_table[param_t[1]](opq, 1);
2516
    return;
2517
  }
2518
 
2519
  if(!param[1]) {
2520
    l_sfgeu_null_t_table[param_t[0]](opq, 1);
2521
    return;
2522
  }
2523
  if(param_t[1] == T_NONE)
2524
    l_sfgeu_imm_t_table[param_t[0]](opq, 1, param[1]);
2525
  else
2526
    l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
2527
}
2528
 
2529
static const generic_gen_op l_sfgts_null_t_table[NUM_T_REGS] =
2530
 { gen_op_sfgts_null_t0, gen_op_sfgts_null_t1, gen_op_sfgts_null_t2 };
2531
 
2532
static const generic_gen_op l_sflts_null_t_table[NUM_T_REGS] =
2533
 { gen_op_sflts_null_t0, gen_op_sflts_null_t1, gen_op_sflts_null_t2 };
2534
 
2535
static const imm_gen_op l_sfgts_imm_t_table[NUM_T_REGS] =
2536
 { gen_op_sfgts_imm_t0, gen_op_sfgts_imm_t1, gen_op_sfgts_imm_t2 };
2537
 
2538
static const generic_gen_op l_sfgts_t_table[NUM_T_REGS][NUM_T_REGS] = {
2539
/* param0 -> t0 */ { gen_op_sfgts_t0_t0, gen_op_sfgts_t0_t1, gen_op_sfgts_t0_t2 },
2540
/* param0 -> t1 */ { gen_op_sfgts_t1_t0, gen_op_sfgts_t1_t1, gen_op_sfgts_t1_t2 },
2541
/* param0 -> t2 */ { gen_op_sfgts_t2_t0, gen_op_sfgts_t2_t1, gen_op_sfgts_t2_t2 } };
2542
 
2543
void gen_l_sfgts(struct op_queue *opq, int param_t[3], orreg_t param[3],
2544
                 int delay_slot)
2545
{
2546
  if(!param[0] && !param[1]) {
2547
    gen_op_clear_flag(opq, 1);
2548
    return;
2549
  }
2550
 
2551
  if(!param[0]) {
2552
    /* sflts IS correct */
2553
    if(param_t[1] == T_NONE) {
2554
      if(0 > (orreg_t)param[1])
2555
        gen_op_set_flag(opq, 1);
2556
      else
2557
        gen_op_clear_flag(opq, 1);
2558
    } else
2559
      l_sflts_null_t_table[param_t[1]](opq, 1);
2560
    return;
2561
  }
2562
 
2563
  if(!param[1]) {
2564
    l_sfgts_null_t_table[param_t[0]](opq, 1);
2565
    return;
2566
  }
2567
 
2568
  if(param_t[1] == T_NONE)
2569
    l_sfgts_imm_t_table[param_t[0]](opq, 1, param[1]);
2570
  else
2571
    l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
2572
}
2573
 
2574
static const generic_gen_op l_sfgtu_null_t_table[NUM_T_REGS] =
2575
 { gen_op_sfgtu_null_t0, gen_op_sfgtu_null_t1, gen_op_sfgtu_null_t2 };
2576
 
2577
static const generic_gen_op l_sfltu_null_t_table[NUM_T_REGS] =
2578
 { gen_op_sfltu_null_t0, gen_op_sfltu_null_t1, gen_op_sfltu_null_t2 };
2579
 
2580
static const imm_gen_op l_sfgtu_imm_t_table[NUM_T_REGS] =
2581
 { gen_op_sfgtu_imm_t0, gen_op_sfgtu_imm_t1, gen_op_sfgtu_imm_t2 };
2582
 
2583
static const generic_gen_op l_sfgtu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2584
/* param0 -> t0 */ { gen_op_sfgtu_t0_t0, gen_op_sfgtu_t0_t1, gen_op_sfgtu_t0_t2 },
2585
/* param0 -> t1 */ { gen_op_sfgtu_t1_t0, gen_op_sfgtu_t1_t1, gen_op_sfgtu_t1_t2 },
2586
/* param0 -> t2 */ { gen_op_sfgtu_t2_t0, gen_op_sfgtu_t2_t1, gen_op_sfgtu_t2_t2 } };
2587
 
2588
void gen_l_sfgtu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2589
                 int delay_slot)
2590
{
2591
  if(!param[0] && !param[1]) {
2592
    gen_op_clear_flag(opq, 1);
2593
    return;
2594
  }
2595
 
2596
  if(!param[0]) {
2597
    /* sfltu IS correct */
2598
    if(param_t[1] == T_NONE) {
2599
      if(0 > param[1])
2600
        gen_op_set_flag(opq, 1);
2601
      else
2602
        gen_op_clear_flag(opq, 1);
2603
    } else
2604
      l_sfltu_null_t_table[param_t[1]](opq, 1);
2605
    return;
2606
  }
2607
 
2608
  if(!param[1]) {
2609
    l_sfgtu_null_t_table[param_t[0]](opq, 1);
2610
    return;
2611
  }
2612
 
2613
  if(param_t[1] == T_NONE)
2614
    l_sfgtu_imm_t_table[param_t[0]](opq, 1, param[1]);
2615
  else
2616
    l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
2617
}
2618
 
2619
static const imm_gen_op l_sfles_imm_t_table[NUM_T_REGS] =
2620
 { gen_op_sfles_imm_t0, gen_op_sfles_imm_t1, gen_op_sfles_imm_t2 };
2621
 
2622
static const generic_gen_op l_sfles_t_table[NUM_T_REGS][NUM_T_REGS] = {
2623
/* param0 -> t0 */ { gen_op_sfles_t0_t0, gen_op_sfles_t0_t1, gen_op_sfles_t0_t2 },
2624
/* param0 -> t1 */ { gen_op_sfles_t1_t0, gen_op_sfles_t1_t1, gen_op_sfles_t1_t2 },
2625
/* param0 -> t2 */ { gen_op_sfles_t2_t0, gen_op_sfles_t2_t1, gen_op_sfles_t2_t2 } };
2626
 
2627
void gen_l_sfles(struct op_queue *opq, int param_t[3], orreg_t param[3],
2628
                 int delay_slot)
2629
{
2630
  if(!param[0] && !param[1]) {
2631
    gen_op_set_flag(opq, 1);
2632
    return;
2633
  }
2634
 
2635
  if(!param[0]) {
2636
    /* sfges IS correct */
2637
    if(param_t[1] == T_NONE) {
2638
      if(0 <= (orreg_t)param[1])
2639
        gen_op_set_flag(opq, 1);
2640
      else
2641
        gen_op_clear_flag(opq, 1);
2642
    } else
2643
      l_sfges_null_t_table[param_t[1]](opq, 1);
2644
    return;
2645
  }
2646
 
2647
  if(!param[1]) {
2648
    l_sfles_null_t_table[param_t[0]](opq, 1);
2649
    return;
2650
  }
2651
 
2652
  if(param_t[1] == T_NONE)
2653
    l_sfles_imm_t_table[param_t[0]](opq, 1, param[1]);
2654
  else
2655
    l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
2656
}
2657
 
2658
static const imm_gen_op l_sfleu_imm_t_table[NUM_T_REGS] =
2659
 { gen_op_sfleu_imm_t0, gen_op_sfleu_imm_t1, gen_op_sfleu_imm_t2 };
2660
 
2661
static const generic_gen_op l_sfleu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2662
/* param0 -> t0 */ { gen_op_sfleu_t0_t0, gen_op_sfleu_t0_t1, gen_op_sfleu_t0_t2 },
2663
/* param0 -> t1 */ { gen_op_sfleu_t1_t0, gen_op_sfleu_t1_t1, gen_op_sfleu_t1_t2 },
2664
/* param0 -> t2 */ { gen_op_sfleu_t2_t0, gen_op_sfleu_t2_t1, gen_op_sfleu_t2_t2 } };
2665
 
2666
void gen_l_sfleu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2667
                 int delay_slot)
2668
{
2669
  if(!param[0] && !param[1]) {
2670
    gen_op_set_flag(opq, 1);
2671
    return;
2672
  }
2673
 
2674
  if(!param[0]) {
2675
    /* sfleu IS correct */
2676
    if(param_t[1] == T_NONE) {
2677
      if(0 <= param[1])
2678
        gen_op_set_flag(opq, 1);
2679
      else
2680
        gen_op_clear_flag(opq, 1);
2681
    } else
2682
      l_sfgeu_null_t_table[param_t[1]](opq, 1);
2683
    return;
2684
  }
2685
 
2686
  if(!param[1]) {
2687
    l_sfleu_null_t_table[param_t[0]](opq, 1);
2688
    return;
2689
  }
2690
 
2691
  if(param_t[1] == T_NONE)
2692
    l_sfleu_imm_t_table[param_t[0]](opq, 1, param[1]);
2693
  else
2694
    l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
2695
}
2696
 
2697
static const imm_gen_op l_sflts_imm_t_table[NUM_T_REGS] =
2698
 { gen_op_sflts_imm_t0, gen_op_sflts_imm_t1, gen_op_sflts_imm_t2 };
2699
 
2700
static const generic_gen_op l_sflts_t_table[NUM_T_REGS][NUM_T_REGS] = {
2701
/* param0 -> t0 */ { gen_op_sflts_t0_t0, gen_op_sflts_t0_t1, gen_op_sflts_t0_t2 },
2702
/* param0 -> t1 */ { gen_op_sflts_t1_t0, gen_op_sflts_t1_t1, gen_op_sflts_t1_t2 },
2703
/* param0 -> t2 */ { gen_op_sflts_t2_t0, gen_op_sflts_t2_t1, gen_op_sflts_t2_t2 } };
2704
 
2705
void gen_l_sflts(struct op_queue *opq, int param_t[3], orreg_t param[3],
2706
                 int delay_slot)
2707
{
2708
  if(!param[0] && !param[1]) {
2709
    gen_op_clear_flag(opq, 1);
2710
    return;
2711
  }
2712
 
2713
  if(!param[0]) {
2714
    /* sfgts IS correct */
2715
    if(param_t[1] == T_NONE) {
2716
      if(0 < (orreg_t)param[1])
2717
        gen_op_set_flag(opq, 1);
2718
      else
2719
        gen_op_clear_flag(opq, 1);
2720
    } else
2721
      l_sfgts_null_t_table[param_t[1]](opq, 1);
2722
    return;
2723
  }
2724
 
2725
  if(!param[1]) {
2726
    l_sflts_null_t_table[param_t[0]](opq, 1);
2727
    return;
2728
  }
2729
 
2730
  if(param_t[1] == T_NONE)
2731
    l_sflts_imm_t_table[param_t[0]](opq, 1, param[1]);
2732
  else
2733
    l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
2734
}
2735
 
2736
static const imm_gen_op l_sfltu_imm_t_table[NUM_T_REGS] =
2737
 { gen_op_sfltu_imm_t0, gen_op_sfltu_imm_t1, gen_op_sfltu_imm_t2 };
2738
 
2739
static const generic_gen_op l_sfltu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2740
/* param0 -> t0 */ { gen_op_sfltu_t0_t0, gen_op_sfltu_t0_t1, gen_op_sfltu_t0_t2 },
2741
/* param0 -> t1 */ { gen_op_sfltu_t1_t0, gen_op_sfltu_t1_t1, gen_op_sfltu_t1_t2 },
2742
/* param0 -> t2 */ { gen_op_sfltu_t2_t0, gen_op_sfltu_t2_t1, gen_op_sfltu_t2_t2 } };
2743
 
2744
void gen_l_sfltu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2745
                 int delay_slot)
2746
{
2747
  if(!param[0] && !param[1]) {
2748
    gen_op_clear_flag(opq, 1);
2749
    return;
2750
  }
2751
 
2752
  if(!param[0]) {
2753
    /* sfgtu IS correct */
2754
    if(param_t[1] == T_NONE) {
2755
      if(0 < param[1])
2756
        gen_op_set_flag(opq, 1);
2757
      else
2758
        gen_op_clear_flag(opq, 1);
2759
    } else
2760
      l_sfgtu_null_t_table[param_t[1]](opq, 1);
2761
    return;
2762
  }
2763
 
2764
  if(!param[1]) {
2765
    l_sfltu_null_t_table[param_t[0]](opq, 1);
2766
    return;
2767
  }
2768
 
2769
  if(param_t[1] == T_NONE)
2770
    l_sfltu_imm_t_table[param_t[0]](opq, 1, param[1]);
2771
  else
2772
    l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
2773
}
2774
 
2775
static const generic_gen_op l_sfne_null_t_table[NUM_T_REGS] =
2776
 { gen_op_sfne_null_t0, gen_op_sfne_null_t1, gen_op_sfne_null_t2 };
2777
 
2778
static const imm_gen_op l_sfne_imm_t_table[NUM_T_REGS] =
2779
 { gen_op_sfne_imm_t0, gen_op_sfne_imm_t1, gen_op_sfne_imm_t2 };
2780
 
2781
static const generic_gen_op l_sfne_t_table[NUM_T_REGS][NUM_T_REGS] = {
2782
/* param0 -> t0 */ { gen_op_sfne_t0_t0, gen_op_sfne_t0_t1, gen_op_sfne_t0_t2 },
2783
/* param0 -> t1 */ { gen_op_sfne_t1_t0, gen_op_sfne_t1_t1, gen_op_sfne_t1_t2 },
2784
/* param0 -> t2 */ { gen_op_sfne_t2_t0, gen_op_sfne_t2_t1, gen_op_sfne_t2_t2 } };
2785
 
2786
void gen_l_sfne(struct op_queue *opq, int param_t[3], orreg_t param[3],
2787
                int delay_slot)
2788
{
2789
  if(!param[0] && !param[1]) {
2790
    gen_op_set_flag(opq, 1);
2791
    return;
2792
  }
2793
 
2794
  if(!param[0]) {
2795
    if(param_t[1] == T_NONE)
2796
      if(param[1])
2797
        gen_op_set_flag(opq, 1);
2798
      else
2799
        gen_op_clear_flag(opq, 1);
2800
    else
2801
      l_sfne_null_t_table[param_t[1]](opq, 1);
2802
    return;
2803
  }
2804
 
2805
  if(!param[1]) {
2806
    l_sfne_null_t_table[param_t[0]](opq, 1);
2807
    return;
2808
  }
2809
 
2810
  if(param_t[1] == T_NONE)
2811
    l_sfne_imm_t_table[param_t[0]](opq, 1, param[1]);
2812
  else
2813
    l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
2814
}
2815
 
2816
static const imm_gen_op l_sll_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2817
/* param0 -> t0 */ { gen_op_sll_imm_t0_t0, gen_op_sll_imm_t0_t1, gen_op_sll_imm_t0_t2 },
2818
/* param0 -> t1 */ { gen_op_sll_imm_t1_t0, gen_op_sll_imm_t1_t1, gen_op_sll_imm_t1_t2 },
2819
/* param0 -> t2 */ { gen_op_sll_imm_t2_t0, gen_op_sll_imm_t2_t1, gen_op_sll_imm_t2_t2 } };
2820
 
2821
static const generic_gen_op l_sll_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2822
/* param0 -> t0 */              {
2823
/* param0 -> t0, param1 -> t0 */ { gen_op_sll_t0_t0_t0, gen_op_sll_t0_t0_t1, gen_op_sll_t0_t0_t2 },
2824
/* param0 -> t0, param1 -> t1 */ { gen_op_sll_t0_t1_t0, gen_op_sll_t0_t1_t1, gen_op_sll_t0_t1_t2 },
2825
/* param0 -> t0, param1 -> t2 */ { gen_op_sll_t0_t2_t0, gen_op_sll_t0_t2_t1, gen_op_sll_t0_t2_t2 } },
2826
/* param0 -> t1 */              {
2827
/* param0 -> t1, param1 -> t0 */ { gen_op_sll_t1_t0_t0, gen_op_sll_t1_t0_t1, gen_op_sll_t1_t0_t2 },
2828
/* param0 -> t1, param1 -> t1 */ { gen_op_sll_t1_t1_t0, gen_op_sll_t1_t1_t1, gen_op_sll_t1_t1_t2 },
2829
/* param0 -> t1, param1 -> t2 */ { gen_op_sll_t1_t2_t0, gen_op_sll_t1_t2_t1, gen_op_sll_t1_t2_t2 } },
2830
/* param0 -> t2 */              {
2831
/* param0 -> t2, param1 -> t0 */ { gen_op_sll_t2_t0_t0, gen_op_sll_t2_t0_t1, gen_op_sll_t2_t0_t2 },
2832
/* param0 -> t2, param1 -> t1 */ { gen_op_sll_t2_t1_t0, gen_op_sll_t2_t1_t1, gen_op_sll_t2_t1_t2 },
2833
/* param0 -> t2, param1 -> t2 */ { gen_op_sll_t2_t2_t0, gen_op_sll_t2_t2_t1, gen_op_sll_t2_t2_t2 } } };
2834
 
2835
void gen_l_sll(struct op_queue *opq, int param_t[3], orreg_t param[3],
2836
               int delay_slot)
2837
{
2838
  if(!param[0])
2839
    return;
2840
 
2841
  if(!param[1]) {
2842
    clear_t[param_t[0]](opq, 1);
2843
    return;
2844
  }
2845
 
2846
  if(!param[2]) {
2847
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2848
    return;
2849
  }
2850
 
2851
  if(param_t[2] == T_NONE)
2852
    l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2853
  else
2854
    l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2855
}
2856
 
2857
static const imm_gen_op l_sra_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2858
/* param0 -> t0 */ { gen_op_sra_imm_t0_t0, gen_op_sra_imm_t0_t1, gen_op_sra_imm_t0_t2 },
2859
/* param0 -> t1 */ { gen_op_sra_imm_t1_t0, gen_op_sra_imm_t1_t1, gen_op_sra_imm_t1_t2 },
2860
/* param0 -> t2 */ { gen_op_sra_imm_t2_t0, gen_op_sra_imm_t2_t1, gen_op_sra_imm_t2_t2 } };
2861
 
2862
static const generic_gen_op l_sra_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2863
/* param0 -> t0 */              {
2864
/* param0 -> t0, param1 -> t0 */ { gen_op_sra_t0_t0_t0, gen_op_sra_t0_t0_t1, gen_op_sra_t0_t0_t2 },
2865
/* param0 -> t0, param1 -> t1 */ { gen_op_sra_t0_t1_t0, gen_op_sra_t0_t1_t1, gen_op_sra_t0_t1_t2 },
2866
/* param0 -> t0, param1 -> t2 */ { gen_op_sra_t0_t2_t0, gen_op_sra_t0_t2_t1, gen_op_sra_t0_t2_t2 } },
2867
/* param0 -> t1 */              {
2868
/* param0 -> t1, param1 -> t0 */ { gen_op_sra_t1_t0_t0, gen_op_sra_t1_t0_t1, gen_op_sra_t1_t0_t2 },
2869
/* param0 -> t1, param1 -> t1 */ { gen_op_sra_t1_t1_t0, gen_op_sra_t1_t1_t1, gen_op_sra_t1_t1_t2 },
2870
/* param0 -> t1, param1 -> t2 */ { gen_op_sra_t1_t2_t0, gen_op_sra_t1_t2_t1, gen_op_sra_t1_t2_t2 } },
2871
/* param0 -> t2 */              {
2872
/* param0 -> t2, param1 -> t0 */ { gen_op_sra_t2_t0_t0, gen_op_sra_t2_t0_t1, gen_op_sra_t2_t0_t2 },
2873
/* param0 -> t2, param1 -> t1 */ { gen_op_sra_t2_t1_t0, gen_op_sra_t2_t1_t1, gen_op_sra_t2_t1_t2 },
2874
/* param0 -> t2, param1 -> t2 */ { gen_op_sra_t2_t2_t0, gen_op_sra_t2_t2_t1, gen_op_sra_t2_t2_t2 } } };
2875
 
2876
void gen_l_sra(struct op_queue *opq, int param_t[3], orreg_t param[3],
2877
               int delay_slot)
2878
{
2879
  if(!param[0])
2880
    return;
2881
 
2882
  if(!param[1]) {
2883
    clear_t[param_t[0]](opq, 1);
2884
    return;
2885
  }
2886
 
2887
  if(!param[2]) {
2888
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2889
    return;
2890
  }
2891
 
2892
  if(param_t[2] == T_NONE)
2893
    l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2894
  else
2895
    l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2896
}
2897
 
2898
static const imm_gen_op l_srl_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2899
/* param0 -> t0 */ { gen_op_srl_imm_t0_t0, gen_op_srl_imm_t0_t1, gen_op_srl_imm_t0_t2 },
2900
/* param0 -> t1 */ { gen_op_srl_imm_t1_t0, gen_op_srl_imm_t1_t1, gen_op_srl_imm_t1_t2 },
2901
/* param0 -> t2 */ { gen_op_srl_imm_t2_t0, gen_op_srl_imm_t2_t1, gen_op_srl_imm_t2_t2 } };
2902
 
2903
static const generic_gen_op l_srl_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2904
/* param0 -> t0 */              {
2905
/* param0 -> t0, param1 -> t0 */ { gen_op_srl_t0_t0_t0, gen_op_srl_t0_t0_t1, gen_op_srl_t0_t0_t2 },
2906
/* param0 -> t0, param1 -> t1 */ { gen_op_srl_t0_t1_t0, gen_op_srl_t0_t1_t1, gen_op_srl_t0_t1_t2 },
2907
/* param0 -> t0, param1 -> t2 */ { gen_op_srl_t0_t2_t0, gen_op_srl_t0_t2_t1, gen_op_srl_t0_t2_t2 } },
2908
/* param0 -> t1 */              {
2909
/* param0 -> t1, param1 -> t0 */ { gen_op_srl_t1_t0_t0, gen_op_srl_t1_t0_t1, gen_op_srl_t1_t0_t2 },
2910
/* param0 -> t1, param1 -> t1 */ { gen_op_srl_t1_t1_t0, gen_op_srl_t1_t1_t1, gen_op_srl_t1_t1_t2 },
2911
/* param0 -> t1, param1 -> t2 */ { gen_op_srl_t1_t2_t0, gen_op_srl_t1_t2_t1, gen_op_srl_t1_t2_t2 } },
2912
/* param0 -> t2 */              {
2913
/* param0 -> t2, param1 -> t0 */ { gen_op_srl_t2_t0_t0, gen_op_srl_t2_t0_t1, gen_op_srl_t2_t0_t2 },
2914
/* param0 -> t2, param1 -> t1 */ { gen_op_srl_t2_t1_t0, gen_op_srl_t2_t1_t1, gen_op_srl_t2_t1_t2 },
2915
/* param0 -> t2, param1 -> t2 */ { gen_op_srl_t2_t2_t0, gen_op_srl_t2_t2_t1, gen_op_srl_t2_t2_t2 } } };
2916
 
2917
void gen_l_srl(struct op_queue *opq, int param_t[3], orreg_t param[3],
2918
               int delay_slot)
2919
{
2920
  if(!param[0])
2921
    return;
2922
 
2923
  if(!param[1]) {
2924
    clear_t[param_t[0]](opq, 1);
2925
    return;
2926
  }
2927
 
2928
  if(!param[2]) {
2929
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2930
    return;
2931
  }
2932
 
2933
  if(param_t[2] == T_NONE)
2934
    l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2935
  else
2936
    l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2937
}
2938
 
2939
static const generic_gen_op l_neg_t_table[NUM_T_REGS][NUM_T_REGS] = {
2940
/* param0 -> t0 */ { gen_op_neg_t0_t0, gen_op_neg_t0_t1, gen_op_neg_t0_t2 },
2941
/* param0 -> t1 */ { gen_op_neg_t1_t0, gen_op_neg_t1_t1, gen_op_neg_t1_t2 },
2942
/* param0 -> t2 */ { gen_op_neg_t2_t0, gen_op_neg_t2_t1, gen_op_neg_t2_t2 } };
2943
 
2944
static const generic_gen_op l_sub_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2945
/* param0 -> t0 */              {
2946
/* param0 -> t0, param1 -> t0 */ { gen_op_sub_t0_t0_t0, gen_op_sub_t0_t0_t1, gen_op_sub_t0_t0_t2 },
2947
/* param0 -> t0, param1 -> t1 */ { gen_op_sub_t0_t1_t0, gen_op_sub_t0_t1_t1, gen_op_sub_t0_t1_t2 },
2948
/* param0 -> t0, param1 -> t2 */ { gen_op_sub_t0_t2_t0, gen_op_sub_t0_t2_t1, gen_op_sub_t0_t2_t2 } },
2949
/* param0 -> t1 */              {
2950
/* param0 -> t1, param1 -> t0 */ { gen_op_sub_t1_t0_t0, gen_op_sub_t1_t0_t1, gen_op_sub_t1_t0_t2 },
2951
/* param0 -> t1, param1 -> t1 */ { gen_op_sub_t1_t1_t0, gen_op_sub_t1_t1_t1, gen_op_sub_t1_t1_t2 },
2952
/* param0 -> t1, param1 -> t2 */ { gen_op_sub_t1_t2_t0, gen_op_sub_t1_t2_t1, gen_op_sub_t1_t2_t2 } },
2953
/* param0 -> t2 */              {
2954
/* param0 -> t2, param1 -> t0 */ { gen_op_sub_t2_t0_t0, gen_op_sub_t2_t0_t1, gen_op_sub_t2_t0_t2 },
2955
/* param0 -> t2, param1 -> t1 */ { gen_op_sub_t2_t1_t0, gen_op_sub_t2_t1_t1, gen_op_sub_t2_t1_t2 },
2956
/* param0 -> t2, param1 -> t2 */ { gen_op_sub_t2_t2_t0, gen_op_sub_t2_t2_t1, gen_op_sub_t2_t2_t2 } } };
2957
 
2958
void gen_l_sub(struct op_queue *opq, int param_t[3], orreg_t param[3],
2959
               int delay_slot)
2960
{
2961
  if(!param[0])
2962
    return;
2963
 
2964
  if((param_t[2] != T_NONE) && (param[1] == param[2])) {
2965
    clear_t[param_t[0]](opq, 1);
2966
    return;
2967
  }
2968
 
2969
  if(!param[1] && !param[2]) {
2970
    clear_t[param_t[0]](opq, 1);
2971
    return;
2972
  }
2973
 
2974
  if(!param[1]) {
2975
    if(param_t[2] == T_NONE)
2976
      mov_t_imm[param_t[0]](opq, 1, -param[2]);
2977
    else
2978
      l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
2979
    return;
2980
  }
2981
 
2982
  if(!param[2]) {
2983
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2984
    return;
2985
  }
2986
 
2987
  l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2988
}
2989
 
2990
/* FIXME: This will not work if the l.sys is in a delay slot */
2991
void gen_l_sys(struct op_queue *opq, int param_t[3], orreg_t param[3],
2992
               int delay_slot)
2993
{
2994
  /* Since we *know* that we *will* jump to the next instruction, insert an xref
2995
   * there */
2996
  find_jump_loc(opq->insn_addr + 4, opq);
2997
 
2998
  if(!delay_slot)
2999
    gen_op_prep_sys(opq, 1);
3000
  else
3001
    gen_op_prep_sys_delay(opq, 1);
3002
}
3003
 
3004
/* FIXME: This will not work if the l.trap is in a delay slot */
3005
void gen_l_trap(struct op_queue *opq, int param_t[3], orreg_t param[3],
3006
                int delay_slot)
3007
{
3008
  /* Since we *know* that we *will* jump to the next instruction, insert an xref
3009
   * there */
3010
  find_jump_loc(opq->insn_addr + 4, opq);
3011
 
3012
  if(!delay_slot)
3013
    gen_op_prep_trap(opq, 1);
3014
  else
3015
    gen_op_prep_trap_delay(opq, 1);
3016
}
3017
 
3018
static const imm_gen_op l_xor_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
3019
/* param0 -> t0 */ { gen_op_xor_imm_t0_t0, gen_op_xor_imm_t0_t1, gen_op_xor_imm_t0_t2 },
3020
/* param0 -> t1 */ { gen_op_xor_imm_t1_t0, gen_op_xor_imm_t1_t1, gen_op_xor_imm_t1_t2 },
3021
/* param0 -> t2 */ { gen_op_xor_imm_t2_t0, gen_op_xor_imm_t2_t1, gen_op_xor_imm_t2_t2 } };
3022
 
3023
static const generic_gen_op l_xor_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
3024
/* param0 -> t0 */              {
3025
/* param0 -> t0, param1 -> t0 */ { gen_op_xor_t0_t0_t0, gen_op_xor_t0_t0_t1, gen_op_xor_t0_t0_t2 },
3026
/* param0 -> t0, param1 -> t1 */ { gen_op_xor_t0_t1_t0, gen_op_xor_t0_t1_t1, gen_op_xor_t0_t1_t2 },
3027
/* param0 -> t0, param1 -> t2 */ { gen_op_xor_t0_t2_t0, gen_op_xor_t0_t2_t1, gen_op_xor_t0_t2_t2 } },
3028
/* param0 -> t1 */              {
3029
/* param0 -> t1, param1 -> t0 */ { gen_op_xor_t1_t0_t0, gen_op_xor_t1_t0_t1, gen_op_xor_t1_t0_t2 },
3030
/* param0 -> t1, param1 -> t1 */ { gen_op_xor_t1_t1_t0, gen_op_xor_t1_t1_t1, gen_op_xor_t1_t1_t2 },
3031
/* param0 -> t1, param1 -> t2 */ { gen_op_xor_t1_t2_t0, gen_op_xor_t1_t2_t1, gen_op_xor_t1_t2_t2 } },
3032
/* param0 -> t2 */              {
3033
/* param0 -> t2, param1 -> t0 */ { gen_op_xor_t2_t0_t0, gen_op_xor_t2_t0_t1, gen_op_xor_t2_t0_t2 },
3034
/* param0 -> t2, param1 -> t1 */ { gen_op_xor_t2_t1_t0, gen_op_xor_t2_t1_t1, gen_op_xor_t2_t1_t2 },
3035
/* param0 -> t2, param1 -> t2 */ { gen_op_xor_t2_t2_t0, gen_op_xor_t2_t2_t1, gen_op_xor_t2_t2_t2 } } };
3036
 
3037
void gen_l_xor(struct op_queue *opq, int param_t[3], orreg_t param[3],
3038
               int delay_slot)
3039
{
3040
  if(!param[0])
3041
    return;
3042
 
3043
  if((param_t[2] != T_NONE) && (param[1] == param[2])) {
3044
    clear_t[param_t[0]](opq, 1);
3045
    return;
3046
  }
3047
 
3048
  if(!param[2]) {
3049
    if((param_t[2] == T_NONE) && (param[0] == param[1]))
3050
      return;
3051
    move_t_t[param_t[0]][param_t[1]](opq, 1);
3052
    return;
3053
  }
3054
 
3055
  if(!param[1]) {
3056
    if(param_t[2] == T_NONE) {
3057
      mov_t_imm[param_t[0]](opq, 1, param[2]);
3058
      return;
3059
    }
3060
    move_t_t[param_t[0]][param_t[2]](opq, 1);
3061
    return;
3062
  }
3063
 
3064
  if(param_t[2] == T_NONE)
3065
    l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
3066
  else
3067
    l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
3068
}
3069
 
3070
void gen_l_invalid(struct op_queue *opq, int param_t[3], orreg_t param[3],
3071
                   int delay_slot)
3072
{
3073
  /* The program running on openrisc may decide to patch this location, so
3074
   * just cross reference this location just-in-case */
3075
  find_jump_loc(opq->insn_addr, opq);
3076
  if(!delay_slot)
3077
    gen_op_illegal(opq, 1);
3078
  else
3079
    gen_op_illegal_delay(opq, 1);
3080
}
3081
 
3082
/*----------------------------------[ Floating point instructions (stubs) ]---*/
3083
void gen_lf_add_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3084
                  int delay_slot)
3085
{
3086
  gen_l_invalid(opq, param_t, param, delay_slot);
3087
}
3088
 
3089
void gen_lf_div_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3090
                  int delay_slot)
3091
{
3092
  gen_l_invalid(opq, param_t, param, delay_slot);
3093
}
3094
 
3095
void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3096
                   int delay_slot)
3097
{
3098
  gen_l_invalid(opq, param_t, param, delay_slot);
3099
}
3100
 
3101
void gen_lf_itof_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3102
                   int delay_slot)
3103
{
3104
  gen_l_invalid(opq, param_t, param, delay_slot);
3105
}
3106
 
3107
void gen_lf_madd_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3108
                   int delay_slot)
3109
{
3110
  gen_l_invalid(opq, param_t, param, delay_slot);
3111
}
3112
 
3113
void gen_lf_mul_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3114
                  int delay_slot)
3115
{
3116
  gen_l_invalid(opq, param_t, param, delay_slot);
3117
}
3118
 
3119
void gen_lf_rem_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3120
                  int delay_slot)
3121
{
3122
  gen_l_invalid(opq, param_t, param, delay_slot);
3123
}
3124
 
3125
void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3126
                   int delay_slot)
3127
{
3128
  gen_l_invalid(opq, param_t, param, delay_slot);
3129
}
3130
 
3131
void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3132
                   int delay_slot)
3133
{
3134
  gen_l_invalid(opq, param_t, param, delay_slot);
3135
}
3136
 
3137
void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3138
                   int delay_slot)
3139
{
3140
  gen_l_invalid(opq, param_t, param, delay_slot);
3141
}
3142
 
3143
void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3144
                   int delay_slot)
3145
{
3146
  gen_l_invalid(opq, param_t, param, delay_slot);
3147
}
3148
 
3149
void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3150
                   int delay_slot)
3151
{
3152
  gen_l_invalid(opq, param_t, param, delay_slot);
3153
}
3154
 
3155
void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3156
                   int delay_slot)
3157
{
3158
  gen_l_invalid(opq, param_t, param, delay_slot);
3159
}
3160
 
3161
void gen_lf_sub_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3162
                  int delay_slot)
3163
{
3164
  gen_l_invalid(opq, param_t, param, delay_slot);
3165
}
3166
 

powered by: WebSVN 2.1.0

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