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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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