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 1526

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

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

powered by: WebSVN 2.1.0

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