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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [cpu/] [or32/] [dyn_rec.c] - Blame information for rev 1543

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

powered by: WebSVN 2.1.0

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