URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/tags/or1ksim/or1ksim-0.5.0rc2/cpu/or32
- from Rev 385 to Rev 388
- ↔ Reverse comparison
Rev 385 → Rev 388
/execute.c
0,0 → 1,1268
/* execute.c -- OR1K architecture dependent simulation |
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
Copyright (C) 2008 Embecosm Limited |
Copyright (C) 2010 ORSoC AB |
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com> |
Contributor Julius Baxter <julius.baxter@orsoc.se> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify it |
under the terms of the GNU General Public License as published by the Free |
Software Foundation; either version 3 of the License, or (at your option) |
any later version. |
|
This program is distributed in the hope that it will be useful, but WITHOUT |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
more details. |
|
You should have received a copy of the GNU General Public License along |
with this program. If not, see <http://www.gnu.org/licenses/>. */ |
|
/* This program is commented throughout in a fashion suitable for processing |
with Doxygen. */ |
|
|
/* Most of the OR1K simulation is done in here. |
|
When SIMPLE_EXECUTION is defined below a file insnset.c is included! |
*/ |
|
/* Autoconf and/or portability configuration */ |
#include "config.h" |
#include "port.h" |
|
/* System includes */ |
#include <stdlib.h> |
|
/* Package includes */ |
#include "execute.h" |
#include "toplevel-support.h" |
#include "except.h" |
#include "labels.h" |
#include "sched.h" |
#include "stats.h" |
#include "opcode/or32.h" |
#include "dmmu.h" |
#include "immu.h" |
#include "sim-cmd.h" |
#include "vapi.h" |
#include "debug-unit.h" |
#include "branch-predict.h" |
#include "sprs.h" |
#include "rsp-server.h" |
#include "softfloat.h" |
|
/* Includes and macros for simple execution */ |
#if SIMPLE_EXECUTION |
|
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn) |
|
#define PARAM0 eval_operand(0, current->insn_index, current->insn) |
#define PARAM1 eval_operand(1, current->insn_index, current->insn) |
#define PARAM2 eval_operand(2, current->insn_index, current->insn) |
|
#define INSTRUCTION(name) void name (struct iqueue_entry *current) |
|
#endif /* SIMPLE_EXECUTION */ |
|
|
/*! Current cpu state. Globally available. */ |
struct cpu_state cpu_state; |
|
/*! Temporary program counter. Globally available */ |
oraddr_t pcnext; |
|
/*! Num cycles waiting for stores to complete. Globally available */ |
int sbuf_wait_cyc = 0; |
|
/*! Number of total store cycles. Globally available */ |
int sbuf_total_cyc = 0; |
|
/*! Whether we are doing statistical analysis. Globally available */ |
int do_stats = 0; |
|
/*! History of execution. Globally available */ |
struct hist_exec *hist_exec_tail = NULL; |
|
/* Benchmark multi issue execution. This file only */ |
static int multissue[20]; |
static int issued_per_cycle = 4; |
|
/* Store buffer analysis - stores are accumulated and commited when IO is |
idle. This file only */ |
static int sbuf_head = 0; |
static int sbuf_tail = 0; |
static int sbuf_count = 0; |
#if !(DYNAMIC_EXECUTION) |
static int sbuf_buf[MAX_SBUF_LEN] = { 0 }; |
#endif |
|
static int sbuf_prev_cycles = 0; |
|
/* Variables used throughout this file to share information */ |
static int breakpoint; |
static int next_delay_insn; |
|
/* Forward declaration of static functions */ |
#if !(DYNAMIC_EXECUTION) |
static void decode_execute (struct iqueue_entry *current); |
#endif |
|
/*---------------------------------------------------------------------------*/ |
/*!Get an actual value of a specific register |
|
Implementation specific. Abort if we are given a duff register. Only used |
externally to support simprintf(), which is now obsolete. |
|
@param[in] regno The register of interest |
|
@return The value of the register */ |
/*---------------------------------------------------------------------------*/ |
uorreg_t |
evalsim_reg (unsigned int regno) |
{ |
if (regno < MAX_GPRS) |
{ |
#if RAW_RANGE_STATS |
int delta = (runtime.sim.cycles - raw_stats.reg[regno]); |
|
if ((unsigned long) delta < (unsigned long) RAW_RANGE) |
{ |
raw_stats.range[delta]++; |
} |
#endif /* RAW_RANGE */ |
|
return cpu_state.reg[regno]; |
} |
else |
{ |
PRINTF ("\nABORT: read out of registers\n"); |
sim_done (); |
return 0; |
} |
} /* evalsim_reg() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Set a specific register with value |
|
Implementation specific. Abort if we are given a duff register. |
|
@param[in] regno The register of interest |
@param[in] value The value to be set */ |
/*---------------------------------------------------------------------------*/ |
void |
setsim_reg (unsigned int regno, |
uorreg_t value) |
{ |
if (regno == 0) /* gpr0 is always zero */ |
{ |
value = 0; |
} |
|
if (regno < MAX_GPRS) |
{ |
cpu_state.reg[regno] = value; |
} |
else |
{ |
PRINTF ("\nABORT: write out of registers\n"); |
sim_done (); |
} |
|
#if RAW_RANGE_STATS |
raw_stats.reg[regno] = runtime.sim.cycles; |
#endif /* RAW_RANGE */ |
|
} /* setsim_reg() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Evaluates source operand operand |
|
Implementation specific. Declared global, although this is only actually |
required for DYNAMIC_EXECUTION, |
|
@param[in] insn The instruction |
@param[in] opd The operand |
|
@return The value of the source operand */ |
/*---------------------------------------------------------------------------*/ |
uorreg_t |
eval_operand_val (uint32_t insn, |
struct insn_op_struct *opd) |
{ |
unsigned long operand = 0; |
unsigned long sbit; |
unsigned int nbits = 0; |
|
while (1) |
{ |
operand |= |
((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << |
nbits; |
nbits += opd->data; |
|
if (opd->type & OPTYPE_OP) |
{ |
break; |
} |
|
opd++; |
} |
|
if (opd->type & OPTYPE_SIG) |
{ |
sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; |
|
if (operand & (1 << sbit)) |
{ |
operand |= ~REG_C (0) << sbit; |
} |
} |
|
return operand; |
|
} /* eval_operand_val() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Does source operand depend on computation of dest operand? |
|
Cycle t Cycle t+1 |
dst: irrelevant src: immediate always 0 |
dst: reg1 direct src: reg2 direct 0 if reg1 != reg2 |
dst: reg1 disp src: reg2 direct always 0 |
dst: reg1 direct src: reg2 disp 0 if reg1 != reg2 |
dst: reg1 disp src: reg2 disp always 1 (store must |
finish before load) |
dst: flag src: flag always 1 |
|
@param[in] prev Previous instruction |
@param[in] next Next instruction |
|
@return Non-zero if yes. */ |
/*---------------------------------------------------------------------------*/ |
static int |
check_depend (struct iqueue_entry *prev, |
struct iqueue_entry *next) |
{ |
/* Find destination type. */ |
unsigned long type = 0; |
int prev_dis; |
int next_dis; |
orreg_t prev_reg_val = 0; |
struct insn_op_struct *opd; |
|
if (or1ksim_or32_opcodes[prev->insn_index].flags & OR32_W_FLAG |
&& or1ksim_or32_opcodes[next->insn_index].flags & OR32_R_FLAG) |
{ |
return 1; |
} |
|
opd = or1ksim_op_start[prev->insn_index]; |
prev_dis = 0; |
|
while (1) |
{ |
if (opd->type & OPTYPE_DIS) |
{ |
prev_dis = 1; |
} |
|
if (opd->type & OPTYPE_DST) |
{ |
type = opd->type; |
|
if (prev_dis) |
{ |
type |= OPTYPE_DIS; |
} |
|
/* Destination is always a register */ |
prev_reg_val = eval_operand_val (prev->insn, opd); |
break; |
} |
|
if (opd->type & OPTYPE_LAST) |
{ |
return 0; /* Doesn't have a destination operand */ |
} |
|
if (opd->type & OPTYPE_OP) |
{ |
prev_dis = 0; |
} |
|
opd++; |
} |
|
/* We search all source operands - if we find confict => return 1 */ |
opd = or1ksim_op_start[next->insn_index]; |
next_dis = 0; |
|
while (1) |
{ |
if (opd->type & OPTYPE_DIS) |
{ |
next_dis = 1; |
} |
|
/* This instruction sequence also depends on order of execution: |
l.lw r1, k(r1) |
l.sw k(r1), r4 |
Here r1 is a destination in l.sw */ |
|
/* FIXME: This situation is not handeld here when r1 == r2: |
l.sw k(r1), r4 |
l.lw r3, k(r2) */ |
if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) |
{ |
if (opd->type & OPTYPE_REG) |
{ |
if (eval_operand_val (next->insn, opd) == prev_reg_val) |
{ |
return 1; |
} |
} |
} |
|
if (opd->type & OPTYPE_LAST) |
{ |
break; |
} |
|
opd++; |
} |
|
return 0; |
|
} /* check_depend() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Should instruction NOT be executed? |
|
Modified by CZ 26/05/01 for new mode execution. |
|
@return Nonzero if instruction should NOT be executed */ |
/*---------------------------------------------------------------------------*/ |
static int |
fetch () |
{ |
static int break_just_hit = 0; |
|
if (NULL != breakpoints) |
{ |
/* MM: Check for breakpoint. This has to be done in fetch cycle, |
because of peripheria. |
MM1709: if we cannot access the memory entry, we could not set the |
breakpoint earlier, so just check the breakpoint list. */ |
if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit) |
{ |
break_just_hit = 1; |
return 1; /* Breakpoint set. */ |
} |
break_just_hit = 0; |
} |
|
breakpoint = 0; |
cpu_state.iqueue.insn_addr = cpu_state.pc; |
cpu_state.iqueue.insn = eval_insn (cpu_state.pc, &breakpoint); |
|
/* Fetch instruction. */ |
if (!except_pending) |
{ |
runtime.cpu.instructions++; |
} |
|
/* update_pc will be called after execution */ |
return 0; |
|
} /* fetch() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!This code actually updates the PC value */ |
/*---------------------------------------------------------------------------*/ |
static void |
update_pc () |
{ |
cpu_state.delay_insn = next_delay_insn; |
cpu_state.sprs[SPR_PPC] = cpu_state.pc; /* Store value for later */ |
cpu_state.pc = pcnext; |
pcnext = cpu_state.delay_insn ? cpu_state.pc_delay : |
pcnext + 4; |
} /* update_pc() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Perform analysis of the instruction being executed |
|
This could be static for SIMPLE_EXECUTION, but made global for general use. |
|
@param[in] current The instruction being executed */ |
/*---------------------------------------------------------------------------*/ |
void |
analysis (struct iqueue_entry *current) |
{ |
if (config.cpu.dependstats) |
{ |
/* Dynamic, dependency stats. */ |
adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1, |
check_depend (&cpu_state.icomplet, current)); |
|
/* Dynamic, functional units stats. */ |
addfstats (or1ksim_or32_opcodes[cpu_state.icomplet.insn_index].func_unit, |
or1ksim_or32_opcodes[current->insn_index].func_unit, 1, |
check_depend (&cpu_state.icomplet, current)); |
|
/* Dynamic, single stats. */ |
addsstats (current->insn_index, 1); |
} |
|
if (config.cpu.superscalar) |
{ |
if ((or1ksim_or32_opcodes[current->insn_index].func_unit == it_branch) || |
(or1ksim_or32_opcodes[current->insn_index].func_unit == it_jump)) |
runtime.sim.storecycles += 0; |
|
if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_store) |
runtime.sim.storecycles += 1; |
|
if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_load) |
runtime.sim.loadcycles += 1; |
|
/* Pseudo multiple issue benchmark */ |
if ((multissue[or1ksim_or32_opcodes[current->insn_index].func_unit] < 1) || |
(check_depend (&cpu_state.icomplet, current)) |
|| (issued_per_cycle < 1)) |
{ |
int i; |
for (i = 0; i < 20; i++) |
multissue[i] = 2; |
issued_per_cycle = 2; |
runtime.cpu.supercycles++; |
if (check_depend (&cpu_state.icomplet, current)) |
runtime.cpu.hazardwait++; |
multissue[it_unknown] = 2; |
multissue[it_shift] = 2; |
multissue[it_compare] = 1; |
multissue[it_branch] = 1; |
multissue[it_jump] = 1; |
multissue[it_extend] = 2; |
multissue[it_nop] = 2; |
multissue[it_move] = 2; |
multissue[it_movimm] = 2; |
multissue[it_arith] = 2; |
multissue[it_store] = 2; |
multissue[it_load] = 2; |
} |
multissue[or1ksim_or32_opcodes[current->insn_index].func_unit]--; |
issued_per_cycle--; |
} |
|
if (config.cpu.dependstats) |
/* Instruction waits in completition buffer until retired. */ |
memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry)); |
|
if (config.sim.history) |
{ |
/* History of execution */ |
hist_exec_tail = hist_exec_tail->next; |
hist_exec_tail->addr = cpu_state.icomplet.insn_addr; |
} |
|
if (config.sim.exe_log) |
dump_exe_log (); |
|
if (config.sim.exe_bin_insn_log) |
dump_exe_bin_insn_log (current); |
|
} /* analysis() */ |
|
|
#if !(DYNAMIC_EXECUTION) |
|
/*---------------------------------------------------------------------------*/ |
/*!Store buffer analysis for store instructions |
|
Stores are accumulated and commited when IO is idle |
|
@param[in] cyc Number of cycles being analysed */ |
/*---------------------------------------------------------------------------*/ |
static void |
sbuf_store (int cyc) |
{ |
int delta = runtime.sim.cycles - sbuf_prev_cycles; |
|
sbuf_total_cyc += cyc; |
sbuf_prev_cycles = runtime.sim.cycles; |
|
/* Take stores from buffer, that occured meanwhile */ |
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) |
{ |
delta -= sbuf_buf[sbuf_tail]; |
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; |
sbuf_count--; |
} |
|
if (sbuf_count) |
{ |
sbuf_buf[sbuf_tail] -= delta; |
} |
|
/* Store buffer is full, take one out */ |
if (sbuf_count >= config.cpu.sbuf_len) |
{ |
sbuf_wait_cyc += sbuf_buf[sbuf_tail]; |
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail]; |
sbuf_prev_cycles += sbuf_buf[sbuf_tail]; |
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; |
sbuf_count--; |
} |
|
/* Put newest store in the buffer */ |
sbuf_buf[sbuf_head] = cyc; |
sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN; |
sbuf_count++; |
|
} /* sbuf_store() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Store buffer analysis for load instructions |
|
Previous stores should commit, before any load */ |
/*---------------------------------------------------------------------------*/ |
static void |
sbuf_load () |
{ |
int delta = runtime.sim.cycles - sbuf_prev_cycles; |
sbuf_prev_cycles = runtime.sim.cycles; |
|
/* Take stores from buffer, that occured meanwhile */ |
while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) |
{ |
delta -= sbuf_buf[sbuf_tail]; |
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; |
sbuf_count--; |
} |
|
if (sbuf_count) |
{ |
sbuf_buf[sbuf_tail] -= delta; |
} |
|
/* Wait for all stores to complete */ |
while (sbuf_count > 0) |
{ |
sbuf_wait_cyc += sbuf_buf[sbuf_tail]; |
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail]; |
sbuf_prev_cycles += sbuf_buf[sbuf_tail]; |
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; |
sbuf_count--; |
} |
} /* sbuf_load() */ |
|
#endif /* !DYNAMIC_EXECUTION */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Outputs dissasembled instruction */ |
/*---------------------------------------------------------------------------*/ |
void |
dump_exe_log () |
{ |
oraddr_t insn_addr = cpu_state.iqueue.insn_addr; |
unsigned int i; |
unsigned int j; |
uorreg_t operand; |
|
if (insn_addr == 0xffffffff) |
{ |
return; |
} |
|
if ((config.sim.exe_log_start <= runtime.cpu.instructions) && |
((config.sim.exe_log_end <= 0) || |
(runtime.cpu.instructions <= config.sim.exe_log_end))) |
{ |
struct label_entry *entry; |
|
if (config.sim.exe_log_marker && |
!(runtime.cpu.instructions % config.sim.exe_log_marker)) |
{ |
fprintf (runtime.sim.fexe_log, |
"--------------------- %8lli instruction " |
"---------------------\n", |
runtime.cpu.instructions); |
} |
|
switch (config.sim.exe_log_type) |
{ |
case EXE_LOG_HARDWARE: |
fprintf (runtime.sim.fexe_log, |
"\nEXECUTED(%11llu): %" PRIxADDR ": ", |
runtime.cpu.instructions, insn_addr); |
fprintf (runtime.sim.fexe_log, "%.2x%.2x", |
eval_direct8 (insn_addr, 0, 0), |
eval_direct8 (insn_addr + 1, 0, 0)); |
fprintf (runtime.sim.fexe_log, "%.2x%.2x", |
eval_direct8 (insn_addr + 2, 0, 0), |
eval_direct8 (insn_addr + 3, 0, 0)); |
|
for (i = 0; i < MAX_GPRS; i++) |
{ |
if (i % 4 == 0) |
{ |
fprintf (runtime.sim.fexe_log, "\n"); |
} |
|
fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG " ", i, |
cpu_state.reg[i]); |
} |
|
fprintf (runtime.sim.fexe_log, "\n"); |
fprintf (runtime.sim.fexe_log, "SR : %.8" PRIx32 " ", |
cpu_state.sprs[SPR_SR]); |
fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR " ", |
cpu_state.sprs[SPR_EPCR_BASE]); |
fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR " ", |
cpu_state.sprs[SPR_EEAR_BASE]); |
fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n", |
cpu_state.sprs[SPR_ESR_BASE]); |
break; |
|
case EXE_LOG_SIMPLE: |
case EXE_LOG_SOFTWARE: |
or1ksim_disassemble_index (cpu_state.iqueue.insn, |
cpu_state.iqueue.insn_index); |
|
entry = get_label (insn_addr); |
if (entry) |
{ |
fprintf (runtime.sim.fexe_log, "%s:\n", entry->name); |
} |
|
if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) |
{ |
struct insn_op_struct *opd = |
or1ksim_op_start[cpu_state.iqueue.insn_index]; |
|
j = 0; |
while (1) |
{ |
operand = eval_operand_val (cpu_state.iqueue.insn, opd); |
while (!(opd->type & OPTYPE_OP)) |
{ |
opd++; |
} |
if (opd->type & OPTYPE_DIS) |
{ |
fprintf (runtime.sim.fexe_log, |
"EA =%" PRIxADDR " PA =%" PRIxADDR " ", |
cpu_state.insn_ea, |
peek_into_dtlb (cpu_state.insn_ea, 0, 0)); |
opd++; /* Skip of register operand */ |
j++; |
} |
else if ((opd->type & OPTYPE_REG) && operand) |
{ |
fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ", |
(int) operand, evalsim_reg (operand)); |
} |
else |
{ |
fprintf (runtime.sim.fexe_log, " "); |
} |
j++; |
if (opd->type & OPTYPE_LAST) |
{ |
break; |
} |
opd++; |
} |
if (or1ksim_or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG) |
{ |
fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ", |
cpu_state.sprs[SPR_SR]); |
j++; |
} |
while (j < 3) |
{ |
fprintf (runtime.sim.fexe_log, " "); |
j++; |
} |
} |
fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr); |
fprintf (runtime.sim.fexe_log, "%s\n", or1ksim_disassembled); |
} |
} |
} /* dump_exe_log() */ |
|
|
|
/*---------------------------------------------------------------------------*/ |
/*!Outputs binary copy of instruction to a file */ |
/*---------------------------------------------------------------------------*/ |
void |
dump_exe_bin_insn_log (struct iqueue_entry *current) |
{ |
// Do endian swap before spitting out (will be kept in LE on a LE machine) |
// but more useful to see it in big endian format. |
// Should probably host htonl(). |
uint32_t insn = (((current->insn & 0xff)<<24) | |
((current->insn & 0xff00)<<8) | |
((current->insn & 0xff0000)>>8) | |
((current->insn & 0xff000000)>>24)); |
|
//for(i=0;i<4;i++) tmp_insn[i] = eval_direct8 (insn_addr+i, 0, 0); |
|
// Dump it into binary log file |
fwrite((void*)&insn, 4, 1, runtime.sim.fexe_bin_insn_log); |
|
|
} /* dump_exe_bin_insn_log() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Dump registers |
|
Supports the CLI 'r' and 't' commands */ |
/*---------------------------------------------------------------------------*/ |
void |
dumpreg () |
{ |
int i; |
oraddr_t physical_pc; |
|
if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr))) |
{ |
disassemble_memory (physical_pc, physical_pc + 4, 0); |
} |
else |
{ |
PRINTF ("INTERNAL SIMULATOR ERROR:\n"); |
PRINTF ("no translation for currently executed instruction\n"); |
} |
|
// generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps); |
PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles, |
runtime.cpu.instructions); |
if (config.cpu.superscalar) |
{ |
PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles); |
} |
if (config.cpu.hazards) |
{ |
PRINTF (" HAZARDWAIT: %u\n", runtime.cpu.hazardwait); |
} |
else if (config.cpu.superscalar) |
{ |
PRINTF ("\n"); |
} |
|
if ((physical_pc = peek_into_itlb (cpu_state.pc))) |
{ |
disassemble_memory (physical_pc, physical_pc + 4, 0); |
} |
else |
{ |
PRINTF ("%" PRIxADDR ": : xxxxxxxx ITLB miss follows", cpu_state.pc); |
} |
|
PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : "")); |
|
for (i = 0; i < MAX_GPRS; i++) |
{ |
if (i % 4 == 0) |
{ |
PRINTF ("\n"); |
} |
|
PRINTF ("GPR%.2u: %" PRIxREG " ", i, evalsim_reg (i)); |
} |
|
PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0); |
|
} /* dumpreg() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Wrapper around real decode_execute function |
|
Some statistics here only |
|
@param[in] current Instruction being executed */ |
/*---------------------------------------------------------------------------*/ |
static void |
decode_execute_wrapper (struct iqueue_entry *current) |
{ |
breakpoint = 0; |
|
#ifndef HAVE_EXECUTION |
#error HAVE_EXECUTION has to be defined in order to execute programs. |
#endif |
|
/* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */ |
#if !(DYNAMIC_EXECUTION) |
decode_execute (current); |
#endif |
|
if (breakpoint) |
{ |
except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]); |
} |
} /* decode_execute_wrapper() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Reset the CPU */ |
/*---------------------------------------------------------------------------*/ |
void |
cpu_reset () |
{ |
int i; |
struct hist_exec *hist_exec_head = NULL; |
struct hist_exec *hist_exec_new; |
|
runtime.sim.cycles = 0; |
runtime.sim.loadcycles = 0; |
runtime.sim.storecycles = 0; |
runtime.cpu.instructions = 0; |
runtime.cpu.supercycles = 0; |
runtime.cpu.hazardwait = 0; |
|
for (i = 0; i < MAX_GPRS; i++) |
{ |
setsim_reg (i, 0); |
} |
|
memset (&cpu_state.iqueue, 0, sizeof (cpu_state.iqueue)); |
memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet)); |
|
sbuf_head = 0; |
sbuf_tail = 0; |
sbuf_count = 0; |
sbuf_prev_cycles = 0; |
|
/* Initialise execution history circular buffer */ |
for (i = 0; i < HISTEXEC_LEN; i++) |
{ |
hist_exec_new = malloc (sizeof (struct hist_exec)); |
|
if (!hist_exec_new) |
{ |
fprintf (stderr, "Out-of-memory\n"); |
exit (1); |
} |
|
if (!hist_exec_head) |
{ |
hist_exec_head = hist_exec_new; |
} |
else |
{ |
hist_exec_tail->next = hist_exec_new; |
} |
|
hist_exec_new->prev = hist_exec_tail; |
hist_exec_tail = hist_exec_new; |
} |
|
/* Make hist_exec_tail->next point to hist_exec_head */ |
hist_exec_tail->next = hist_exec_head; |
hist_exec_head->prev = hist_exec_tail; |
|
/* MM1409: All progs should start at reset vector entry! This sorted out by |
setting the cpu_state.pc field below. Not clear this is very good code! */ |
|
/* Patches suggested by Shinji Wakatsuki, so that the vector address takes |
notice of the Exception Prefix High bit of the Supervision register */ |
pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000); |
|
if (config.sim.verbose) |
{ |
PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext); |
} |
|
cpu_state.pc = pcnext; |
pcnext += 4; |
|
/* MM1409: All programs should set their stack pointer! */ |
#if !(DYNAMIC_EXECUTION) |
except_handle (EXCEPT_RESET, 0); |
update_pc (); |
#endif |
|
except_pending = 0; |
cpu_state.pc = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? |
0xf0000000 + EXCEPT_RESET : EXCEPT_RESET; |
|
} /* cpu_reset() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Simulates one CPU clock cycle |
|
@return non-zero if a breakpoint is hit, zero otherwise. */ |
/*---------------------------------------------------------------------------*/ |
int |
cpu_clock () |
{ |
except_pending = 0; |
next_delay_insn = 0; |
|
if (fetch ()) |
{ |
PRINTF ("Breakpoint hit.\n"); |
return 1; |
} |
|
if (except_pending) |
{ |
update_pc (); |
except_pending = 0; |
return 0; |
} |
|
if (breakpoint) |
{ |
except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]); |
update_pc (); |
except_pending = 0; |
return 0; |
} |
|
decode_execute_wrapper (&cpu_state.iqueue); |
update_pc (); |
return 0; |
|
} /* cpu_clock() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!If decoding cannot be found, call this function */ |
/*---------------------------------------------------------------------------*/ |
#if SIMPLE_EXECUTION |
void |
l_invalid (struct iqueue_entry *current) |
{ |
#else |
void |
l_invalid () |
{ |
#endif |
except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr); |
|
} /* l_invalid() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!The main execution loop */ |
/*---------------------------------------------------------------------------*/ |
void |
exec_main () |
{ |
long long time_start; |
|
while (1) |
{ |
time_start = runtime.sim.cycles; |
if (config.debug.enabled) |
{ |
while (runtime.cpu.stalled) |
{ |
if (config.debug.rsp_enabled) |
{ |
handle_rsp (); |
} |
else |
{ |
fprintf (stderr, "ERROR: CPU stalled and GDB connection not " |
"enabled: Invoking CLI and terminating.\n"); |
/* Dump the user into interactive mode. From there he or |
she can decide what to do. */ |
handle_sim_command (); |
sim_done (); |
} |
if (runtime.sim.iprompt) |
handle_sim_command (); |
} |
} |
|
/* Each cycle has counter of mem_cycles; this value is joined with cycles |
at the end of the cycle; no sim originated memory accesses should be |
performed inbetween. */ |
runtime.sim.mem_cycles = 0; |
|
if (!config.pm.enabled || |
!(config.pm.enabled & |
(cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME)))) |
{ |
if (cpu_clock ()) |
{ |
/* A breakpoint has been hit, drop to interactive mode */ |
handle_sim_command (); |
} |
} |
|
/* If we are tracing, dump after each instruction. */ |
if (!runtime.sim.hush) |
{ |
dumpreg (); |
} |
|
if (config.vapi.enabled && runtime.vapi.enabled) |
{ |
vapi_check (); |
} |
|
if (config.debug.enabled) |
{ |
if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST) |
{ |
set_stall_state (1); |
|
if (config.debug.rsp_enabled) |
{ |
rsp_exception (EXCEPT_TRAP); |
} |
} |
} |
|
runtime.sim.cycles += runtime.sim.mem_cycles; |
scheduler.job_queue->time -= runtime.sim.cycles - time_start; |
|
if (scheduler.job_queue->time <= 0) |
{ |
do_scheduler (); |
} |
} |
} /* exec_main() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Update the rounding mode variable the softfloat library reads */ |
/*---------------------------------------------------------------------------*/ |
static void |
float_set_rm () |
{ |
// |
// float_rounding_mode is used by the softfloat library, it is declared in |
// "softfloat.h" |
// |
switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM) |
{ |
case FPCSR_RM_RN: |
//printf("or1ksim <%s>: rounding mode RN\n",__FUNCTION__); |
float_rounding_mode = float_round_nearest_even; |
break; |
case FPCSR_RM_RZ: |
//printf("or1ksim <%s>: rounding mode RZ\n",__FUNCTION__); |
float_rounding_mode = float_round_to_zero; |
break; |
case FPCSR_RM_RIP: |
//printf("or1ksim <%s>: rounding mode R+\n",__FUNCTION__); |
float_rounding_mode = float_round_up; |
break; |
case FPCSR_RM_RIN: |
//printf("or1ksim <%s>: rounding mode R-\n",__FUNCTION__); |
float_rounding_mode = float_round_down; |
break; |
} |
} |
|
/*---------------------------------------------------------------------------*/ |
/*!Update the OR1K's FPCSR after each floating point instruction */ |
/*---------------------------------------------------------------------------*/ |
static void |
float_set_flags () |
{ |
// Get the flags from softfloat's variable and set the OR1K's FPCR values |
// First clear all flags in OR1K FPCSR |
cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF; |
|
if (float_exception_flags & float_flag_invalid) |
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF; |
if (float_exception_flags & float_flag_divbyzero) |
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF; |
if (float_exception_flags & float_flag_overflow) |
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF; |
if (float_exception_flags & float_flag_underflow) |
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF; |
if (float_exception_flags & float_flag_inexact) |
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF; |
/* |
printf("or1ksim: post-fp-op flags from softfloat: %x%x%x%x%x\n", |
!!(float_exception_flags & float_flag_invalid), |
!!(float_exception_flags & float_flag_divbyzero), |
!!(float_exception_flags & float_flag_overflow), |
!!(float_exception_flags & float_flag_underflow), |
!!(float_exception_flags & float_flag_inexact)); |
*/ |
// TODO: Call FP exception is FPEE set and any of the flags were set |
/* |
if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) & |
(|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF))) |
except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr); |
*/ |
// Now clear softfloat's flags: |
float_exception_flags = 0; |
|
} |
|
#if COMPLEX_EXECUTION |
|
/* Include generated/built in decode_execute function */ |
#include "execgen.c" |
|
#elif SIMPLE_EXECUTION |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Evaluates source operand |
|
Implementation specific. |
|
@param[in] op_no The operand |
@param[in] insn_index Address of the instruction |
@param[in] insn The instruction |
|
@return The value of the operand */ |
/*---------------------------------------------------------------------------*/ |
static uorreg_t |
eval_operand (int op_no, |
unsigned long insn_index, |
uint32_t insn) |
{ |
struct insn_op_struct *opd = or1ksim_op_start[insn_index]; |
uorreg_t ret; |
|
while (op_no) |
{ |
if (opd->type & OPTYPE_LAST) |
{ |
fprintf (stderr, |
"Instruction requested more operands than it has\n"); |
exit (1); |
} |
|
if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) |
{ |
op_no--; |
} |
|
opd++; |
} |
|
if (opd->type & OPTYPE_DIS) |
{ |
ret = eval_operand_val (insn, opd); |
|
while (!(opd->type & OPTYPE_OP)) |
{ |
opd++; |
} |
|
opd++; |
ret += evalsim_reg (eval_operand_val (insn, opd)); |
cpu_state.insn_ea = ret; |
|
return ret; |
} |
|
if (opd->type & OPTYPE_REG) |
{ |
return evalsim_reg (eval_operand_val (insn, opd)); |
} |
|
return eval_operand_val (insn, opd); |
|
} /* eval_operand() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Set destination operand (register direct) with value. |
|
Implementation specific. |
|
@param[in] op_no The operand |
@param[in] value The value to set |
@param[in] insn_index Address of the instruction |
@param[in] insn The instruction */ |
/*---------------------------------------------------------------------------*/ |
static void |
set_operand (int op_no, |
orreg_t value, |
unsigned long insn_index, |
uint32_t insn) |
{ |
struct insn_op_struct *opd = or1ksim_op_start[insn_index]; |
|
while (op_no) |
{ |
if (opd->type & OPTYPE_LAST) |
{ |
fprintf (stderr, |
"Instruction requested more operands than it has\n"); |
exit (1); |
} |
|
if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) |
{ |
op_no--; |
} |
|
opd++; |
} |
|
if (!(opd->type & OPTYPE_REG)) |
{ |
fprintf (stderr, "Trying to set a non-register operand\n"); |
exit (1); |
} |
|
setsim_reg (eval_operand_val (insn, opd), value); |
|
} /* set_operand() */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Simple and rather slow decoding function |
|
Based on built automata. |
|
@param[in] current The current instruction to execute */ |
/*---------------------------------------------------------------------------*/ |
static void |
decode_execute (struct iqueue_entry *current) |
{ |
int insn_index; |
|
current->insn_index = insn_index = or1ksim_insn_decode (current->insn); |
|
if (insn_index < 0) |
{ |
l_invalid (current); |
} |
else |
{ |
or1ksim_or32_opcodes[insn_index].exec (current); |
} |
|
if (do_stats) |
analysis (&cpu_state.iqueue); |
} |
|
#include "insnset.c" |
|
#elif defined(DYNAMIC_EXECUTION) |
|
#else |
# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION" |
#endif |
execute.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: Makefile.in
===================================================================
--- Makefile.in (nonexistent)
+++ Makefile.in (revision 388)
@@ -0,0 +1,818 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile -- Makefile for OR32 dependent simulation
+#
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+# Copyright (C) 2008 Embecosm Limited
+#
+# Contributor Jeremy Bennett
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@noinst_PROGRAMS = generate$(EXEEXT)
+@DYNAMIC_EXECUTION_TRUE@noinst_PROGRAMS = dyngen$(EXEEXT)
+subdir = cpu/or32
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libarch_la_LIBADD =
+am__libarch_la_SOURCES_DIST = execute.c or32.c common-i386.h \
+ dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
+ op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
+ op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
+ op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h op.c \
+ dyn-rec.c op-support.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@am_libarch_la_OBJECTS = \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ execute.lo \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.lo
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_libarch_la_OBJECTS = \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ execute.lo \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.lo
+@DYNAMIC_EXECUTION_TRUE@am_libarch_la_OBJECTS = execute.lo or32.lo \
+@DYNAMIC_EXECUTION_TRUE@ op.lo dyn-rec.lo op-support.lo
+@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_OBJECTS = gen-ops.lo \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.lo gen-ops-rel.lo
+am__dist_EXTRA_libarch_la_SOURCES_DIST = insnset.c
+libarch_la_OBJECTS = $(am_libarch_la_OBJECTS) \
+ $(nodist_libarch_la_OBJECTS)
+@DYNAMIC_EXECUTION_FALSE@am_libarch_la_rpath =
+@DYNAMIC_EXECUTION_TRUE@am_libarch_la_rpath =
+PROGRAMS = $(noinst_PROGRAMS)
+am__dyngen_SOURCES_DIST = dyngen.c dyngen-i386.c dyngen-elf.c \
+ common-i386.h dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h \
+ op-arith-op.h op-comp-op.h op-extend-op.h op-ff1-op.h \
+ op-i386.h op-lwhb-op.h op-mac-op.h op-mftspr-op.h op-support.h \
+ op-swhb-op.h op-t-reg-mov-op.h rec-i386.h sched-i386.h \
+ simpl32-defs.h
+@DYNAMIC_EXECUTION_TRUE@am_dyngen_OBJECTS = dyngen-dyngen.$(OBJEXT) \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-i386.$(OBJEXT) \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-elf.$(OBJEXT)
+dyngen_OBJECTS = $(am_dyngen_OBJECTS)
+dyngen_LDADD = $(LDADD)
+dyngen_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(dyngen_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__generate_SOURCES_DIST = or32.c generate.c common-i386.h \
+ dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
+ op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
+ op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
+ op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_generate_OBJECTS = generate-or32.$(OBJEXT) \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate-generate.$(OBJEXT)
+generate_OBJECTS = $(am_generate_OBJECTS)
+generate_LDADD = $(LDADD)
+generate_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(generate_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libarch_la_SOURCES) $(nodist_libarch_la_SOURCES) \
+ $(dist_EXTRA_libarch_la_SOURCES) $(dyngen_SOURCES) \
+ $(generate_SOURCES)
+DIST_SOURCES = $(am__libarch_la_SOURCES_DIST) \
+ $(am__dist_EXTRA_libarch_la_SOURCES_DIST) \
+ $(am__dyngen_SOURCES_DIST) $(am__generate_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_DIR = @BUILD_DIR@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPU_ARCH = @CPU_ARCH@
+CYGPATH_W = @CYGPATH_W@
+DEBUGFLAGS = @DEBUGFLAGS@
+DEFS = @DEFS@
+DEJAGNU = @DEJAGNU@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INCLUDES = @INCLUDES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
+LOCAL_DEFS = @LOCAL_DEFS@
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POW_LIB = @POW_LIB@
+RANLIB = @RANLIB@
+RUNTESTDEFAULTFLAGS = @RUNTESTDEFAULTFLAGS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUMVERSION = @SUMVERSION@
+TERMCAP_LIB = @TERMCAP_LIB@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@DYNAMIC_EXECUTION_FALSE@noinst_LTLIBRARIES = libarch.la
+@DYNAMIC_EXECUTION_TRUE@noinst_LTLIBRARIES = libarch.la
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_TRUE@ or32.c \
+@DYNAMIC_EXECUTION_TRUE@ op.c \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.c \
+@DYNAMIC_EXECUTION_TRUE@ op-support.c \
+@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_SOURCES = gen-ops.h \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@BUILT_SOURCES = execgen.c
+@DYNAMIC_EXECUTION_TRUE@BUILT_SOURCES = gen-ops.h \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
+
+@DYNAMIC_EXECUTION_TRUE@dyngen_SOURCES = dyngen.c \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-i386.c \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-elf.c \
+@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@dyngen_CFLAGS = $(AM_CFLAGS)
+@DYNAMIC_EXECUTION_TRUE@OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@EXTRA_DIST = insnset.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_SOURCES = or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_CFLAGS = $(AM_CFLAGS)
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@dist_EXTRA_libarch_la_SOURCES = insnset.c
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+CLEANFILES = execgen.c \
+ generate \
+ gen-ops.c \
+ gen-ops.h \
+ gen-ops-rel.c \
+ gen-ops-gen.c
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cpu/or32/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu cpu/or32/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libarch.la: $(libarch_la_OBJECTS) $(libarch_la_DEPENDENCIES)
+ $(LINK) $(am_libarch_la_rpath) $(libarch_la_OBJECTS) $(libarch_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+dyngen$(EXEEXT): $(dyngen_OBJECTS) $(dyngen_DEPENDENCIES)
+ @rm -f dyngen$(EXEEXT)
+ $(dyngen_LINK) $(dyngen_OBJECTS) $(dyngen_LDADD) $(LIBS)
+generate$(EXEEXT): $(generate_OBJECTS) $(generate_DEPENDENCIES)
+ @rm -f generate$(EXEEXT)
+ $(generate_LINK) $(generate_OBJECTS) $(generate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyn-rec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-elf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-i386.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-gen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-rel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-generate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-or32.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/insnset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-support.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or32.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+dyngen-dyngen.o: dyngen.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
+
+dyngen-dyngen.obj: dyngen.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
+
+dyngen-dyngen-i386.o: dyngen-i386.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
+
+dyngen-dyngen-i386.obj: dyngen-i386.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
+
+dyngen-dyngen-elf.o: dyngen-elf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
+
+dyngen-dyngen-elf.obj: dyngen-elf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
+
+generate-or32.o: or32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.o -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
+
+generate-or32.obj: or32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.obj -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
+
+generate-generate.o: generate.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.o -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
+
+generate-generate.obj: generate.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.obj -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
+
+
+@DYNAMIC_EXECUTION_TRUE@gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o
+@DYNAMIC_EXECUTION_TRUE@ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h
+
+@DYNAMIC_EXECUTION_TRUE@op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h
+@DYNAMIC_EXECUTION_TRUE@ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $<
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@execgen.c: generate$(EXEEXT) insnset.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: or32.c
===================================================================
--- or32.c (nonexistent)
+++ or32.c (revision 388)
@@ -0,0 +1,1296 @@
+/* Table of opcodes for the OpenRISC 1000 ISA.
+
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributed by Damjan Lampret (lampret@opencores.org).
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+ This file is also part of gen_or1k_isa, GDB and GAS.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+/* Autoconf and/or portability configuration */
+#include "config.h"
+#include "port.h"
+
+/* System includes */
+#include
+#include
+
+/* Package includes */
+#include "opcode/or32.h"
+
+/* We treat all letters the same in encode/decode routines so
+ we need to assign some characteristics to them like signess etc.*/
+CONST struct or32_letter or32_letters[] = {
+ {'A', NUM_UNSIGNED},
+ {'B', NUM_UNSIGNED},
+ {'D', NUM_UNSIGNED},
+ {'I', NUM_SIGNED},
+ {'K', NUM_UNSIGNED},
+ {'L', NUM_UNSIGNED},
+ {'N', NUM_SIGNED},
+ {'0', NUM_UNSIGNED},
+ {'\0', 0} /* dummy entry */
+};
+
+/* Opcode encoding:
+ machine[31:30]: first two bits of opcode
+ 00 - neither of source operands is GPR
+ 01 - second source operand is GPR (rB)
+ 10 - first source operand is GPR (rA)
+ 11 - both source operands are GPRs (rA and rB)
+ machine[29:26]: next four bits of opcode
+ machine[25:00]: instruction operands (specific to individual instruction)
+
+ Recommendation: irrelevant instruction bits should be set with a value of
+ bits in same positions of instruction preceding current instruction in the
+ code (when assembling).
+*/
+
+#ifdef HAVE_EXECUTION
+# if SIMPLE_EXECUTION
+# define EFN &l_none
+# define EF(func) &(func)
+# define EFI &l_invalid
+# elif COMPLEX_EXECUTION
+# define EFN "l_none"
+# define EFI "l_invalid"
+# ifdef __GNUC__
+# define EF(func) #func
+# else
+# define EF(func) "func"
+# endif
+# else /* DYNAMIC_EXECUTION */
+# define EFN &l_none
+# define EF(func) &(gen_ ##func)
+# define EFI &gen_l_invalid
+# endif
+#else /* HAVE_EXECUTION */
+# define EFN &l_none
+# define EF(func) EFN
+# define EFI EFN
+#endif /* HAVE_EXECUTION */
+
+CONST struct or32_opcode or1ksim_or32_opcodes[] = {
+
+ {"l.j", "N", "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NNNN",
+ EF (l_j), OR32_IF_DELAY, it_jump},
+ {"l.jal", "N", "00 0x1 NNNNN NNNNN NNNN NNNN NNNN NNNN",
+ EF (l_jal), OR32_IF_DELAY, it_jump},
+ {"l.bnf", "N", "00 0x3 NNNNN NNNNN NNNN NNNN NNNN NNNN",
+ EF (l_bnf), OR32_IF_DELAY | OR32_R_FLAG, it_branch},
+ {"l.bf", "N", "00 0x4 NNNNN NNNNN NNNN NNNN NNNN NNNN",
+ EF (l_bf), OR32_IF_DELAY | OR32_R_FLAG, it_branch},
+ {"l.nop", "K", "00 0x5 01--- ----- KKKK KKKK KKKK KKKK",
+ EF (l_nop), 0, it_nop},
+ {"l.movhi", "rD,K", "00 0x6 DDDDD ----0 KKKK KKKK KKKK KKKK",
+ EF (l_movhi), 0, it_movimm},
+ {"l.macrc", "rD", "00 0x6 DDDDD ----1 0000 0000 0000 0000",
+ EF (l_macrc), 0, it_mac},
+ {"l.sys", "K", "00 0x8 00000 00000 KKKK KKKK KKKK KKKK",
+ EF (l_sys), 0, it_exception},
+ {"l.trap", "K", "00 0x8 01000 00000 KKKK KKKK KKKK KKKK",
+ EF (l_trap), 0, it_exception},
+ {"l.msync", "", "00 0x8 10000 00000 0000 0000 0000 0000", EFN,
+ 0, it_unknown},
+ {"l.psync", "", "00 0x8 10100 00000 0000 0000 0000 0000", EFN,
+ 0, it_unknown},
+ {"l.csync", "", "00 0x8 11000 00000 0000 0000 0000 0000", EFN,
+ 0, it_unknown},
+ {"l.rfe", "", "00 0x9 ----- ----- ---- ---- ---- ----",
+ EF (l_rfe), 0, it_exception},
+ {"lv.all_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0,
+ it_unknown},
+ {"lv.all_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0,
+ it_unknown},
+ {"lv.all_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0,
+ it_unknown},
+ {"lv.all_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0,
+ it_unknown},
+ {"lv.all_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x4", EFI, 0,
+ it_unknown},
+ {"lv.all_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x5", EFI, 0,
+ it_unknown},
+ {"lv.all_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0,
+ it_unknown},
+ {"lv.all_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0,
+ it_unknown},
+ {"lv.all_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x8", EFI, 0,
+ it_unknown},
+ {"lv.all_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x9", EFI, 0,
+ it_unknown},
+ {"lv.all_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xA", EFI, 0,
+ it_unknown},
+ {"lv.all_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xB", EFI, 0,
+ it_unknown},
+ {"lv.any_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x0", EFI, 0,
+ it_unknown},
+ {"lv.any_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x1", EFI, 0,
+ it_unknown},
+ {"lv.any_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x2", EFI, 0,
+ it_unknown},
+ {"lv.any_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x3", EFI, 0,
+ it_unknown},
+ {"lv.any_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x4", EFI, 0,
+ it_unknown},
+ {"lv.any_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x5", EFI, 0,
+ it_unknown},
+ {"lv.any_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x6", EFI, 0,
+ it_unknown},
+ {"lv.any_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x7", EFI, 0,
+ it_unknown},
+ {"lv.any_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x8", EFI, 0,
+ it_unknown},
+ {"lv.any_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x9", EFI, 0,
+ it_unknown},
+ {"lv.any_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xA", EFI, 0,
+ it_unknown},
+ {"lv.any_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xB", EFI, 0,
+ it_unknown},
+ {"lv.add.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x0", EFI, 0,
+ it_unknown},
+ {"lv.add.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x1", EFI, 0,
+ it_unknown},
+ {"lv.adds.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x2", EFI, 0,
+ it_unknown},
+ {"lv.adds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x3", EFI, 0,
+ it_unknown},
+ {"lv.addu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x4", EFI, 0,
+ it_unknown},
+ {"lv.addu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x5", EFI, 0,
+ it_unknown},
+ {"lv.addus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x6", EFI, 0,
+ it_unknown},
+ {"lv.addus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x7", EFI, 0,
+ it_unknown},
+ {"lv.and", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x8", EFI, 0,
+ it_unknown},
+ {"lv.avg.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x9", EFI, 0,
+ it_unknown},
+ {"lv.avg.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0xA", EFI, 0,
+ it_unknown},
+ {"lv.cmp_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x0", EFI, 0,
+ it_unknown},
+ {"lv.cmp_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x1", EFI, 0,
+ it_unknown},
+ {"lv.cmp_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x2", EFI, 0,
+ it_unknown},
+ {"lv.cmp_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x3", EFI, 0,
+ it_unknown},
+ {"lv.cmp_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x4", EFI, 0,
+ it_unknown},
+ {"lv.cmp_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x5", EFI, 0,
+ it_unknown},
+ {"lv.cmp_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x6", EFI, 0,
+ it_unknown},
+ {"lv.cmp_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x7", EFI, 0,
+ it_unknown},
+ {"lv.cmp_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x8", EFI, 0,
+ it_unknown},
+ {"lv.cmp_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x9", EFI, 0,
+ it_unknown},
+ {"lv.cmp_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xA", EFI, 0,
+ it_unknown},
+ {"lv.cmp_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xB", EFI, 0,
+ it_unknown},
+ {"lv.madds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x4", EFI, 0,
+ it_unknown},
+ {"lv.max.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x5", EFI, 0,
+ it_unknown},
+ {"lv.max.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x6", EFI, 0,
+ it_unknown},
+ {"lv.merge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x7", EFI, 0,
+ it_unknown},
+ {"lv.merge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x8", EFI, 0,
+ it_unknown},
+ {"lv.min.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x9", EFI, 0,
+ it_unknown},
+ {"lv.min.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xA", EFI, 0,
+ it_unknown},
+ {"lv.msubs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xB", EFI, 0,
+ it_unknown},
+ {"lv.muls.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xC", EFI, 0,
+ it_unknown},
+ {"lv.nand", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xD", EFI, 0,
+ it_unknown},
+ {"lv.nor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xE", EFI, 0,
+ it_unknown},
+ {"lv.or", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xF", EFI, 0,
+ it_unknown},
+ {"lv.pack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x0", EFI, 0,
+ it_unknown},
+ {"lv.pack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x1", EFI, 0,
+ it_unknown},
+ {"lv.packs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x2", EFI, 0,
+ it_unknown},
+ {"lv.packs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x3", EFI, 0,
+ it_unknown},
+ {"lv.packus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x4", EFI, 0,
+ it_unknown},
+ {"lv.packus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x5", EFI, 0,
+ it_unknown},
+ {"lv.perm.n", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x6", EFI, 0,
+ it_unknown},
+ {"lv.rl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x7", EFI, 0,
+ it_unknown},
+ {"lv.rl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x8", EFI, 0,
+ it_unknown},
+ {"lv.sll.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x9", EFI, 0,
+ it_unknown},
+ {"lv.sll.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xA", EFI, 0,
+ it_unknown},
+ {"lv.sll", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xB", EFI, 0,
+ it_unknown},
+ {"lv.srl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xC", EFI, 0,
+ it_unknown},
+ {"lv.srl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xD", EFI, 0,
+ it_unknown},
+ {"lv.sra.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xE", EFI, 0,
+ it_unknown},
+ {"lv.sra.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xF", EFI, 0,
+ it_unknown},
+ {"lv.srl", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x0", EFI, 0,
+ it_unknown},
+ {"lv.sub.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x1", EFI, 0,
+ it_unknown},
+ {"lv.sub.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x2", EFI, 0,
+ it_unknown},
+ {"lv.subs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x3", EFI, 0,
+ it_unknown},
+ {"lv.subs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x4", EFI, 0,
+ it_unknown},
+ {"lv.subu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x5", EFI, 0,
+ it_unknown},
+ {"lv.subu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x6", EFI, 0,
+ it_unknown},
+ {"lv.subus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x7", EFI, 0,
+ it_unknown},
+ {"lv.subus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x8", EFI, 0,
+ it_unknown},
+ {"lv.unpack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x9", EFI, 0,
+ it_unknown},
+ {"lv.unpack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xA", EFI, 0,
+ it_unknown},
+ {"lv.xor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xB", EFI, 0,
+ it_unknown},
+ {"lv.cust1", "", "00 0xA ----- ----- ---- ---- 0xC ----", EFI, 0,
+ it_unknown},
+ {"lv.cust2", "", "00 0xA ----- ----- ---- ---- 0xD ----", EFI, 0,
+ it_unknown},
+ {"lv.cust3", "", "00 0xA ----- ----- ---- ---- 0xE ----", EFI, 0,
+ it_unknown},
+ {"lv.cust4", "", "00 0xA ----- ----- ---- ---- 0xF ----", EFI, 0,
+ it_unknown},
+
+ {"l.jr", "rB", "01 0x1 ----- ----- BBBB B--- ---- ----",
+ EF (l_jr), OR32_IF_DELAY, it_jump},
+ {"l.jalr", "rB", "01 0x2 ----- ----- BBBB B--- ---- ----",
+ EF (l_jalr), OR32_IF_DELAY, it_jump},
+ {"l.maci", "rA,I", "01 0x3 ----- AAAAA IIII IIII IIII IIII",
+ EF (l_mac), 0, it_mac},
+ {"l.cust1", "", "01 0xC ----- ----- ---- ---- ---- ----",
+ EF (l_cust1), 0, it_unknown},
+ {"l.cust2", "", "01 0xD ----- ----- ---- ---- ---- ----",
+ EF (l_cust2), 0, it_unknown},
+ {"l.cust3", "", "01 0xE ----- ----- ---- ---- ---- ----",
+ EF (l_cust3), 0, it_unknown},
+ {"l.cust4", "", "01 0xF ----- ----- ---- ---- ---- ----",
+ EF (l_cust4), 0, it_unknown},
+
+ {"l.ld", "rD,I(rA)", "10 0x0 DDDDD AAAAA IIII IIII IIII IIII", EFI,
+ 0, it_load},
+ {"l.lwz", "rD,I(rA)", "10 0x1 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lwz), 0, it_load},
+ {"l.lws", "rD,I(rA)", "10 0x2 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lws), 0, it_load},
+ {"l.lbz", "rD,I(rA)", "10 0x3 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lbz), 0, it_load},
+ {"l.lbs", "rD,I(rA)", "10 0x4 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lbs), 0, it_load},
+ {"l.lhz", "rD,I(rA)", "10 0x5 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lhz), 0, it_load},
+ {"l.lhs", "rD,I(rA)", "10 0x6 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_lhs), 0, it_load},
+
+ {"l.addi", "rD,rA,I", "10 0x7 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_add), OR32_W_FLAG, it_arith},
+ {"l.addic", "rD,rA,I", "10 0x8 DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_addc), OR32_W_FLAG, it_arith},
+ {"l.andi", "rD,rA,K", "10 0x9 DDDDD AAAAA KKKK KKKK KKKK KKKK",
+ EF (l_and), OR32_W_FLAG, it_arith},
+ {"l.ori", "rD,rA,K", "10 0xA DDDDD AAAAA KKKK KKKK KKKK KKKK",
+ EF (l_or), 0, it_arith},
+#if HAVE_UNSIGNED_XORI
+ {"l.xori", "rD,rA,K", "10 0xB DDDDD AAAAA KKKK KKKK KKKK KKKK",
+ EF (l_xor), 0, it_arith},
+#else
+ {"l.xori", "rD,rA,I", "10 0xB DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_xor), 0, it_arith},
+#endif
+ {"l.muli", "rD,rA,I", "10 0xC DDDDD AAAAA IIII IIII IIII IIII",
+ EF (l_mul), 0, it_arith},
+ {"l.mfspr", "rD,rA,K", "10 0xD DDDDD AAAAA KKKK KKKK KKKK KKKK",
+ EF (l_mfspr), 0, it_move},
+ {"l.slli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 00LL LLLL",
+ EF (l_sll), 0, it_shift},
+ {"l.srli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 01LL LLLL",
+ EF (l_srl), 0, it_shift},
+ {"l.srai", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 10LL LLLL",
+ EF (l_sra), 0, it_shift},
+ {"l.rori", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 11LL LLLL",
+ EF (l_ror), 0, it_shift},
+
+ {"l.sfeqi", "rA,I", "10 0xF 00000 AAAAA IIII IIII IIII IIII",
+ EF (l_sfeq), OR32_W_FLAG, it_compare},
+ {"l.sfnei", "rA,I", "10 0xF 00001 AAAAA IIII IIII IIII IIII",
+ EF (l_sfne), OR32_W_FLAG, it_compare},
+ {"l.sfgtui", "rA,I", "10 0xF 00010 AAAAA IIII IIII IIII IIII",
+ EF (l_sfgtu), OR32_W_FLAG, it_compare},
+ {"l.sfgeui", "rA,I", "10 0xF 00011 AAAAA IIII IIII IIII IIII",
+ EF (l_sfgeu), OR32_W_FLAG, it_compare},
+ {"l.sfltui", "rA,I", "10 0xF 00100 AAAAA IIII IIII IIII IIII",
+ EF (l_sfltu), OR32_W_FLAG, it_compare},
+ {"l.sfleui", "rA,I", "10 0xF 00101 AAAAA IIII IIII IIII IIII",
+ EF (l_sfleu), OR32_W_FLAG, it_compare},
+ {"l.sfgtsi", "rA,I", "10 0xF 01010 AAAAA IIII IIII IIII IIII",
+ EF (l_sfgts), OR32_W_FLAG, it_compare},
+ {"l.sfgesi", "rA,I", "10 0xF 01011 AAAAA IIII IIII IIII IIII",
+ EF (l_sfges), OR32_W_FLAG, it_compare},
+ {"l.sfltsi", "rA,I", "10 0xF 01100 AAAAA IIII IIII IIII IIII",
+ EF (l_sflts), OR32_W_FLAG, it_compare},
+ {"l.sflesi", "rA,I", "10 0xF 01101 AAAAA IIII IIII IIII IIII",
+ EF (l_sfles), OR32_W_FLAG, it_compare},
+
+ {"l.mtspr", "rA,rB,K", "11 0x0 KKKKK AAAAA BBBB BKKK KKKK KKKK",
+ EF (l_mtspr), 0, it_move},
+ {"l.mac", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x1",
+ EF (l_mac), 0, it_mac},
+ {"l.msb", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x2",
+ EF (l_msb), 0, it_mac},
+
+ {"lf.add.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x0",
+ EF (lf_add_s), 0, it_float},
+ {"lf.sub.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x1",
+ EF (lf_sub_s), 0, it_float},
+ {"lf.mul.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x2",
+ EF (lf_mul_s), 0, it_float},
+ {"lf.div.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x3",
+ EF (lf_div_s), 0, it_float},
+ {"lf.itof.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x4",
+ EF (lf_itof_s), 0, it_float},
+ {"lf.ftoi.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x5",
+ EF (lf_ftoi_s), 0, it_float},
+ {"lf.rem.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x6",
+ EF (lf_rem_s), 0, it_float},
+ {"lf.madd.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x7",
+ EF (lf_madd_s), 0, it_float},
+ {"lf.sfeq.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x8",
+ EF (lf_sfeq_s), 0, it_float},
+ {"lf.sfne.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x9",
+ EF (lf_sfne_s), 0, it_float},
+ {"lf.sfgt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xA",
+ EF (lf_sfgt_s), 0, it_float},
+ {"lf.sfge.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xB",
+ EF (lf_sfge_s), 0, it_float},
+ {"lf.sflt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xC",
+ EF (lf_sflt_s), 0, it_float},
+ {"lf.sfle.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xD",
+ EF (lf_sfle_s), 0, it_float},
+ {"lf.cust1.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xD ----", EFI,
+ 0, it_float},
+
+ {"lf.add.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0,
+ it_float},
+ {"lf.sub.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0,
+ it_float},
+ {"lf.mul.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0,
+ it_float},
+ {"lf.div.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0,
+ it_float},
+ {"lf.itof.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x4", EFI, 0,
+ it_float},
+ {"lf.ftoi.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x5", EFI, 0,
+ it_float},
+ {"lf.rem.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0,
+ it_float},
+ {"lf.madd.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0,
+ it_float},
+ {"lf.sfeq.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x8", EFI, 0,
+ it_float},
+ {"lf.sfne.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x9", EFI, 0,
+ it_float},
+ {"lf.sfgt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xA", EFI, 0,
+ it_float},
+ {"lf.sfge.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xB", EFI, 0,
+ it_float},
+ {"lf.sflt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xC", EFI, 0,
+ it_float},
+ {"lf.sfle.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xD", EFI, 0,
+ it_float},
+ {"lf.cust1.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xE ----", EFI, 0,
+ it_float},
+
+ {"l.sd", "I(rA),rB", "11 0x4 IIIII AAAAA BBBB BIII IIII IIII", EFI,
+ 0, it_store},
+ {"l.sw", "I(rA),rB", "11 0x5 IIIII AAAAA BBBB BIII IIII IIII",
+ EF (l_sw), 0, it_store},
+ {"l.sb", "I(rA),rB", "11 0x6 IIIII AAAAA BBBB BIII IIII IIII",
+ EF (l_sb), 0, it_store},
+ {"l.sh", "I(rA),rB", "11 0x7 IIIII AAAAA BBBB BIII IIII IIII",
+ EF (l_sh), 0, it_store},
+
+ {"l.add", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x0",
+ EF (l_add), OR32_W_FLAG, it_arith},
+ {"l.addc", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x1",
+ EF (l_addc), OR32_W_FLAG, it_arith},
+ {"l.sub", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x2",
+ EF (l_sub), 0, it_arith},
+ {"l.and", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x3",
+ EF (l_and), OR32_W_FLAG, it_arith},
+ {"l.or", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x4",
+ EF (l_or), 0, it_arith},
+ {"l.xor", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x5",
+ EF (l_xor), 0, it_arith},
+ {"l.mul", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x6",
+ EF (l_mul), 0, it_arith},
+
+ {"l.sll", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 00-- 0x8",
+ EF (l_sll), 0, it_shift},
+ {"l.srl", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 01-- 0x8",
+ EF (l_srl), 0, it_shift},
+ {"l.sra", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 10-- 0x8",
+ EF (l_sra), 0, it_shift},
+ {"l.ror", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 11-- 0x8",
+ EF (l_ror), 0, it_shift},
+ {"l.div", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x9",
+ EF (l_div), 0, it_arith},
+ {"l.divu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xA",
+ EF (l_divu), 0, it_arith},
+ {"l.mulu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xB",
+ EF (l_mulu), 0, it_arith},
+ {"l.extbs", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xC",
+ EF (l_extbs), 0, it_move},
+ {"l.exths", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xC",
+ EF (l_exths), 0, it_move},
+ {"l.extws", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xD",
+ EF (l_extws), 0, it_move},
+ {"l.extbz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 11-- 0xC",
+ EF (l_extbz), 0, it_move},
+ {"l.exthz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 10-- 0xC",
+ EF (l_exthz), 0, it_move},
+ {"l.extwz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xD",
+ EF (l_extwz), 0, it_move},
+ {"l.cmov", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0xE",
+ EF (l_cmov), OR32_R_FLAG, it_move},
+ {"l.ff1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 ---- 0xF",
+ EF (l_ff1), 0, it_arith},
+ {"l.fl1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --01 ---- 0xF",
+ EF (l_fl1), 0, it_arith},
+
+ {"l.sfeq", "rA,rB", "11 0x9 00000 AAAAA BBBB B--- ---- ----",
+ EF (l_sfeq), OR32_W_FLAG, it_compare},
+ {"l.sfne", "rA,rB", "11 0x9 00001 AAAAA BBBB B--- ---- ----",
+ EF (l_sfne), OR32_W_FLAG, it_compare},
+ {"l.sfgtu", "rA,rB", "11 0x9 00010 AAAAA BBBB B--- ---- ----",
+ EF (l_sfgtu), OR32_W_FLAG, it_compare},
+ {"l.sfgeu", "rA,rB", "11 0x9 00011 AAAAA BBBB B--- ---- ----",
+ EF (l_sfgeu), OR32_W_FLAG, it_compare},
+ {"l.sfltu", "rA,rB", "11 0x9 00100 AAAAA BBBB B--- ---- ----",
+ EF (l_sfltu), OR32_W_FLAG, it_compare},
+ {"l.sfleu", "rA,rB", "11 0x9 00101 AAAAA BBBB B--- ---- ----",
+ EF (l_sfleu), OR32_W_FLAG, it_compare},
+ {"l.sfgts", "rA,rB", "11 0x9 01010 AAAAA BBBB B--- ---- ----",
+ EF (l_sfgts), OR32_W_FLAG, it_compare},
+ {"l.sfges", "rA,rB", "11 0x9 01011 AAAAA BBBB B--- ---- ----",
+ EF (l_sfges), OR32_W_FLAG, it_compare},
+ {"l.sflts", "rA,rB", "11 0x9 01100 AAAAA BBBB B--- ---- ----",
+ EF (l_sflts), OR32_W_FLAG, it_compare},
+ {"l.sfles", "rA,rB", "11 0x9 01101 AAAAA BBBB B--- ---- ----",
+ EF (l_sfles), OR32_W_FLAG, it_compare},
+
+ {"l.cust5", "rD,rA,rB,L,K", "11 0xC DDDDD AAAAA BBBB BLLL LLLK KKKK", EFI,
+ 0, it_unknown},
+ {"l.cust6", "", "11 0xD ----- ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust7", "", "11 0xE ----- ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust8", "", "11 0xF ----- ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+
+/* This section should not be defined in or1ksim, since it contains duplicates,
+ which would cause machine builder to complain. */
+#ifdef HAS_CUST
+ {"l.cust5_1", "rD", "11 0xC DDDDD ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust5_2", "rD,rA", "11 0xC DDDDD AAAAA ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust5_3", "rD,rA,rB", "11 0xC DDDDD AAAAA BBBB B--- ---- ----", EFI,
+ 0, it_unknown},
+
+ {"l.cust6_1", "rD", "11 0xD DDDDD ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust6_2", "rD,rA", "11 0xD DDDDD AAAAA ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust6_3", "rD,rA,rB", "11 0xD DDDDD AAAAA BBBB B--- ---- ----", EFI,
+ 0, it_unknown},
+
+ {"l.cust7_1", "rD", "11 0xE DDDDD ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust7_2", "rD,rA", "11 0xE DDDDD AAAAA ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust7_3", "rD,rA,rB", "11 0xE DDDDD AAAAA BBBB B--- ---- ----", EFI,
+ 0, it_unknown},
+
+ {"l.cust8_1", "rD", "11 0xF DDDDD ----- ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust8_2", "rD,rA", "11 0xF DDDDD AAAAA ---- ---- ---- ----", EFI,
+ 0, it_unknown},
+ {"l.cust8_3", "rD,rA,rB", "11 0xF DDDDD AAAAA BBBB B--- ---- ----", EFI,
+ 0, it_unknown},
+#endif
+
+ {"", "", "", EFI, 0, 0} /* Dummy entry, not included in num_opcodes. This
+ * lets code examine entry i+1 without checking
+ * if we've run off the end of the table. */
+};
+
+#undef EFI
+#undef EFN
+#undef EF
+
+static CONST int NUM_OPCODES =
+ ((sizeof (or1ksim_or32_opcodes)) / (sizeof (struct or32_opcode))) - 1;
+
+/* Calculates instruction length in bytes. Always 4 for OR32. */
+int
+or1ksim_insn_len (int insn_index)
+{
+ insn_index = 0; /* Just to get rid that warning. */
+ return 4;
+}
+
+/* Is individual insn's operand signed or unsigned? */
+static int
+letter_signed (char l)
+{
+ CONST struct or32_letter *pletter;
+
+ for (pletter = or32_letters; pletter->letter != '\0'; pletter++)
+ if (pletter->letter == l)
+ return pletter->sign;
+
+ printf ("letter_signed(%c): Unknown letter.\n", l);
+ return 0;
+}
+
+/* Simple cache for letter ranges */
+static int range_cache[256] = { 0 };
+
+/* Number of letters in the individual lettered operand. */
+static int
+letter_range (char l)
+{
+ CONST struct or32_opcode *pinsn;
+ char *enc;
+ int range = 0;
+
+ /* Is value cached? */
+ if ((range = range_cache[(unsigned char) l]))
+ return range;
+
+ for (pinsn = or1ksim_or32_opcodes; strlen (pinsn->name); pinsn++)
+ {
+ if (strchr (pinsn->encoding, l))
+ {
+ for (enc = pinsn->encoding; *enc != '\0'; enc++)
+ if ((*enc == '0') && (*(enc + 1) == 'x'))
+ enc += 2;
+ else if (*enc == l)
+ range++;
+ return range_cache[(unsigned char) l] = range;
+ }
+ }
+
+ printf ("\nABORT: letter_range(%c): Never used letter.\n", l);
+ exit (1);
+}
+
+/* Returns name of the specified instruction index */
+CONST char *
+or1ksim_insn_name (int index)
+{
+ if (index >= 0 && index < NUM_OPCODES)
+ return or1ksim_or32_opcodes[index].name;
+ else
+ return "???";
+}
+
+/*** Finite automata for instruction decoding building code ***/
+
+/* Find symbols in encoding. */
+static unsigned long
+insn_extract (param_ch, enc_initial)
+ char param_ch;
+ char *enc_initial;
+{
+ char *enc;
+ unsigned long ret = 0;
+ unsigned opc_pos = 32;
+ for (enc = enc_initial; *enc != '\0';)
+ if ((*enc == '0') && (*(enc + 1) == 'x'))
+ {
+ unsigned long tmp = strtol (enc + 2, NULL, 16);
+ opc_pos -= 4;
+ if (param_ch == '0' || param_ch == '1')
+ {
+ if (param_ch == '0')
+ tmp = 15 - tmp;
+ ret |= tmp << opc_pos;
+ }
+ enc += 3;
+ }
+ else
+ {
+ if (*enc == '0' || *enc == '1' || *enc == '-' || isalpha ((int)*enc))
+ {
+ opc_pos--;
+ if (param_ch == *enc)
+ ret |= 1 << opc_pos;
+ }
+ enc++;
+ }
+ return ret;
+}
+
+#define MAX_AUTOMATA_SIZE (1200)
+#define MAX_OP_TABLE_SIZE (1200)
+#define MAX_LEN (8)
+
+#ifndef MIN
+# define MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+unsigned long *or1ksim_automata;
+int nuncovered;
+int curpass = 0;
+
+/* MM: Struct that holds runtime build information about instructions. */
+struct temp_insn_struct *or1ksim_ti;
+
+static struct insn_op_struct *op_data;
+
+struct insn_op_struct **or1ksim_op_start;
+
+static void
+or32_debug (int level, const char *format, ...)
+{
+#if DEBUG
+ char *p;
+ va_list ap;
+
+ if ((p = malloc (1000)) == NULL)
+ return;
+ va_start (ap, format);
+ (void) vsnprintf (p, 1000, format, ap);
+ va_end (ap);
+ printf ("%s\n", p);
+ fflush (stdout);
+ free (p);
+#endif
+}
+
+/* Recursive utility function used to find best match and to build automata. */
+static unsigned long *
+cover_insn (unsigned long *cur, int pass, unsigned int mask)
+{
+ int best_first = 0, best_len = 0, i, last_match = -1, ninstr = 0;
+ unsigned long cur_mask = mask;
+ unsigned long *next;
+
+ for (i = 0; i < NUM_OPCODES; i++)
+ if (or1ksim_ti[i].in_pass == pass)
+ {
+ cur_mask &= or1ksim_ti[i].insn_mask;
+ ninstr++;
+ last_match = i;
+ }
+
+ or32_debug (8, "%08X %08lX\n", mask, cur_mask);
+ if (ninstr == 0)
+ return 0;
+ if (ninstr == 1)
+ {
+ /* Leaf holds instruction index. */
+ or32_debug (8, "%i>I%i %s\n", cur - or1ksim_automata, last_match,
+ or1ksim_or32_opcodes[last_match].name);
+ *cur = LEAF_FLAG | last_match;
+ cur++;
+ nuncovered--;
+ }
+ else
+ {
+ /* Find longest match. */
+ for (i = 0; i < 32; i++)
+ {
+ int len;
+ for (len = best_len + 1; len < MIN (MAX_LEN, 33 - i); len++)
+ {
+ unsigned long m = (1UL << ((unsigned long) len)) - 1;
+ or32_debug (9, " (%i(%08lX & %08lX>>%i = %08lX, %08lX)", len, m,
+ cur_mask, i, (cur_mask >> (unsigned) i),
+ (cur_mask >> (unsigned) i) & m);
+ if ((m & (cur_mask >> (unsigned) i)) == m)
+ {
+ best_len = len;
+ best_first = i;
+ or32_debug (9, "!");
+ }
+ else
+ break;
+ }
+ }
+ or32_debug (9, "\n");
+ if (!best_len)
+ {
+ fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr,
+ mask);
+ for (i = 0; i < NUM_OPCODES; i++)
+ if (or1ksim_ti[i].in_pass == pass)
+ fprintf (stderr, "%s ", or1ksim_or32_opcodes[i].name);
+
+ fprintf (stderr, "\n");
+ exit (1);
+ }
+ or32_debug (8, "%i> #### %i << %i (%i) ####\n", cur - or1ksim_automata, best_len,
+ best_first, ninstr);
+ *cur = best_first;
+ cur++;
+ *cur = (1 << best_len) - 1;
+ cur++;
+ next = cur;
+ /* Allocate space for pointers. */
+ cur += 1 << best_len;
+ cur_mask = (1 << (unsigned long) best_len) - 1;
+
+ for (i = 0; i < (1 << (unsigned long) best_len); i++)
+ {
+ int j;
+ unsigned long *c;
+ curpass++;
+ for (j = 0; j < NUM_OPCODES; j++)
+ if (or1ksim_ti[j].in_pass == pass
+ && ((or1ksim_ti[j].insn >> best_first) & cur_mask) ==
+ (unsigned long) i
+ && ((or1ksim_ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
+ or1ksim_ti[j].in_pass = curpass;
+
+ or32_debug (9, "%08X %08lX %i\n", mask, cur_mask, best_first);
+ c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
+ if (c)
+ {
+ or32_debug (8, "%i> #%X -> %u\n", next - or1ksim_automata, i,
+ cur - or1ksim_automata);
+ *next = cur - or1ksim_automata;
+ cur = c;
+ }
+ else
+ {
+ or32_debug (8, "%i> N/A\n", next - or1ksim_automata);
+ *next = 0;
+ }
+ next++;
+ }
+ }
+ return cur;
+}
+
+/* Returns number of nonzero bits. */
+static int
+num_ones (unsigned long value)
+{
+ int c = 0;
+ while (value)
+ {
+ if (value & 1)
+ c++;
+ value >>= 1;
+ }
+ return c;
+}
+
+/* Utility function, which converts parameters from or32_opcode format to more binary form.
+ Parameters are stored in or1ksim_ti struct. */
+
+static struct insn_op_struct *
+parse_params (CONST struct or32_opcode *opcode, struct insn_op_struct *cur)
+{
+ char *args = opcode->args;
+ int i, type;
+ int num_cur_op = 0;;
+
+ i = 0;
+ type = 0;
+ /* In case we don't have any parameters, we add dummy read from r0. */
+ if (!(*args))
+ {
+ cur->type = OPTYPE_REG | OPTYPE_OP | OPTYPE_LAST;
+ cur->data = 0;
+ or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data);
+ cur++;
+ return cur;
+ }
+
+ while (*args != '\0')
+ {
+ if (*args == 'r')
+ {
+ args++;
+ type |= OPTYPE_REG;
+ if (*args == 'D')
+ type |= OPTYPE_DST;
+ }
+ else if (isalpha ((int)*args))
+ {
+ unsigned long arg;
+ arg = insn_extract (*args, opcode->encoding);
+ or32_debug (9, "%s : %08lX ------\n", opcode->name, arg);
+ if (letter_signed (*args))
+ {
+ type |= OPTYPE_SIG;
+ type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT;
+ }
+
+ num_cur_op = 0;
+ /* Split argument to sequences of consecutive ones. */
+ while (arg)
+ {
+ int shr = 0;
+ unsigned long tmp = arg, mask = 0;
+ while ((tmp & 1) == 0)
+ {
+ shr++;
+ tmp >>= 1;
+ }
+ while (tmp & 1)
+ {
+ mask++;
+ tmp >>= 1;
+ }
+ cur->type = type | shr;
+ cur->data = mask;
+ arg &= ~(((1 << mask) - 1) << shr);
+ or32_debug (6, "|%08lX %08lX\n", cur->type, cur->data);
+ cur++;
+ num_cur_op++;
+ }
+ args++;
+ }
+ else if (*args == '(')
+ {
+ /* Next param is displacement. Later we will treat them as one operand. */
+ /* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this
+ * operand */
+ while (num_cur_op > 0)
+ {
+ cur[-num_cur_op].type |= type | OPTYPE_DIS;
+ num_cur_op--;
+ }
+ cur[-1].type |= OPTYPE_OP;
+ or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
+ type = 0;
+ i++;
+ args++;
+ }
+ else if (*args == OPERAND_DELIM)
+ {
+ cur--;
+ cur->type = type | cur->type | OPTYPE_OP;
+ or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
+ cur++;
+ type = 0;
+ i++;
+ args++;
+ }
+ else if (*args == '0')
+ {
+ cur->type = type;
+ cur->data = 0;
+ or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
+ cur++;
+ type = 0;
+ i++;
+ args++;
+ }
+ else if (*args == ')')
+ args++;
+ else
+ {
+ fprintf (stderr, "%s : parse error in args.\n", opcode->name);
+ exit (1);
+ }
+ }
+ cur--;
+ cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST;
+ or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data);
+ cur++;
+ return cur;
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Constructs new automata based on or1ksim_or32_opcodes array.
+
+ @param[in] quiet If non-zero (TRUE) do not print informational messages. */
+/* -------------------------------------------------------------------------- */
+void
+or1ksim_build_automata (int quiet)
+{
+ int i;
+ unsigned long *end;
+ struct insn_op_struct *cur;
+
+ or1ksim_automata =
+ (unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
+ or1ksim_ti =
+ (struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) *
+ NUM_OPCODES);
+
+ nuncovered = NUM_OPCODES;
+
+#ifdef HAVE_EXECUTION
+ if (!quiet)
+ {
+ printf ("Building automata... ");
+ }
+#endif
+
+ /* Build temporary information about instructions. */
+ for (i = 0; i < NUM_OPCODES; i++)
+ {
+ unsigned long ones, zeros;
+ char *encoding = or1ksim_or32_opcodes[i].encoding;
+ ones = insn_extract ('1', encoding);
+ zeros = insn_extract ('0', encoding);
+ or1ksim_ti[i].insn_mask = ones | zeros;
+ or1ksim_ti[i].insn = ones;
+ or1ksim_ti[i].in_pass = curpass = 0;
+ /*debug(9, "%s: %s %08X %08X\n", or1ksim_or32_opcodes[i].name,
+ or1ksim_or32_opcodes[i].encoding, or1ksim_ti[i].insn_mask, or1ksim_ti[i].insn); */
+ }
+
+ /* Until all are covered search for best criteria to separate them. */
+ end = cover_insn (or1ksim_automata, curpass, 0xFFFFFFFF);
+ if (end - or1ksim_automata > MAX_AUTOMATA_SIZE)
+ {
+ fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
+ exit (1);
+ }
+#ifdef HAVE_EXECUTION
+ if (!quiet)
+ {
+ printf ("done, num uncovered: %i/%i.\n", nuncovered, NUM_OPCODES);
+ }
+#endif
+
+#ifdef HAVE_EXECUTION
+ if (!quiet)
+ {
+ printf ("Parsing operands data... ");
+ }
+#endif
+ op_data =
+ (struct insn_op_struct *) malloc (MAX_OP_TABLE_SIZE *
+ sizeof (struct insn_op_struct));
+ or1ksim_op_start =
+ (struct insn_op_struct **) malloc (NUM_OPCODES *
+ sizeof (struct insn_op_struct *));
+ cur = op_data;
+ for (i = 0; i < NUM_OPCODES; i++)
+ {
+ or1ksim_op_start[i] = cur;
+ cur = parse_params (&or1ksim_or32_opcodes[i], cur);
+ if (cur - op_data > MAX_OP_TABLE_SIZE)
+ {
+ fprintf (stderr,
+ "Operands table too small, increase MAX_OP_TABLE_SIZE.\n");
+ exit (1);
+ }
+ }
+#ifdef HAVE_EXECUTION
+ if (!quiet)
+ {
+ printf ("done.\n");
+ }
+#endif
+}
+
+void
+or1ksim_destruct_automata ()
+{
+ free (or1ksim_ti);
+ free (or1ksim_automata);
+ free (op_data);
+ free (or1ksim_op_start);
+}
+
+/* Decodes instruction and returns instruction index. */
+int
+or1ksim_insn_decode (unsigned int insn)
+{
+ unsigned long *a = or1ksim_automata;
+ int i;
+ while (!(*a & LEAF_FLAG))
+ {
+ unsigned int first = *a;
+ //debug(9, "%i ", a - or1ksim_automata);
+ a++;
+ i = (insn >> first) & *a;
+ a++;
+ if (!*(a + i))
+ { /* Invalid instruction found? */
+ //debug(9, "XXX\n", i);
+ return -1;
+ }
+ a = or1ksim_automata + *(a + i);
+ }
+ i = *a & ~LEAF_FLAG;
+ //debug(9, "%i\n", i);
+ /* Final check - do we have direct match?
+ (based on or1ksim_or32_opcodes this should be the only possibility,
+ but in case of invalid/missing instruction we must perform a check) */
+ if ((or1ksim_ti[i].insn_mask & insn) == or1ksim_ti[i].insn)
+ return i;
+ else
+ return -1;
+}
+
+static char disassembled_str[50];
+char *or1ksim_disassembled = &disassembled_str[0];
+
+/* Automagically does zero- or sign- extension and also finds correct
+ sign bit position if sign extension is correct extension. Which extension
+ is proper is figured out from letter description. */
+
+unsigned long
+or1ksim_extend_imm (unsigned long imm, char l)
+{
+ unsigned long mask;
+ int letter_bits;
+
+ /* First truncate all bits above valid range for this letter
+ in case it is zero extend. */
+ letter_bits = letter_range (l);
+ mask = (1 << letter_bits) - 1;
+ imm &= mask;
+
+ /* Do sign extend if this is the right one. */
+ if (letter_signed (l) && (imm >> (letter_bits - 1)))
+ imm |= (~mask);
+
+ return imm;
+}
+
+unsigned long
+or1ksim_or32_extract (param_ch, enc_initial, insn)
+ char param_ch;
+ char *enc_initial;
+ unsigned long insn;
+{
+ char *enc;
+ unsigned long ret = 0;
+ int opc_pos = 0;
+ int param_pos = 0;
+
+ for (enc = enc_initial; *enc != '\0'; enc++)
+ if (*enc == param_ch)
+ {
+ if (enc - 2 >= enc_initial && (*(enc - 2) == '0')
+ && (*(enc - 1) == 'x'))
+ continue;
+ else
+ param_pos++;
+ }
+
+#if DEBUG
+ printf ("or1ksim_or32_extract: %x ", param_pos);
+#endif
+ opc_pos = 32;
+ for (enc = enc_initial; *enc != '\0';)
+ if ((*enc == '0') && (*(enc + 1) == 'x'))
+ {
+ opc_pos -= 4;
+ if ((param_ch == '0') || (param_ch == '1'))
+ {
+ unsigned long tmp = strtol (enc, NULL, 16);
+#if DEBUG
+ printf (" enc=%s, tmp=%x ", enc, tmp);
+#endif
+ if (param_ch == '0')
+ tmp = 15 - tmp;
+ ret |= tmp << opc_pos;
+ }
+ enc += 3;
+ }
+ else if ((*enc == '0') || (*enc == '1'))
+ {
+ opc_pos--;
+ if (param_ch == *enc)
+ ret |= 1 << opc_pos;
+ enc++;
+ }
+ else if (*enc == param_ch)
+ {
+ opc_pos--;
+ param_pos--;
+#if DEBUG
+ printf ("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos,
+ param_pos);
+#endif
+ if (islower ((int) param_ch))
+ ret -= ((insn >> opc_pos) & 0x1) << param_pos;
+ else
+ ret += ((insn >> opc_pos) & 0x1) << param_pos;
+ enc++;
+ }
+ else if (isalpha ((int)*enc))
+ {
+ opc_pos--;
+ enc++;
+ }
+ else if (*enc == '-')
+ {
+ opc_pos--;
+ enc++;
+ }
+ else
+ enc++;
+
+#if DEBUG
+ printf ("ret=%x\n", ret);
+#endif
+ return ret;
+}
+
+/* Print register. Used only by print_insn. */
+
+static char *
+or32_print_register (dest, param_ch, encoding, insn)
+ char *dest;
+ char param_ch;
+ char *encoding;
+ unsigned long insn;
+{
+ int regnum = or1ksim_or32_extract (param_ch, encoding, insn);
+
+ sprintf (dest, "r%d", regnum);
+ while (*dest)
+ dest++;
+ return dest;
+}
+
+/* Print immediate. Used only by print_insn. */
+
+static char *
+or32_print_immediate (dest, param_ch, encoding, insn)
+ char *dest;
+ char param_ch;
+ char *encoding;
+ unsigned long insn;
+{
+ int imm = or1ksim_or32_extract (param_ch, encoding, insn);
+
+ imm = or1ksim_extend_imm (imm, param_ch);
+
+ if (letter_signed (param_ch))
+ {
+ if (imm < 0)
+ sprintf (dest, "%d", imm);
+ else
+ sprintf (dest, "0x%x", imm);
+ }
+ else
+ sprintf (dest, "%#x", imm);
+ while (*dest)
+ dest++;
+ return dest;
+}
+
+/* Disassemble one instruction from insn to disassemble.
+ Return the size of the instruction. */
+
+int
+or1ksim_disassemble_insn (insn)
+ unsigned long insn;
+{
+ return or1ksim_disassemble_index (insn, or1ksim_insn_decode (insn));
+}
+
+/* Disassemble one instruction from insn index.
+ Return the size of the instruction. */
+
+int
+or1ksim_disassemble_index (insn, index)
+ unsigned long insn;
+ int index;
+{
+ char *dest = or1ksim_disassembled;
+ if (index >= 0)
+ {
+ struct or32_opcode const *opcode = &or1ksim_or32_opcodes[index];
+ char *s;
+
+ strcpy (dest, opcode->name);
+ while (*dest)
+ dest++;
+ *dest++ = ' ';
+ *dest = 0;
+
+ for (s = opcode->args; *s != '\0'; ++s)
+ {
+ switch (*s)
+ {
+ case '\0':
+ return or1ksim_insn_len (insn);
+
+ case 'r':
+ dest = or32_print_register (dest, *++s, opcode->encoding, insn);
+ break;
+
+ default:
+ if (strchr (opcode->encoding, *s))
+ dest =
+ or32_print_immediate (dest, *s, opcode->encoding, insn);
+ else
+ {
+ *dest++ = *s;
+ *dest = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* This used to be %8x for binutils. */
+ sprintf (dest, ".word 0x%08lx", insn);
+ while (*dest)
+ dest++;
+ }
+ return or1ksim_insn_len (insn);
+}
or32.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: generate.c
===================================================================
--- generate.c (nonexistent)
+++ generate.c (revision 388)
@@ -0,0 +1,474 @@
+/* generate.c -- generates file execgen.c from instruction set
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+/* Autoconf and/or portability configuration */
+#include "config.h"
+#include "port.h"
+
+/* System includes */
+#include
+#include
+#include
+
+/* Package includes */
+#include "opcode/or32.h"
+
+static char *in_file;
+static char *out_file;
+
+/* Whether this instruction stores something in register */
+static int write_to_reg;
+
+static int out_lines = 0;
+
+static int shift_fprintf(int level, FILE *f, const char *fmt, ...)
+{
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ for(i = 0; i < level; i++)
+ fprintf(f, " ");
+
+ i = vfprintf(f, fmt, ap);
+ va_end(ap);
+
+ out_lines++;
+ return i + (level * 2);
+}
+
+/* Generates a execute sequence for one instruction */
+int output_function (FILE *fo, const char *func_name, int level)
+{
+ FILE *fi;
+ int olevel;
+ int line_num = 0;
+
+ if ((fi = fopen (in_file, "rt")) == NULL) {
+ printf("could not open file\n");
+ return 1;
+ }
+
+ while (!feof (fi)) {
+ char line[10000], *str = line;
+ char *res;
+
+ res = fgets (str, sizeof (line), fi);
+
+ if (NULL == res)
+ {
+ fclose (fi); /* Mark Jarvin patch */
+ return 1;
+ }
+
+ line[sizeof (line) - 1] = 0;
+ line_num++;
+ if (strncmp (str, "INSTRUCTION (", 13) == 0) {
+ char *s;
+ str += 13;
+ while (isspace ((int)*str)) str++;
+ s = str;
+ while (*s && *s != ')') s++;
+ *s = 0;
+ while (isspace((int)*(s - 1))) s--;
+ *s = 0;
+ if (strcmp (str, func_name) == 0) {
+ olevel = 1;
+ str += strlen (str) + 1;
+ while (isspace ((int)*str)) str++;
+ s = str;
+ while (*s && *s != '\n' && *s != '\r') s++;
+ *s = 0;
+ while (isspace((int)*(s - 1))) s--;
+ *s = 0;
+ /*shift_fprintf (level, fo, "#line %i \"%s\"\n", line_num, in_file);*/
+ shift_fprintf (level, fo, "%s", str);
+ shift_fprintf (level, fo, " /* \"%s\" */\n", func_name);
+ do {
+ res = fgets (line, sizeof (line), fi);
+
+ if (NULL == res)
+ {
+ fclose (fi);
+ return 1;
+ }
+
+ line[sizeof(line) - 1] = 0;
+ for (str = line; *str; str++) {
+ if (*str == '{') olevel++;
+ else if (*str == '}') olevel--;
+ }
+ shift_fprintf (level, fo, "%s", line);
+ } while (olevel);
+ fclose(fi);
+ /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/
+ return 0;
+ }
+ }
+ }
+ shift_fprintf (level, fo, "%s ();\n", func_name);
+
+ fclose(fi);
+ return 0;
+}
+
+/* Parses operands. */
+
+static int
+gen_eval_operands (FILE *fo, int insn_index, int level)
+{
+ struct insn_op_struct *opd = or1ksim_op_start[insn_index];
+ int i;
+ int num_ops;
+ int nbits = 0;
+ int set_param = 0;
+ int dis = 0;
+ int sbit;
+ int dis_op = -1;
+
+ write_to_reg = 0;
+
+ shift_fprintf (level, fo, "uorreg_t ");
+
+ /* Count number of operands */
+ for (i = 0, num_ops = 0;; i++) {
+ if (!(opd[i].type & OPTYPE_OP))
+ continue;
+ if (opd[i].type & OPTYPE_DIS)
+ continue;
+ if (num_ops)
+ fprintf(fo, ", ");
+ fprintf(fo, "%c", 'a' + num_ops);
+ num_ops++;
+ if (opd[i].type & OPTYPE_LAST)
+ break;
+ }
+
+ fprintf (fo, ";\n");
+
+ shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops);
+
+ i = 0;
+ num_ops = 0;
+ do {
+/*
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0'); printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0');
+ printf("opd[%i].type = %i\n", i, opd->type & OPTYPE_SHR);
+ printf("opd[%i].type = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR);
+ printf("opd[%i].data = %i\n", i, opd->data);
+*/
+
+ if (!nbits)
+ shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops,
+ opd->type & OPTYPE_SHR, (1 << opd->data) - 1);
+ else
+ shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n",
+ 'a' + num_ops, opd->type & OPTYPE_SHR,
+ (1 << opd->data) - 1, nbits);
+
+ nbits += opd->data;
+
+ if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) {
+ sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+ if (opd->type & OPTYPE_SIG)
+ shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
+ 'a' + num_ops, 1 << sbit, 'a' + num_ops,
+ 0xffffffff << sbit);
+ opd++;
+ shift_fprintf (level, fo, "*(orreg_t *)&%c += (orreg_t)cpu_state.reg[(insn >> %i) & 0x%x];\n",
+ 'a' + num_ops, opd->type & OPTYPE_SHR,
+ (1 << opd->data) - 1);
+ dis = 1;
+ dis_op = num_ops;
+ }
+
+ if (opd->type & OPTYPE_OP) {
+ sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+ if (opd->type & OPTYPE_SIG)
+ shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
+ 'a' + num_ops, 1 << sbit, 'a' + num_ops,
+ 0xffffffff << sbit);
+ if ((opd->type & OPTYPE_REG) && !dis) {
+ if(!i) {
+ shift_fprintf (level, fo, "#define SET_PARAM0(val) cpu_state.reg[a] = val\n");
+ shift_fprintf (level, fo, "#define REG_PARAM0 a\n");
+ set_param = 1;
+ }
+ shift_fprintf (level, fo, "#define PARAM%i cpu_state.reg[%c]\n", num_ops,
+ 'a' + num_ops);
+ if(opd->type & OPTYPE_DST)
+ write_to_reg = 1;
+ } else {
+ shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops,
+ 'a' + num_ops);
+ }
+ num_ops++;
+ nbits = 0;
+ dis = 0;
+ }
+
+ if ((opd->type & OPTYPE_LAST))
+ break;
+ opd++;
+ i++;
+ } while (1);
+
+ output_function (fo, or1ksim_or32_opcodes[insn_index].function_name, level);
+
+ if (set_param)
+ {
+ shift_fprintf (level, fo, "#undef SET_PARAM0\n");
+ shift_fprintf (level, fo, "#undef REG_PARAM0\n");
+ }
+
+ for (i = 0; i < num_ops; i++)
+ shift_fprintf (level, fo, "#undef PARAM%i\n", i);
+
+ return dis_op;
+}
+
+/* Generates decode and execute for one instruction instance */
+static int output_call (FILE *fo, int index, int level)
+{
+ int dis_op = -1;
+
+ /*printf ("%i:%s\n", index, insn_name (index));*/
+
+ shift_fprintf (level++, fo, "{\n");
+
+ if (index >= 0)
+ dis_op = gen_eval_operands (fo, index, level);
+
+ if (index < 0) output_function (fo, "l_invalid", level);
+
+ fprintf (fo, "\n");
+
+ shift_fprintf (level++, fo, "if (do_stats) {\n");
+
+ if (dis_op >= 0)
+ shift_fprintf (level, fo, "cpu_state.insn_ea = %c;\n", 'a' + dis_op);
+
+ shift_fprintf (level, fo, "current->insn_index = %i; /* \"%s\" */\n", index,
+ or1ksim_insn_name (index));
+
+ shift_fprintf (level, fo, "analysis(current);\n");
+ shift_fprintf (--level, fo, "}\n");
+
+ if (write_to_reg)
+ shift_fprintf (level, fo, "cpu_state.reg[0] = 0; /* Repair in case we changed it */\n");
+ shift_fprintf (--level, fo, "}\n");
+ return 0;
+}
+
+
+/* Generates .c file header */
+static int generate_header (FILE *fo)
+{
+ fprintf (fo, "/* execgen.c -- Automatically generated decoder\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
+ fprintf (fo, " Copyright (C) 2008 Embecosm Limited\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " Contributor Jeremy Bennett \n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This program is free software; you can redistribute it and/or modify it\n");
+ fprintf (fo, " under the terms of the GNU General Public License as published by the Free\n");
+ fprintf (fo, " Software Foundation; either version 3 of the License, or (at your option)\n");
+ fprintf (fo, " any later version.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This program is distributed in the hope that it will be useful, but WITHOUT\n");
+ fprintf (fo, " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n");
+ fprintf (fo, " FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n");
+ fprintf (fo, " more details.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " You should have received a copy of the GNU General Public License along\n");
+ fprintf (fo, " with this program. If not, see . */\n");
+ fprintf (fo, "\n");
+ fprintf (fo, "/* This program is commented throughout in a fashion suitable for processing\n");
+ fprintf (fo, " with Doxygen. */\n");
+ fprintf (fo, "\n");
+
+ fprintf (fo, "/* This file was automatically generated by generate (see\n");
+ fprintf (fo, " cpu/or32/generate.c) */\n\n");
+
+
+ return 0;
+}
+
+/* Generates .c file decode function hedaer */
+static int generate_decode_function_header (FILE *fo)
+{
+ fprintf (fo, "typedef union {\n\tfloat fval;\n\tuint32_t hval;\n} FLOAT;\n\n");
+ fprintf (fo, "static void decode_execute (struct iqueue_entry *current)\n{\n");
+ fprintf (fo, " uint32_t insn = current->insn;\n");
+ out_lines +=3;
+ return 0;
+}
+
+// List of strings which will be printed on a line after "#include "
+char *include_strings[] = { "",
+ "",
+ ""}; // Last one must be empty
+
+
+/* Generates .c file includes */
+static int generate_includes (FILE *fo)
+{
+ int i;
+ for (i=0;(strcmp(include_strings[i], "")!=0);i++)
+ fprintf (fo, "#include %s\n\n", include_strings[i]);
+ out_lines +=i;
+ return 0;
+
+}
+
+/* Generates .c file footer */
+static int generate_footer (FILE *fo)
+{
+ fprintf (fo, "}\n");
+ return 0;
+}
+
+/* Decodes all instructions and generates code for that. This function
+ is similar to or1ksim_insn_decode, except it decodes all instructions.
+
+ JPB: Added code to generate an illegal instruction exception for invalid
+ instructions. */
+static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
+{
+ unsigned long shift = *a;
+ unsigned long mask;
+ int i;
+ int prev_inv = 0;
+
+ if (!(*a & LEAF_FLAG)) {
+ shift = *a++;
+ mask = *a++;
+ shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift,
+ mask);
+ for (i = 0; i <= mask; i++, a++) {
+ if (!*a) {
+ shift_fprintf (level, fo, "case 0x%x:\n", i);
+ prev_inv = 1;
+ } else {
+ if(prev_inv) {
+ shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
+ shift_fprintf (level--, fo, "break;\n");
+ }
+ shift_fprintf (level, fo, "case 0x%x:\n", i);
+ generate_body (fo, or1ksim_automata + *a, cur_mask | (mask << shift), ++level);
+ shift_fprintf (level--, fo, "break;\n");
+ prev_inv = 0;
+ }
+ }
+ if (prev_inv) {
+ shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
+ shift_fprintf (level, fo,
+ "except_handle (EXCEPT_ILLEGAL, cpu_state.pc);\n");
+ shift_fprintf (level--, fo, "break;\n");
+ }
+ shift_fprintf (level, fo, "}\n");
+ } else {
+ i = *a & ~LEAF_FLAG;
+
+ /* Final check - do we have direct match?
+ (based on or1ksim_or32_opcodes this should be the only possibility,
+ but in case of invalid/missing instruction we must perform a check) */
+
+ if (or1ksim_ti[i].insn_mask != cur_mask) {
+ shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", or1ksim_ti[i].insn_mask, cur_mask);
+ shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n",
+ or1ksim_ti[i].insn_mask, or1ksim_ti[i].insn);
+ }
+ shift_fprintf (level, fo, "/* Instruction: %s */\n", or1ksim_or32_opcodes[i].name);
+
+ output_call (fo, i, level);
+
+ if (or1ksim_ti[i].insn_mask != cur_mask) {
+ shift_fprintf (--level, fo, "} else {\n");
+ shift_fprintf (++level, fo, "/* Invalid insn */\n");
+ output_call (fo, -1, level);
+ shift_fprintf (--level, fo, "}\n");
+ }
+ }
+ return 0;
+}
+
+/* Main function; it takes two parameters:
+ input_file(possibly insnset.c) output_file(possibly execgen.c)*/
+int main (int argc, char *argv[])
+{
+ FILE *fo;
+
+ if (argc != 3) {
+ fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
+ exit (-1);
+ }
+
+ in_file = argv[1];
+ out_file = argv[2];
+ if (!(fo = fopen (argv[2], "wt+"))) {
+ fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
+ exit (1);
+ }
+
+ or1ksim_build_automata (0);
+ if (generate_header (fo)) {
+ fprintf (stderr, "generate_header\n");
+ return 1;
+ }
+
+ if (generate_includes (fo)) {
+ fprintf (stderr, "generate_includes\n");
+ return 1;
+ }
+
+ if (generate_decode_function_header (fo)) {
+ fprintf (stderr, "generate_decode_function_header\n");
+ return 1;
+ }
+
+ if (generate_body (fo, or1ksim_automata, 0, 1)) {
+ fprintf (stderr, "generate_body\n");
+ return 1;
+ }
+
+ if (generate_footer (fo)) {
+ fprintf (stderr, "generate_footer\n");
+ return 1;
+ }
+
+ fclose (fo);
+ or1ksim_destruct_automata ();
+ return 0;
+}
+
generate.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: insnset.c
===================================================================
--- insnset.c (nonexistent)
+++ insnset.c (revision 388)
@@ -0,0 +1,933 @@
+/* insnset.c -- Instruction specific functions.
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ 2000-2002 Marko Mlinar, markom@opencores.org
+ Copyright (C) 2008 Embecosm Limited
+ Copyright (C) 2009 Jungsook yang, jungsook.yang@uci.edu
+
+ Contributor Jeremy Bennett
+ Contributor Julius Baxter julius@orsoc.se
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+INSTRUCTION (l_add) {
+ orreg_t temp1, temp2, temp3;
+ int8_t temp4;
+
+ temp2 = (orreg_t)PARAM2;
+ temp3 = (orreg_t)PARAM1;
+ temp1 = temp2 + temp3;
+ SET_PARAM0 (temp1);
+
+ /* Set overflow if two negative values gave a positive sum, or if two
+ positive values gave a negative sum. Otherwise clear it */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the result is smaller than
+ either operand (if it smaller than one, it will be smaller than both, so
+ we need only test one). */
+ if ((uorreg_t) temp1 < (uorreg_t) temp2)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+
+ temp4 = temp1;
+ if (temp4 == temp1)
+ or1k_mstats.byteadd++;
+}
+INSTRUCTION (l_addc) {
+ orreg_t temp1, temp2, temp3;
+ int8_t temp4;
+ int carry_in = (cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY;
+
+ temp2 = (orreg_t)PARAM2;
+ temp3 = (orreg_t)PARAM1;
+ temp1 = temp2 + temp3;
+
+ if(carry_in)
+ {
+ temp1++; /* Add in the carry bit */
+ }
+
+ SET_PARAM0(temp1);
+
+ /* Set overflow if two negative values gave a positive sum, or if two
+ positive values gave a negative sum. Otherwise clear it. There are no
+ corner cases with the extra bit carried in (unlike the carry flag - see
+ below). */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the result is smaller than
+ either operand (if it smaller than one, it will be smaller than both, so
+ we need only test one). If there is a carry in, the test should be less
+ than or equal, to deal with the 0 + 0xffffffff + c = 0 case (which
+ generates a carry). */
+ if ((carry_in && ((uorreg_t) temp1 <= (uorreg_t) temp2)) ||
+ ((uorreg_t) temp1 < (uorreg_t) temp2))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+
+ temp4 = temp1;
+ if (temp4 == temp1)
+ or1k_mstats.byteadd++;
+}
+INSTRUCTION (l_sw) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem32(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t - old_cyc);
+ }
+}
+INSTRUCTION (l_sb) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem8(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t- old_cyc);
+ }
+}
+INSTRUCTION (l_sh) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem16(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t - old_cyc);
+ }
+}
+INSTRUCTION (l_lws) {
+ uint32_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem32(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lwz) {
+ uint32_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem32(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lbs) {
+ int8_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem8(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lbz) {
+ uint8_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem8(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lhs) {
+ int16_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem16(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lhz) {
+ uint16_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem16(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_movhi) {
+ SET_PARAM0(PARAM1 << 16);
+}
+INSTRUCTION (l_and) {
+ uorreg_t temp1;
+ temp1 = PARAM1 & PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_or) {
+ uorreg_t temp1;
+ temp1 = PARAM1 | PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_xor) {
+ /* The argument is now specified as unsigned, but historically OR1K has
+ always treated the argument as signed (so l.xori rD,rA,-1 can be used in
+ the absence of l.not). Use this as the default behavior. This is
+ controlled from or32.c. */
+ uorreg_t temp1 = PARAM1 ^ PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_sub) {
+ orreg_t temp1, temp2, temp3;
+
+ temp3 = (orreg_t)PARAM2;
+ temp2 = (orreg_t)PARAM1;
+ temp1 = temp2 - temp3;
+ SET_PARAM0 (temp1);
+
+ /* Set overflow if a negative value minus a positive value gave a positive
+ sum, or if a positive value minus a negative value gave a negative
+ sum. Otherwise clear it */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the second operand is greater
+ than the first. */
+ if ((uorreg_t) temp3 > (uorreg_t) temp2)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+/*int mcount = 0;*/
+INSTRUCTION (l_mul) {
+ orreg_t temp0, temp1, temp2;
+ LONGEST ltemp0, ltemp1, ltemp2;
+ ULONGEST ultemp0, ultemp1, ultemp2;
+
+ /* Args in 32-bit */
+ temp2 = (orreg_t) PARAM2;
+ temp1 = (orreg_t) PARAM1;
+
+ /* Compute initially in 64-bit */
+ ltemp1 = (LONGEST) temp1;
+ ltemp2 = (LONGEST) temp2;
+ ltemp0 = ltemp1 * ltemp2;
+
+ temp0 = (orreg_t) (ltemp0 & 0xffffffffLL);
+ SET_PARAM0 (temp0);
+
+ /* We have 2's complement overflow, if the result is less than the smallest
+ possible 32-bit negative number, or greater than the largest possible
+ 32-bit positive number. */
+ if ((ltemp0 < (LONGEST) INT32_MIN) || (ltemp0 > (LONGEST) INT32_MAX))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* We have 1's complement overflow, if, as an unsigned operation, the result
+ is greater than the largest possible 32-bit unsigned number. This is
+ probably quicker than unpicking the bits of the signed result. */
+ ultemp1 = (ULONGEST) temp1 & 0xffffffffULL;
+ ultemp2 = (ULONGEST) temp2 & 0xffffffffULL;
+ ultemp0 = ultemp1 * ultemp2;
+
+ if (ultemp0 > (ULONGEST) UINT32_MAX)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_mulu) {
+ uorreg_t temp0, temp1, temp2;
+ ULONGEST ultemp0, ultemp1, ultemp2;
+
+ /* Args in 32-bit */
+ temp2 = (uorreg_t) PARAM2;
+ temp1 = (uorreg_t) PARAM1;
+
+ /* Compute initially in 64-bit */
+ ultemp1 = (ULONGEST) temp1 & 0xffffffffULL;
+ ultemp2 = (ULONGEST) temp2 & 0xffffffffULL;
+ ultemp0 = ultemp1 * ultemp2;
+
+ temp0 = (uorreg_t) (ultemp0 & 0xffffffffULL);
+ SET_PARAM0 (temp0);
+
+ /* We never have 2's complement overflow */
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+
+ /* We have 1's complement overflow, if the result is greater than the
+ largest possible 32-bit unsigned number. */
+ if (ultemp0 > (ULONGEST) UINT32_MAX)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+}
+INSTRUCTION (l_div) {
+ orreg_t temp3, temp2, temp1;
+
+ temp3 = (orreg_t) PARAM2;
+ temp2 = (orreg_t) PARAM1;
+
+ /* Check for divide by zero (sets carry) */
+ if (0 == temp3)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ temp1 = temp2 / temp3;
+ SET_PARAM0(temp1);
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV; /* Never set */
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_divu) {
+ uorreg_t temp3, temp2, temp1;
+
+ temp3 = (uorreg_t) PARAM2;
+ temp2 = (uorreg_t) PARAM1;
+
+ /* Check for divide by zero (sets carry) */
+ if (0 == temp3)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ temp1 = temp2 / temp3;
+ SET_PARAM0(temp1);
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV; /* Never set */
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_sll) {
+ uorreg_t temp1;
+
+ temp1 = PARAM1 << PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_sra) {
+ orreg_t temp1;
+
+ temp1 = (orreg_t)PARAM1 >> PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_srl) {
+ uorreg_t temp1;
+ temp1 = PARAM1 >> PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_ror) {
+ uorreg_t temp1;
+ temp1 = PARAM1 >> (PARAM2 & 0x1f);
+ temp1 |= PARAM1 << (32 - (PARAM2 & 0x1f));
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_bf) {
+ if (config.bpb.enabled) {
+ int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
+ or1k_mstats.bf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0][fwd]++;
+ bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
+ }
+ if(cpu_state.sprs[SPR_SR] & SPR_SR_F) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ btic_update(pcnext);
+ next_delay_insn = 1;
+ } else {
+ btic_update(cpu_state.pc);
+ }
+}
+INSTRUCTION (l_bnf) {
+ if (config.bpb.enabled) {
+ int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
+ or1k_mstats.bnf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1][fwd]++;
+ bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1);
+ }
+ if (!(cpu_state.sprs[SPR_SR] & SPR_SR_F)) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ btic_update(pcnext);
+ next_delay_insn = 1;
+ } else {
+ btic_update(cpu_state.pc);
+ }
+}
+INSTRUCTION (l_j) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ next_delay_insn = 1;
+}
+INSTRUCTION (l_jal) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+
+ setsim_reg(LINK_REGNO, cpu_state.pc + 8);
+ next_delay_insn = 1;
+ if (config.sim.profile) {
+ struct label_entry *tmp;
+ if (verify_memoryarea(cpu_state.pc_delay) && (tmp = get_label (cpu_state.pc_delay)))
+ fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n",
+ runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
+ tmp->name);
+ else
+ fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n",
+ runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
+ cpu_state.pc_delay);
+ }
+}
+INSTRUCTION (l_jalr) {
+ /* Badly aligned destination or use of link register triggers an exception */
+ uorreg_t temp1 = PARAM0;
+
+ if (REG_PARAM0 == LINK_REGNO)
+ {
+ except_handle (EXCEPT_ILLEGAL, cpu_state.pc);
+ }
+ else if ((temp1 & 0x3) != 0)
+ {
+ except_handle (EXCEPT_ALIGN, cpu_state.pc);
+ }
+ else
+ {
+ cpu_state.pc_delay = temp1;
+ setsim_reg(LINK_REGNO, cpu_state.pc + 8);
+ next_delay_insn = 1;
+ }
+}
+INSTRUCTION (l_jr) {
+ /* Badly aligned destination triggers an exception */
+ uorreg_t temp1 = PARAM0;
+
+ if ((temp1 & 0x3) != 0)
+ {
+ except_handle (EXCEPT_ALIGN, cpu_state.pc);
+ }
+ else
+ {
+ cpu_state.pc_delay = temp1;
+ next_delay_insn = 1;
+
+ if (config.sim.profile)
+ {
+ fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n",
+ runtime.sim.cycles, cpu_state.pc_delay);
+ }
+ }
+}
+INSTRUCTION (l_rfe) {
+ pcnext = cpu_state.sprs[SPR_EPCR_BASE];
+ mtspr(SPR_SR, cpu_state.sprs[SPR_ESR_BASE]);
+}
+INSTRUCTION (l_nop) {
+ uint32_t k = PARAM0;
+ switch (k) {
+ case NOP_NOP:
+ break;
+ case NOP_EXIT:
+ PRINTFQ("exit(%"PRIdREG")\n", evalsim_reg (3));
+ PRINTFQ("@reset : cycles %lld, insn #%lld\n",
+ runtime.sim.reset_cycles, runtime.cpu.reset_instructions);
+ PRINTFQ("@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles,
+ runtime.cpu.instructions);
+ PRINTFQ(" diff : cycles %lld, insn #%lld\n",
+ runtime.sim.cycles - runtime.sim.reset_cycles,
+ runtime.cpu.instructions - runtime.cpu.reset_instructions);
+ if (config.sim.is_library)
+ {
+ runtime.cpu.halted = 1;
+ set_stall_state (1);
+ }
+ else
+ {
+ sim_done();
+ }
+ break;
+ case NOP_CNT_RESET:
+ PRINTF("****************** counters reset ******************\n");
+ PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
+ PRINTF("****************** counters reset ******************\n");
+ runtime.sim.reset_cycles = runtime.sim.cycles;
+ runtime.cpu.reset_instructions = runtime.cpu.instructions;
+ break;
+ case NOP_PUTC: /*JPB */
+ printf( "%c", (char)(evalsim_reg( 3 ) & 0xff));
+ fflush( stdout );
+ break;
+ case NOP_GET_TICKS:
+ cpu_state.reg[11] = runtime.sim.cycles & 0xffffffff;
+ cpu_state.reg[12] = runtime.sim.cycles >> 32;
+ break;
+ case NOP_GET_PS:
+ cpu_state.reg[11] = config.sim.clkcycle_ps;
+ break;
+ case NOP_REPORT:
+ PRINTF("report(0x%"PRIxREG");\n", evalsim_reg(3));
+ default:
+ if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST)
+ PRINTF("report %" PRIdREG " (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST,
+ evalsim_reg(3));
+ break;
+ }
+}
+INSTRUCTION (l_sfeq) {
+ if(PARAM0 == PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfne) {
+ if(PARAM0 != PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgts) {
+ if((orreg_t)PARAM0 > (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfges) {
+ if((orreg_t)PARAM0 >= (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sflts) {
+ if((orreg_t)PARAM0 < (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfles) {
+ if((orreg_t)PARAM0 <= (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgtu) {
+ if(PARAM0 > PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgeu) {
+ if(PARAM0 >= PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfltu) {
+ if(PARAM0 < PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfleu) {
+ if(PARAM0 <= PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_extbs) {
+ int8_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_extbz) {
+ uint8_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_exths) {
+ int16_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_exthz) {
+ uint16_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_extws) {
+ int32_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_extwz) {
+ uint32_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_mtspr) {
+ uint16_t regno = PARAM0 | PARAM2;
+ uorreg_t value = PARAM1;
+
+ if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
+ mtspr(regno, value);
+ else {
+ PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n");
+ sim_done();
+ }
+}
+INSTRUCTION (l_mfspr) {
+ uint16_t regno = PARAM1 | PARAM2;
+ uorreg_t value = mfspr(regno);
+
+ if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
+ SET_PARAM0(value);
+ else {
+ SET_PARAM0(0);
+ PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n");
+ sim_done();
+ }
+}
+INSTRUCTION (l_sys) {
+ except_handle(EXCEPT_SYSCALL, cpu_state.sprs[SPR_EEAR_BASE]);
+}
+INSTRUCTION (l_trap) {
+ /* TODO: some SR related code here! */
+ except_handle(EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
+}
+INSTRUCTION (l_mac) {
+ uorreg_t lo, hi;
+ LONGEST l;
+ orreg_t x, y, t;
+
+ lo = cpu_state.sprs[SPR_MACLO];
+ hi = cpu_state.sprs[SPR_MACHI];
+ x = PARAM0;
+ y = PARAM1;
+/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
+
+ /* Compute the temporary as (signed) 32-bits, then sign-extend to 64 when
+ adding in. */
+ l = (ULONGEST)lo | ((LONGEST)hi << 32);
+ t = x * y;
+ l += (LONGEST) t;
+
+ /* This implementation is very fast - it needs only one cycle for mac. */
+ lo = ((ULONGEST)l) & 0xFFFFFFFF;
+ hi = ((LONGEST)l) >> 32;
+ cpu_state.sprs[SPR_MACLO] = lo;
+ cpu_state.sprs[SPR_MACHI] = hi;
+/* PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo); */
+}
+INSTRUCTION (l_msb) {
+ uorreg_t lo, hi;
+ LONGEST l;
+ orreg_t x, y;
+
+ lo = cpu_state.sprs[SPR_MACLO];
+ hi = cpu_state.sprs[SPR_MACHI];
+ x = PARAM0;
+ y = PARAM1;
+
+/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
+
+ l = (ULONGEST)lo | ((LONGEST)hi << 32);
+ l -= x * y;
+
+ /* This implementation is very fast - it needs only one cycle for msb. */
+ lo = ((ULONGEST)l) & 0xFFFFFFFF;
+ hi = ((LONGEST)l) >> 32;
+ cpu_state.sprs[SPR_MACLO] = lo;
+ cpu_state.sprs[SPR_MACHI] = hi;
+/* PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo); */
+}
+INSTRUCTION (l_macrc) {
+ orreg_t lo;
+ /* No need for synchronization here -- all MAC instructions are 1 cycle long. */
+ lo = cpu_state.sprs[SPR_MACLO];
+ //PRINTF ("<%08x>\n", (unsigned long)l);
+ SET_PARAM0(lo);
+ cpu_state.sprs[SPR_MACLO] = 0;
+ cpu_state.sprs[SPR_MACHI] = 0;
+}
+INSTRUCTION (l_cmov) {
+ SET_PARAM0(cpu_state.sprs[SPR_SR] & SPR_SR_F ? PARAM1 : PARAM2);
+}
+INSTRUCTION (l_ff1) {
+ SET_PARAM0(ffs(PARAM1));
+}
+INSTRUCTION (l_fl1) {
+ orreg_t t = (orreg_t)PARAM1;
+
+ /* Reverse the word and use ffs */
+ t = (((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1));
+ t = (((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2));
+ t = (((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4));
+ t = (((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8));
+ t = ffs ((t >> 16) | (t << 16));
+
+ SET_PARAM0 (0 == t ? t : 33 - t);
+}
+/******* Floating point instructions *******/
+/* Do calculation, and update FPCSR as required */
+/* Single precision */
+INSTRUCTION (lf_add_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_add((unsigned int)PARAM1,(unsigned int)PARAM2));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_div_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_div((unsigned int)PARAM1,(unsigned int)PARAM2));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_ftoi_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_to_int32((unsigned int)PARAM1));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_itof_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(int32_to_float32((unsigned int)PARAM1));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_madd_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_add((unsigned int)PARAM0, float32_mul((unsigned int)PARAM1,(unsigned int)PARAM2)));
+ // Note: this ignores flags from the multiply!
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_mul_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_mul((unsigned int)PARAM1,(unsigned int)PARAM2));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_rem_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_rem((unsigned int)PARAM1,(unsigned int)PARAM2));
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfeq_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if(float32_eq((unsigned int)PARAM0, (unsigned int)PARAM1))
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfge_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if((!float32_lt((unsigned int)PARAM0, (unsigned int)PARAM1) &
+ !float32_is_nan( (unsigned int)PARAM0) &
+ !float32_is_nan( (unsigned int)PARAM1) ) )
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfgt_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if((!float32_le((unsigned int)PARAM0, (unsigned int)PARAM1) &
+ !float32_is_nan( (unsigned int)PARAM0) &
+ !float32_is_nan( (unsigned int)PARAM1) ) )
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfle_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if((float32_le((unsigned int)PARAM0, (unsigned int)PARAM1) &
+ !float32_is_nan( (unsigned int)PARAM0) &
+ !float32_is_nan( (unsigned int)PARAM1) ) )
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sflt_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if(( float32_lt((unsigned int)PARAM0, (unsigned int)PARAM1) &
+ !float32_is_nan( (unsigned int)PARAM0) &
+ !float32_is_nan( (unsigned int)PARAM1) ) )
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfne_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ if(!float32_eq((unsigned int)PARAM0, (unsigned int)PARAM1))
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ float_set_flags();
+ } else l_invalid();
+}
+INSTRUCTION (lf_sub_s) {
+ if (config.cpu.hardfloat) {
+ float_set_rm();
+ SET_PARAM0(float32_sub((unsigned int)PARAM1,(unsigned int)PARAM2));
+ float_set_flags();
+ } else l_invalid();
+}
+
+/******* Custom instructions *******/
+INSTRUCTION (l_cust1) {
+ /*int destr = current->insn >> 21;
+ int src1r = current->insn >> 15;
+ int src2r = current->insn >> 9;*/
+}
+INSTRUCTION (l_cust2) {
+}
+INSTRUCTION (l_cust3) {
+}
+INSTRUCTION (l_cust4) {
+}
+INSTRUCTION (lf_cust1) {
+}
insnset.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: simpl32-defs.h
===================================================================
--- simpl32-defs.h (nonexistent)
+++ simpl32-defs.h (revision 388)
@@ -0,0 +1,111 @@
+/* simpl32-defs.h -- Definitions for the simple execution model
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributed by Damjan Lampret (lampret@opencores.org).
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+ This file is also part of or1k_gen_isa, GDB and GAS.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef SIMPLE32_DEFS__H
+#define SIMPLE32_DEFS__H
+
+/* Package includes */
+#include "abstract.h"
+
+
+extern void l_invalid PARAMS((struct iqueue_entry *));
+extern void l_sfne PARAMS((struct iqueue_entry *));
+extern void l_bf PARAMS((struct iqueue_entry *));
+extern void l_add PARAMS((struct iqueue_entry *));
+extern void l_addc PARAMS((struct iqueue_entry *));
+extern void l_sw PARAMS((struct iqueue_entry *));
+extern void l_sb PARAMS((struct iqueue_entry *));
+extern void l_sh PARAMS((struct iqueue_entry *));
+extern void l_lwz PARAMS((struct iqueue_entry *));
+extern void l_lbs PARAMS((struct iqueue_entry *));
+extern void l_lbz PARAMS((struct iqueue_entry *));
+extern void l_lhs PARAMS((struct iqueue_entry *));
+extern void l_lhz PARAMS((struct iqueue_entry *));
+extern void l_movhi PARAMS((struct iqueue_entry *));
+extern void l_and PARAMS((struct iqueue_entry *));
+extern void l_or PARAMS((struct iqueue_entry *));
+extern void l_xor PARAMS((struct iqueue_entry *));
+extern void l_sub PARAMS((struct iqueue_entry *));
+extern void l_mul PARAMS((struct iqueue_entry *));
+extern void l_div PARAMS((struct iqueue_entry *));
+extern void l_divu PARAMS((struct iqueue_entry *));
+extern void l_sll PARAMS((struct iqueue_entry *));
+extern void l_sra PARAMS((struct iqueue_entry *));
+extern void l_srl PARAMS((struct iqueue_entry *));
+extern void l_j PARAMS((struct iqueue_entry *));
+extern void l_jal PARAMS((struct iqueue_entry *));
+extern void l_jalr PARAMS((struct iqueue_entry *));
+extern void l_jr PARAMS((struct iqueue_entry *));
+extern void l_rfe PARAMS((struct iqueue_entry *));
+extern void l_nop PARAMS((struct iqueue_entry *));
+extern void l_bnf PARAMS((struct iqueue_entry *));
+extern void l_sfeq PARAMS((struct iqueue_entry *));
+extern void l_sfgts PARAMS((struct iqueue_entry *));
+extern void l_sfges PARAMS((struct iqueue_entry *));
+extern void l_sflts PARAMS((struct iqueue_entry *));
+extern void l_sfles PARAMS((struct iqueue_entry *));
+extern void l_sfgtu PARAMS((struct iqueue_entry *));
+extern void l_sfgeu PARAMS()(struct iqueue_entry *);
+extern void l_sfltu PARAMS((struct iqueue_entry *));
+extern void l_sfleu PARAMS((struct iqueue_entry *));
+extern void l_extbs PARAMS((struct iqueue_entry *));
+extern void l_extbz PARAMS((struct iqueue_entry *));
+extern void l_exths PARAMS((struct iqueue_entry *));
+extern void l_exthz PARAMS((struct iqueue_entry *));
+extern void l_extws PARAMS((struct iqueue_entry *));
+extern void l_extwz PARAMS((struct iqueue_entry *));
+extern void l_mtspr PARAMS((struct iqueue_entry *));
+extern void l_mfspr PARAMS((struct iqueue_entry *));
+extern void l_sys PARAMS((struct iqueue_entry *));
+extern void l_trap PARAMS((struct iqueue_entry *)); /* CZ 21/06/01 */
+extern void l_macrc PARAMS((struct iqueue_entry *));
+extern void l_mac PARAMS((struct iqueue_entry *));
+extern void l_msb PARAMS((struct iqueue_entry *));
+extern void l_cmov PARAMS ((struct iqueue_entry *));
+extern void l_ff1 PARAMS ((struct iqueue_entry *));
+extern void l_cust1 PARAMS ((struct iqueue_entry *));
+extern void l_cust2 PARAMS ((struct iqueue_entry *));
+extern void l_cust3 PARAMS ((struct iqueue_entry *));
+extern void l_cust4 PARAMS ((struct iqueue_entry *));
+extern void lf_add_s PARAMS ((struct iqueue_entry *));
+extern void lf_div_s PARAMS ((struct iqueue_entry *));
+extern void lf_ftoi_s PARAMS ((struct iqueue_entry *));
+extern void lf_itof_s PARAMS ((struct iqueue_entry *));
+extern void lf_madd_s PARAMS ((struct iqueue_entry *));
+extern void lf_mul_s PARAMS ((struct iqueue_entry *));
+extern void lf_rem_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfeq_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfge_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfgt_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfle_s PARAMS ((struct iqueue_entry *));
+extern void lf_sflt_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfne_s PARAMS ((struct iqueue_entry *));
+extern void lf_sub_s PARAMS((struct iqueue_entry *));
+extern void l_none PARAMS((struct iqueue_entry *));
+
+#endif /* SIMPLE32_DEFS__H */
simpl32-defs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: rec-i386.h
===================================================================
--- rec-i386.h (nonexistent)
+++ rec-i386.h (revision 388)
@@ -0,0 +1,28 @@
+/* rec-i386.h -- i386 specific parts of the recompile engine
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Gets the current stack pointer */
+static void *get_sp(void)
+{
+ void *stack;
+ asm("movl %%esp, %0" : "=rm" (stack));
+ return stack;
+}
+
rec-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-2t.h
===================================================================
--- op-2t.h (nonexistent)
+++ op-2t.h (revision 388)
@@ -0,0 +1,62 @@
+/* op-2t.h -- Instantiation of operatations that work on only 2 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define OP_2T
+#define T glue(glue(glue(_, T0), _), T1)
+
+#if NUM_T_REGS == 3
+# define T0 t0
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+# define T0 t1
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+# define T0 t2
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+#else
+#error Update op_2t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_2T
op-2t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-mftspr-op.h
===================================================================
--- op-mftspr-op.h (nonexistent)
+++ op-mftspr-op.h (revision 388)
@@ -0,0 +1,78 @@
+/* op-mftspr-op.h -- Micro operations template for the m{f,t}spr operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifdef OP_2T
+__or_dynop void glue (op_mfspr, T) (void)
+{
+ /* FIXME: NPC/PPC Handling is br0ke */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ T0 = mfspr (T1 + OP_PARAM1);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (op_mfspr_imm, T) (void)
+{
+ /* FIXME: NPC/PPC Handling is br0ke */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ T0 = mfspr (OP_PARAM1);
+}
+#endif
+
+#ifdef OP_2T
+__or_dynop void glue (op_mtspr, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (T0 + OP_PARAM1, T1);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (op_mtspr_clear, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (T0 + OP_PARAM1, 0);
+}
+
+__or_dynop void glue (op_mtspr_imm, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (OP_PARAM1, T0);
+}
+#endif
+
+#if !defined(OP_1T) && !defined(OP_2T)
+__or_dynop void
+op_mtspr_imm_clear (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (OP_PARAM1, 0);
+}
+#endif
op-mftspr-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-i386.h
===================================================================
--- op-i386.h (nonexistent)
+++ op-i386.h (revision 388)
@@ -0,0 +1,46 @@
+/* op-i386.h -- i386 specific support routines for micro operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef OP_I386__H
+#define OP_I386__H
+
+#define OP_JUMP(x) asm("jmp *%0" : : "rm" (x))
+
+#define FORCE_RET asm volatile ("")
+
+/* Does a function call (with no arguments) makeing sure that gcc doesn't peddle
+ * the stack. (FIXME: Is this safe??) */
+#define SPEEDY_CALL(func) asm("call "#func"\n")
+
+/* Return out of the recompiled code */
+asm (" .align 2\n"
+ " .p2align 4,,15\n"
+ ".globl op_do_jump\n"
+ " .type op_do_jump,@function\n"
+ "op_do_jump:\n"
+ " ret\n" " ret\n" "1:\n" " .size op_do_jump,1b-op_do_jump\n");
+
+#endif /* OP_I386__H */
op-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op.c
===================================================================
--- op.c (nonexistent)
+++ op.c (revision 388)
@@ -0,0 +1,971 @@
+/* op.c -- Micro operations for the recompiler
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "spr-defs.h"
+#include "opcode/or32.h"
+#include "sim-config.h"
+#include "except.h"
+#include "abstract.h"
+#include "execute.h"
+#include "sprs.h"
+#include "sched.h"
+#include "immu.h"
+
+#include "op-support.h"
+
+#include "i386-regs.h"
+
+#include "dyn-rec.h"
+
+register struct cpu_state *env asm(CPU_STATE_REG);
+
+#include "op-i386.h"
+
+/*
+ * WARNING: Before going of and wildly editing everything in this file remember
+ * the following about its contents:
+ * 1) The `functions' don't EVER return. In otherwords haveing return state-
+ * ments _anywere_ in this file is likely not to work. This is because
+ * dyngen just strips away the ret from the end of the function and just uses
+ * the function `body'. If a ret statement is executed _anyware_ inside the
+ * dynamicly generated code, then it is undefined were we shall jump to.
+ * 2) Because of 1), try not to have overly complicated functions. In too
+ * complicated functions, gcc may decide to generate premature `exits'. This
+ * is what passing the -fno-reorder-blocks command line switch to gcc helps
+ * with. This is ofcourse not desired and is rather flaky as we don't (and
+ * can't) control the kind of code that gcc generates: It may work for one
+ * and break for another. The less branches there are the less likely it is
+ * that a premature return shall occur.
+ * 3) If gcc decides that it is going to be a basterd then it will optimise a
+ * very simple condition (if/switch) with a premature exit. But gcc can't
+ * fuck ME over! Just stick a FORCE_RET; at the END of the offending
+ * function.
+ * 4) All operations must start with `op_'. dyngen ignores all other functions.
+ * 5) Local variables are depriciated: They hinder performance.
+ * 6) Function calls are expensive as the stack has to be shifted (twice).
+ */
+
+/*#define __or_dynop __attribute__((noreturn))*/
+#define __or_dynop
+
+/* Temporaries to hold the (simulated) registers in */
+register uint32_t t0 asm(T0_REG);
+register uint32_t t1 asm(T1_REG);
+register uint32_t t2 asm(T2_REG);
+
+#define OP_PARAM1 ((uorreg_t)(&__op_param1))
+#define OP_PARAM2 ((uorreg_t)(&__op_param2))
+#define OP_PARAM3 ((uorreg_t)(&__op_param3))
+
+extern uorreg_t __op_param1;
+extern uorreg_t __op_param2;
+extern uorreg_t __op_param3;
+
+
+static inline void save_t_bound(oraddr_t pc)
+{
+ int reg;
+
+ pc = (pc & immu_state->page_offset_mask) / 4;
+ reg = env->curr_page->ts_bound[pc];
+
+ if(reg & 0x1f)
+ env->reg[reg & 0x1f] = t0;
+
+ if((reg >> 5) & 0x1f)
+ env->reg[(reg >> 5) & 0x1f] = t1;
+
+ if((reg >> 10) & 0x1f)
+ env->reg[(reg >> 10) & 0x1f] = t2;
+}
+
+void do_sched_wrap(void)
+{
+ env->pc += 4;
+ //runtime.cpu.instructions++;
+ runtime.sim.cycles -= env->cycles_dec;
+ scheduler.job_queue->time += env->cycles_dec;
+ if(scheduler.job_queue->time <= 0) {
+ save_t_bound(env->pc - 4);
+ do_scheduler();
+ }
+}
+
+/* do_scheduler wrapper for instructions that are in the delay slot */
+void do_sched_wrap_delay(void)
+{
+ /* FIXME: Can't this be eliminated? */
+ env->pc += 4;
+ //runtime.cpu.instructions++;
+ runtime.sim.cycles -= env->cycles_dec;
+ scheduler.job_queue->time += env->cycles_dec;
+ if(scheduler.job_queue->time <= 0)
+ do_scheduler();
+}
+
+void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
+{
+ uint16_t reg = 0;
+ uint32_t t0_reg = t0, t1_reg = t1, t2_reg = t2;
+ struct cpu_state *cpu_reg = env;
+
+ addr &= immu_state->page_offset_mask;
+ addr >>= 2;
+
+ if(addr)
+ reg = dp->ts_bound[addr - 1];
+
+ t0 = cpu_state.reg[reg & 0x1f];
+ t1 = cpu_state.reg[(reg >> 5) & 0x1f];
+
+ /* Don't we all love gcc? For some heavenly reason gcc 3.2 _knows_ that if I
+ * don't put a condition around the assignment of t2, _all_ the assignments to
+ * t{0,1,2} are useless and not needed. I'm pleasently happy that gcc is so
+ * bright, but on the other hand, t{0,1,2} are globals (!) how can you assume
+ * that the value of a global won't be used in a function further up or
+ * further down the stack?? */
+ if(addr)
+ t2 = cpu_state.reg[(reg >> 10) & 0x1f];
+
+ env = &cpu_state;
+
+ ((gen_code_ent *)dp->locs)[addr]();
+ t0 = t0_reg;
+ t1 = t1_reg;
+ t2 = t2_reg;
+ env = (struct cpu_state *)cpu_reg;
+}
+
+__or_dynop void op_set_pc_pc_delay(void)
+{
+ env->sprs[SPR_PPC] = env->pc;
+ /* pc_delay is pulled back 4 since imediatly after this is run, the scheduler
+ * runs which also increments it by 4 */
+ env->pc = env->pc_delay - 4;
+}
+
+__or_dynop void op_set_pc_delay_imm(void)
+{
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_set_pc_delay_pc(void)
+{
+ env->pc_delay = env->pc;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_clear_pc_delay(void)
+{
+ env->pc_delay = 0;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_do_jump_delay(void)
+{
+ env->pc = env->pc_delay;
+}
+
+__or_dynop void op_clear_delay_insn(void)
+{
+ env->delay_insn = 0;
+}
+
+__or_dynop void op_set_delay_insn(void)
+{
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_check_delay_slot(void)
+{
+ if(!env->delay_insn)
+ OP_JUMP(OP_PARAM1);
+}
+
+__or_dynop void op_jmp_imm(void)
+{
+ OP_JUMP(OP_PARAM1);
+}
+
+__or_dynop void op_set_flag(void)
+{
+ env->sprs[SPR_SR] |= SPR_SR_F;
+}
+
+__or_dynop void op_clear_flag(void)
+{
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+}
+
+/* Used for the l.bf instruction. Therefore if the flag is not set, jump over
+ * all the jumping stuff */
+__or_dynop void op_check_flag(void)
+{
+ if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
+ SPEEDY_CALL(do_sched_wrap);
+ OP_JUMP(OP_PARAM1);
+ }
+}
+
+/* Used for l.bf if the delay slot instruction is on another page */
+__or_dynop void op_check_flag_delay(void)
+{
+ if(env->sprs[SPR_SR] & SPR_SR_F) {
+ env->delay_insn = 1;
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ }
+}
+
+/* Used for the l.bnf instruction. Therefore if the flag is set, jump over all
+ * the jumping stuff */
+__or_dynop void op_check_not_flag(void)
+{
+ if(env->sprs[SPR_SR] & SPR_SR_F) {
+ SPEEDY_CALL(do_sched_wrap);
+ OP_JUMP(OP_PARAM1);
+ }
+}
+
+/* Used for l.bnf if the delay slot instruction is on another page */
+__or_dynop void op_check_not_flag_delay(void)
+{
+ if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
+ env->delay_insn = 1;
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ }
+}
+
+__or_dynop void op_add_pc(void)
+{
+ env->pc += OP_PARAM1;
+}
+
+__or_dynop void op_nop_exit(void)
+{
+ op_support_nop_exit();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_reset(void)
+{
+ op_support_nop_reset();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_printf(void)
+{
+ op_support_nop_printf();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_report(void)
+{
+ op_support_nop_report();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_report_imm(void)
+{
+ op_support_nop_report_imm(OP_PARAM1);
+}
+
+/* FIXME: Create another 2 sched functions that to the actual analysis call
+ * instead of bloating the recompiled code with this */
+__or_dynop void op_analysis(void)
+{
+ SPEEDY_CALL(op_support_analysis);
+}
+
+__or_dynop void op_move_gpr1_pc_delay(void)
+{
+ env->pc_delay = env->reg[1];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr2_pc_delay(void)
+{
+ env->pc_delay = env->reg[2];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr3_pc_delay(void)
+{
+ env->pc_delay = env->reg[3];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr4_pc_delay(void)
+{
+ env->pc_delay = env->reg[4];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr5_pc_delay(void)
+{
+ env->pc_delay = env->reg[5];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr6_pc_delay(void)
+{
+ env->pc_delay = env->reg[6];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr7_pc_delay(void)
+{
+ env->pc_delay = env->reg[7];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr8_pc_delay(void)
+{
+ env->pc_delay = env->reg[8];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr9_pc_delay(void)
+{
+ env->pc_delay = env->reg[9];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr10_pc_delay(void)
+{
+ env->pc_delay = env->reg[10];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr11_pc_delay(void)
+{
+ env->pc_delay = env->reg[11];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr12_pc_delay(void)
+{
+ env->pc_delay = env->reg[12];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr13_pc_delay(void)
+{
+ env->pc_delay = env->reg[13];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr14_pc_delay(void)
+{
+ env->pc_delay = env->reg[14];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr15_pc_delay(void)
+{
+ env->pc_delay = env->reg[15];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr16_pc_delay(void)
+{
+ env->pc_delay = env->reg[16];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr17_pc_delay(void)
+{
+ env->pc_delay = env->reg[17];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr18_pc_delay(void)
+{
+ env->pc_delay = env->reg[18];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr19_pc_delay(void)
+{
+ env->pc_delay = env->reg[19];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr20_pc_delay(void)
+{
+ env->pc_delay = env->reg[20];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr21_pc_delay(void)
+{
+ env->pc_delay = env->reg[21];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr22_pc_delay(void)
+{
+ env->pc_delay = env->reg[22];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr23_pc_delay(void)
+{
+ env->pc_delay = env->reg[23];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr24_pc_delay(void)
+{
+ env->pc_delay = env->reg[24];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr25_pc_delay(void)
+{
+ env->pc_delay = env->reg[25];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr26_pc_delay(void)
+{
+ env->pc_delay = env->reg[26];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr27_pc_delay(void)
+{
+ env->pc_delay = env->reg[27];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr28_pc_delay(void)
+{
+ env->pc_delay = env->reg[28];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr29_pc_delay(void)
+{
+ env->pc_delay = env->reg[29];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr30_pc_delay(void)
+{
+ env->pc_delay = env->reg[30];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr31_pc_delay(void)
+{
+ env->pc_delay = env->reg[31];
+ env->delay_insn = 1;
+}
+
+#define OP_FILE "op-1t-op.h"
+#include "op-1t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-2t-op.h"
+#include "op-2t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-3t-op.h"
+#include "op-3t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-arith-op.h"
+#define OP_EXTRA
+
+#define OP /
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME div
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP /
+#define OP_CAST(x) (x)
+#define OP_NAME divu
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP *
+#define OP_CAST(x) (x)
+#define OP_NAME mulu
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP -
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME sub
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+
+#define OP_EXTRA + ((env->sprs[SPR_SR] & SPR_SR_CY) >> 10)
+#define OP +
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME addc
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+#define OP_EXTRA
+
+#define OP +
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME add
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP &
+#define OP_CAST(x) (x)
+#define OP_NAME and
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP *
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME mul
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP |
+#define OP_CAST(x) (x)
+#define OP_NAME or
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP <<
+#define OP_CAST(x) (x)
+#define OP_NAME sll
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP >>
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME sra
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP >>
+#define OP_CAST(x) (x)
+#define OP_NAME srl
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP ^
+#define OP_CAST(x) (x)
+#define OP_NAME xor
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+#undef OP_FILE
+
+#define OP_FILE "op-extend-op.h"
+
+#define EXT_NAME extbs
+#define EXT_TYPE int8_t
+#define EXT_CAST (orreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME extbz
+#define EXT_TYPE uint8_t
+#define EXT_CAST (uorreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME exths
+#define EXT_TYPE int16_t
+#define EXT_CAST (orreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME exthz
+#define EXT_TYPE uint16_t
+#define EXT_CAST (uorreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#undef OP_FILE
+
+#define OP_FILE "op-comp-op.h"
+
+#define COMP ==
+#define COMP_NAME sfeq
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP !=
+#define COMP_NAME sfne
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >
+#define COMP_NAME sfgtu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >=
+#define COMP_NAME sfgeu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <
+#define COMP_NAME sfltu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <=
+#define COMP_NAME sfleu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >
+#define COMP_NAME sfgts
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >=
+#define COMP_NAME sfges
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <
+#define COMP_NAME sflts
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <=
+#define COMP_NAME sfles
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#undef OP_FILE
+
+#define OP_FILE "op-t-reg-mov-op.h"
+#include "op-1t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-mftspr-op.h"
+#include "op-1t.h"
+#include "op-2t.h"
+#undef OP_FILE
+#include "op-mftspr-op.h"
+
+#define OP_FILE "op-mac-op.h"
+
+#define OP +=
+#define OP_NAME mac
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP
+
+#define OP -=
+#define OP_NAME msb
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP
+
+#undef OP_FILE
+
+#define OP_FILE "op-lwhb-op.h"
+
+#define LS_OP_NAME lbz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem8
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lbs
+#define LS_OP_CAST (int8_t)
+#define LS_OP_FUNC eval_mem8
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lhz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem16
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lhs
+#define LS_OP_CAST (int16_t)
+#define LS_OP_FUNC eval_mem16
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lwz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem32
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lws
+#define LS_OP_CAST (int32_t)
+#define LS_OP_FUNC eval_mem32
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#undef OP_FILE
+
+#define OP_FILE "op-swhb-op.h"
+
+#define S_OP_NAME sb
+#define S_FUNC set_mem8
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+#define S_OP_NAME sh
+#define S_FUNC set_mem16
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+#define S_OP_NAME sw
+#define S_FUNC set_mem32
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+__or_dynop void op_join_mem_cycles(void)
+{
+ runtime.sim.cycles += runtime.sim.mem_cycles;
+ scheduler.job_queue->time -= runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = 0;
+}
+
+__or_dynop void op_store_link_addr_gpr(void)
+{
+ env->reg[LINK_REGNO] = env->pc + 8;
+}
+
+__or_dynop void op_prep_rfe(void)
+{
+ env->sprs[SPR_SR] = env->sprs[SPR_ESR_BASE] | SPR_SR_FO;
+ env->sprs[SPR_PPC] = env->pc;
+ env->pc = env->sprs[SPR_EPCR_BASE] - 4;
+}
+
+static inline void prep_except(oraddr_t epcr_base)
+{
+ env->sprs[SPR_EPCR_BASE] = epcr_base;
+
+ env->sprs[SPR_ESR_BASE] = env->sprs[SPR_SR];
+
+ /* Address translation is always disabled when starting exception. */
+ env->sprs[SPR_SR] &= ~SPR_SR_DME;
+ env->sprs[SPR_SR] &= ~SPR_SR_IME;
+
+ env->sprs[SPR_SR] &= ~SPR_SR_OVE; /* Disable overflow flag exception. */
+
+ env->sprs[SPR_SR] |= SPR_SR_SM; /* SUPV mode */
+ env->sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */
+}
+
+/* Before the code in op_{sys,trap}{,_delay} gets run, the scheduler runs.
+ * Therefore the pc will point to the instruction after the l.sys or l.trap
+ * instruction */
+__or_dynop void op_prep_sys_delay(void)
+{
+ env->delay_insn = 0;
+ prep_except(env->pc - 4);
+ env->pc = EXCEPT_SYSCALL - 4;
+}
+
+__or_dynop void op_prep_sys(void)
+{
+ prep_except(env->pc + 4);
+ env->pc = EXCEPT_SYSCALL - 4;
+}
+
+__or_dynop void op_prep_trap_delay(void)
+{
+ env->delay_insn = 0;
+ prep_except(env->pc - 4);
+ env->pc = EXCEPT_TRAP - 4;
+}
+
+__or_dynop void op_prep_trap(void)
+{
+ prep_except(env->pc);
+ env->pc = EXCEPT_TRAP - 4;
+}
+
+/* FIXME: This `instruction' should be split up like the l.trap and l.sys
+ * instructions are done */
+__or_dynop void op_illegal_delay(void)
+{
+ env->delay_insn = 0;
+ env->sprs[SPR_EEAR_BASE] = env->pc - 4;
+ env->pc = EXCEPT_ILLEGAL - 4;
+}
+
+__or_dynop void op_illegal(void)
+{
+ env->sprs[SPR_EEAR_BASE] = env->pc;
+ env->pc = EXCEPT_ILLEGAL;
+}
+
+__or_dynop void op_do_sched(void)
+{
+ SPEEDY_CALL(do_sched_wrap);
+}
+
+__or_dynop void op_do_sched_delay(void)
+{
+ SPEEDY_CALL(do_sched_wrap_delay);
+}
+
+__or_dynop void op_macc(void)
+{
+ env->sprs[SPR_MACLO] = 0;
+ env->sprs[SPR_MACHI] = 0;
+}
+
+__or_dynop void op_store_insn_ea(void)
+{
+ env->insn_ea = OP_PARAM1;
+}
+
op.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: sched-i386.h
===================================================================
--- sched-i386.h (nonexistent)
+++ sched-i386.h (revision 388)
@@ -0,0 +1,40 @@
+/* sched-i386.h -- i386 specific support routines for the scheduler
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Sets the cycle counter to a specific value */
+static void set_sched_cycle(int32_t job_time)
+{
+ union {
+ uint64_t val64;
+ union {
+ uint32_t low32;
+ uint32_t high32;
+ } val3232;
+ } time_pc;
+
+ asm("movq %%mm0, %0\n"
+ "\tmovl %2, %1\n"
+ "\tmovq %3, %%mm0\n"
+ : "=m" (time_pc.val64),
+ "=m" (time_pc.val3232.low32)
+ : "r" (job_time),
+ "m" (time_pc.val64));
+}
+
sched-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn32-defs.h
===================================================================
--- dyn32-defs.h (nonexistent)
+++ dyn32-defs.h (revision 388)
@@ -0,0 +1,139 @@
+/* dyn32-defs.h -- Definitions for the dynamic execution model
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef DYN32_DEFS__H
+#define DYN32_DEFS__H
+
+
+/* Package includes */
+#include "arch.h"
+
+
+struct op_queue {
+ unsigned int num_ops;
+ unsigned int ops_len;
+ unsigned int *ops;
+ unsigned int num_ops_param;
+ unsigned int ops_param_len;
+ unsigned int *ops_param;
+ unsigned int jump_local; /* Parameter index that holds the location of the jump */
+ oraddr_t jump_local_loc; /* Location to jump to (relative to start of page */
+ unsigned int not_jump_loc; /* Location to jump if not jumping (l.bf/l.bnf) */
+ int xref; /* Is this location cross referenced? */
+ oraddr_t insn_addr; /* Physical address of the instruction */
+ unsigned int reg_t[3]; /* Which registers are in the temporaries (after the instruction)? */
+ unsigned int tflags[3];
+
+ int insn_index;
+ unsigned int param_type[5]; /* opd->type */
+ orreg_t param[5]; /* Value of operand */
+ unsigned int param_num; /* Number of operands */
+ uint32_t insn; /* Instruction word */
+
+ struct op_queue *prev;
+ struct op_queue *next;
+};
+
+void gen_l_add PARAMS((struct op_queue *, int *, int));
+void gen_l_addc PARAMS((struct op_queue *, int *, int));
+void gen_l_and PARAMS((struct op_queue *, int *, int));
+void gen_l_bf PARAMS((struct op_queue *, int *, int));
+void gen_l_bnf PARAMS((struct op_queue *, int *, int));
+void gen_l_cmov PARAMS((struct op_queue *, int *, int));
+void gen_l_cust1 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust2 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust3 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust4 PARAMS((struct op_queue *, int *, int));
+void gen_l_div PARAMS((struct op_queue *, int *, int));
+void gen_l_divu PARAMS((struct op_queue *, int *, int));
+void gen_l_extbs PARAMS((struct op_queue *, int *, int));
+void gen_l_extbz PARAMS((struct op_queue *, int *, int));
+void gen_l_exths PARAMS((struct op_queue *, int *, int));
+void gen_l_exthz PARAMS((struct op_queue *, int *, int));
+void gen_l_extws PARAMS((struct op_queue *, int *, int));
+void gen_l_extwz PARAMS((struct op_queue *, int *, int));
+void gen_l_ff1 PARAMS((struct op_queue *, int *, int));
+void gen_l_j PARAMS((struct op_queue *, int *, int));
+void gen_l_jal PARAMS((struct op_queue *, int *, int));
+void gen_l_jr PARAMS((struct op_queue *, int *, int));
+void gen_l_jalr PARAMS((struct op_queue *, int *, int));
+void gen_l_lbs PARAMS((struct op_queue *, int *, int));
+void gen_l_lbz PARAMS((struct op_queue *, int *, int));
+void gen_l_lhs PARAMS((struct op_queue *, int *, int));
+void gen_l_lhz PARAMS((struct op_queue *, int *, int));
+void gen_l_lws PARAMS((struct op_queue *, int *, int));
+void gen_l_lwz PARAMS((struct op_queue *, int *, int));
+void gen_l_mac PARAMS((struct op_queue *, int *, int));
+void gen_l_macrc PARAMS((struct op_queue *, int *, int));
+void gen_l_mfspr PARAMS((struct op_queue *, int *, int));
+void gen_l_movhi PARAMS((struct op_queue *, int *, int));
+void gen_l_msb PARAMS((struct op_queue *, int *, int));
+void gen_l_mtspr PARAMS((struct op_queue *, int *, int));
+void gen_l_mul PARAMS((struct op_queue *, int *, int));
+void gen_l_mulu PARAMS((struct op_queue *, int *, int));
+void gen_l_nop PARAMS((struct op_queue *, int *, int));
+void gen_l_or PARAMS((struct op_queue *, int *, int));
+void gen_l_rfe PARAMS((struct op_queue *, int *, int));
+void gen_l_sb PARAMS((struct op_queue *, int *, int));
+void gen_l_sh PARAMS((struct op_queue *, int *, int));
+void gen_l_sw PARAMS((struct op_queue *, int *, int));
+void gen_l_sfeq PARAMS((struct op_queue *, int *, int));
+void gen_l_sfges PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgeu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgts PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgtu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfles PARAMS((struct op_queue *, int *, int));
+void gen_l_sfleu PARAMS((struct op_queue *, int *, int));
+void gen_l_sflts PARAMS((struct op_queue *, int *, int));
+void gen_l_sfltu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfne PARAMS((struct op_queue *, int *, int));
+void gen_l_sll PARAMS((struct op_queue *, int *, int));
+void gen_l_sra PARAMS((struct op_queue *, int *, int));
+void gen_l_srl PARAMS((struct op_queue *, int *, int));
+void gen_l_sub PARAMS((struct op_queue *, int *, int));
+void gen_l_sys PARAMS((struct op_queue *, int *, int));
+void gen_l_trap PARAMS((struct op_queue *, int *, int));
+void gen_l_xor PARAMS((struct op_queue *, int *, int));
+void gen_l_invalid PARAMS((struct op_queue *, int *, int));
+
+void gen_lf_add_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_div_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_ftoi_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_itof_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_madd_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_mul_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_rem_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfeq_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfge_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfgt_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfle_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sflt_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfne_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sub_s PARAMS((struct op_queue *, int *, int));
+void l_none(struct op_queue *opq, int *param_t, int delay_slot);
+
+#endif /* DYN32_DEFS__H */
+
dyn32-defs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-support.c
===================================================================
--- op-support.c (nonexistent)
+++ op-support.c (revision 388)
@@ -0,0 +1,114 @@
+/* op-support.c -- Support routines for micro operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "opcode/or32.h"
+#include "sim-config.h"
+#include "spr-defs.h"
+#include "except.h"
+#include "immu.h"
+#include "abstract.h"
+#include "execute.h"
+#include "sched.h"
+#include "i386-regs.h"
+#include "dyn-rec.h"
+#include "op-support.h"
+#include "simprintf.h"
+
+
+/* Stuff that is really a `micro' operation but is rather big (or for some other
+ * reason like calling exit()) */
+
+void op_support_nop_exit(void)
+{
+ PRINTF("exit(%"PRIdREG")\n", cpu_state.reg[3]);
+ fprintf(stderr, "@reset : cycles %lld, insn #%lld\n",
+ runtime.sim.reset_cycles, runtime.cpu.reset_instructions);
+ fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles,
+ runtime.cpu.instructions);
+ fprintf(stderr, " diff : cycles %lld, insn #%lld\n",
+ runtime.sim.cycles - runtime.sim.reset_cycles,
+ runtime.cpu.instructions - runtime.cpu.reset_instructions);
+ /* FIXME: Implement emulation of a stalled cpu
+ if (config.debug.gdb_enabled)
+ set_stall_state (1);
+ else {
+ handle_sim_command();
+ sim_done();
+ }
+ */
+ exit(0);
+}
+
+void op_support_nop_reset(void)
+{
+ PRINTF("****************** counters reset ******************\n");
+ PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
+ PRINTF("****************** counters reset ******************\n");
+ runtime.sim.reset_cycles = runtime.sim.cycles;
+ runtime.cpu.reset_instructions = runtime.cpu.instructions;
+}
+
+void op_support_nop_printf(void)
+{
+ simprintf(cpu_state.reg[4], cpu_state.reg[3]);
+}
+
+void op_support_nop_report(void)
+{
+ PRINTF("report(0x%"PRIxREG");\n", cpu_state.reg[3]);
+}
+
+void op_support_nop_report_imm(int imm)
+{
+ PRINTF("report %i (0x%"PRIxREG");\n", imm, cpu_state.reg[3]);
+}
+
+/* Handles a jump */
+/* addr is a VIRTUAL address */
+/* NOTE: We can't use env since this code is compiled like the rest of the
+ * simulator (most likely without -fomit-frame-pointer) and thus env will point
+ * to some bogus value. */
+void do_jump(oraddr_t addr)
+{
+ cpu_state.pc = addr;
+ longjmp(cpu_state.excpt_loc, 0);
+}
+
+/* Wrapper around analysis() that contains all the recompiler specific stuff */
+void op_support_analysis(void)
+{
+ oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
+ runtime.cpu.instructions++;
+ cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
+ cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
+ cpu_state.iqueue.insn_addr = cpu_state.pc;
+ analysis(&cpu_state.iqueue);
+}
+
op-support.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-lwhb-op.h
===================================================================
--- op-lwhb-op.h (nonexistent)
+++ op-lwhb-op.h (revision 388)
@@ -0,0 +1,38 @@
+/* op-lwhb-op.h -- Micro operations template for load operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* FIXME: Do something if a breakpoint is hit */
+
+#ifdef OP_2T
+__or_dynop void glue(glue(op_, LS_OP_NAME), T)(void)
+{
+ int breakpoint;
+ T0 = LS_OP_CAST LS_OP_FUNC(T1 + OP_PARAM1, &breakpoint);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue(glue(glue(op_, LS_OP_NAME), _imm), T)(void)
+{
+ int breakpoint;
+ T0 = LS_OP_CAST LS_OP_FUNC(OP_PARAM1, &breakpoint);
+}
+#endif
+
op-lwhb-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-comp-op.h
===================================================================
--- op-comp-op.h (nonexistent)
+++ op-comp-op.h (revision 388)
@@ -0,0 +1,50 @@
+/* op-comp-op.h -- Micro operations template for comparison operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef OP_2T
+__or_dynop void glue(glue(op_, COMP_NAME), T)(void)
+{
+ if(COMP_CAST(T0) COMP COMP_CAST(T1))
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue(glue(glue(op_, COMP_NAME), _imm), T)(void)
+{
+ if(COMP_CAST(T0) COMP COMP_CAST(OP_PARAM1))
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+
+__or_dynop void glue(glue(glue(op_, COMP_NAME), _null), T)(void)
+{
+ if(COMP_CAST(T0) COMP 0)
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+#endif
+
op-comp-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: .cvsignore
===================================================================
--- .cvsignore (nonexistent)
+++ .cvsignore (revision 388)
@@ -0,0 +1,3 @@
+Makefile
+.deps
+generate
Index: op-support.h
===================================================================
--- op-support.h (nonexistent)
+++ op-support.h (revision 388)
@@ -0,0 +1,28 @@
+/* op-support.h -- Definitions of support routines for operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+void op_support_nop_exit(void);
+void op_support_nop_reset(void);
+void op_support_nop_printf(void);
+void op_support_nop_report(void);
+void op_support_nop_report_imm(int imm);
+void op_support_analysis(void);
+void do_jump(oraddr_t addr);
+
+void upd_reg_from_t(oraddr_t pc, int bound);
op-support.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-swhb-op.h
===================================================================
--- op-swhb-op.h (nonexistent)
+++ op-swhb-op.h (revision 388)
@@ -0,0 +1,57 @@
+/* op-swhb-op.h -- Micro operations template for store operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+/* FIXME: Do something with breakpoint */
+
+
+#ifdef OP_2T
+__or_dynop void glue (glue (op_, S_OP_NAME), T) (void)
+{
+ int breakpoint;
+ S_FUNC (T0 + OP_PARAM1, T1, &breakpoint);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (glue (glue (op_, S_OP_NAME), _imm), T) (void)
+{
+ int breakpoint;
+ S_FUNC (OP_PARAM1, T0, &breakpoint);
+}
+
+__or_dynop void glue (glue (glue (op_, S_OP_NAME), _clear), T) (void)
+{
+ int breakpoint;
+ S_FUNC (T0 + OP_PARAM1, 0, &breakpoint);
+}
+#endif
+
+#if !defined(OP_1T) && !defined(OP_2T)
+__or_dynop void glue (glue (op_, S_OP_NAME), _clear_imm) (void)
+{
+ int breakpoint;
+ S_FUNC (OP_PARAM1, 0, &breakpoint);
+}
+#endif
op-swhb-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn-rec.c
===================================================================
--- dyn-rec.c (nonexistent)
+++ dyn-rec.c (revision 388)
@@ -0,0 +1,2451 @@
+/* dyn-rec.c -- Dynamic recompiler implementation for or32
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "immu.h"
+#include "abstract.h"
+#include "opcode/or32.h"
+#include "spr-defs.h"
+#include "execute.h"
+#include "except.h"
+#include "spr-defs.h"
+#include "sim-config.h"
+#include "sched.h"
+#include "i386-regs.h"
+#include "def-op-t.h"
+#include "dyn-rec.h"
+#include "gen-ops.h"
+#include "op-support.h"
+#include "toplevel-support.h"
+
+
+/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
+
+/* FIXME: Optimise sorted list adding */
+
+typedef void (*generic_gen_op)(struct op_queue *opq, int end);
+typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
+
+void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot);
+
+/* ttg->temporary to gpr */
+DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr);
+/* gtt->gpr to temporary */
+DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr);
+
+DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea);
+
+/* Linker stubs. This will allow the linker to link in op.o. The relocations
+ * that the linker does for these will be irrelevent anyway, since we patch the
+ * relocations during recompilation. */
+uorreg_t __op_param1;
+uorreg_t __op_param2;
+uorreg_t __op_param3;
+
+/* The number of bytes that a dynamicly recompiled page should be enlarged by */
+#define RECED_PAGE_ENLARGE_BY 51200
+
+/* The number of entries that the micro operations array in op_queue should be
+ * enlarged by */
+#define OPS_ENLARGE_BY 5
+
+#define T_NONE (-1)
+
+/* Temporary is used as a source operand */
+#define TFLAG_SRC 1
+/* Temporary is used as a destination operand */
+#define TFLAG_DST 2
+/* Temporary has been saved to permanent storage */
+#define TFLAG_SAVED 4
+/* Temporary contains the value of the register before the instruction execution
+ * occurs (either by an explicit reg->t move or implicitly being left over from
+ * a previous instruction) */
+#define TFLAG_SOURCED 8
+
+/* FIXME: Put this into some header */
+extern int do_stats;
+
+static int sigsegv_state = 0;
+static void *sigsegv_addr = NULL;
+
+void dyn_ret_stack_prot(void);
+
+void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
+{
+ struct dyn_page *dp;
+ FILE *f;
+ char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
+ int i;
+ struct sigcontext *sigc = dat;
+
+ if(!sigsegv_state) {
+ sigsegv_addr = siginf->si_addr;
+ } else {
+ fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n");
+ sigsegv_state++;
+ }
+
+ /* First dump all the data that does not need dereferenceing to get */
+ switch(sigsegv_state) {
+ case 0:
+ fflush(stderr);
+ fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n",
+ sigsegv_addr, sigc->eip, cpu_state.pc);
+ sigsegv_state++;
+ case 1:
+ /* Run through the recompiled pages, dumping them to disk as we go */
+ for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) {
+ dp = cpu_state.dyn_pages[i];
+ if(!dp)
+ continue;
+ fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
+ dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
+ dp->host_len);
+ fflush(stdout);
+
+ sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
+ if(!(f = fopen(filen, "w"))) {
+ fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
+ filen, strerror(errno));
+ continue;
+ }
+ if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
+ fprintf(stderr, "Unable to write recompiled data to file: %s\n",
+ strerror(errno));
+
+ fclose(f);
+ }
+ sigsegv_state++;
+ case 2:
+ sim_done();
+ }
+}
+
+struct dyn_page *new_dp(oraddr_t page)
+{
+ struct dyn_page *dp = malloc(sizeof(struct dyn_page));
+ dp->or_page = IADDR_PAGE(page);
+
+ dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4));
+
+ dp->host_len = 0;
+ dp->host_page = NULL;
+ dp->dirty = 1;
+
+ if(do_stats) {
+ dp->insns = malloc(immu_state->pagesize);
+ dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4));
+ }
+
+ cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp;
+ return dp;
+}
+
+void dyn_main(void)
+{
+ struct dyn_page *target_dp;
+ oraddr_t phys_page;
+
+ setjmp(cpu_state.excpt_loc);
+ for(;;) {
+ phys_page = immu_translate(cpu_state.pc);
+
+/*
+ printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
+ phys_page, cpu_state.sprs[SPR_PPC] - 4);
+*/
+
+ /* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
+ * it to the cycles when the instruction is executed so if we don't reset it
+ * now it will produce wrong results */
+ runtime.sim.mem_cycles = 0;
+
+ target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2];
+
+ if(!target_dp)
+ target_dp = new_dp(phys_page);
+
+ /* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
+ * 0x0 page if the jump is to that location */
+ if(phys_page < 0x100)
+ target_dp->dirty = 1;
+
+ if(target_dp->dirty)
+ recompile_page(target_dp);
+
+ cpu_state.curr_page = target_dp;
+
+ /* FIXME: If the page is backed by more than one type of memory, this will
+ * produce wrong results */
+ cpu_state.cycles_dec = target_dp->delayr;
+ if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
+ /* Add the mmu hit delay to the cycle counter */
+ cpu_state.cycles_dec -= immu_state->hitdelay;
+
+ /* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
+ * calls but the recompiled code trashes them... */
+ enter_dyn_code(phys_page, target_dp);
+ }
+}
+
+static void immu_retranslate(void *dat)
+{
+ int got_en_dis = (int)dat;
+ immu_translate(cpu_state.pc);
+ runtime.sim.mem_cycles = 0;
+
+ /* Only update the cycle decrementer if the mmu got enabled or disabled */
+ if(got_en_dis == IMMU_GOT_ENABLED)
+ /* Add the mmu hit delay to the cycle counter */
+ cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay;
+ else if(got_en_dis == IMMU_GOT_DISABLED)
+ cpu_state.cycles_dec = cpu_state.curr_page->delayr;
+}
+
+/* This is called whenever the immu is either enabled/disabled or reconfigured
+ * while enabled. This checks if an itlb miss would occour and updates the immu
+ * hit delay counter */
+void recheck_immu(int got_en_dis)
+{
+ oraddr_t addr;
+
+ if(cpu_state.delay_insn)
+ addr = cpu_state.pc_delay;
+ else
+ addr = cpu_state.pc + 4;
+
+ if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr))
+ /* Schedule a job to do immu_translate() */
+ SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0);
+}
+
+/* Runs the scheduler. Called from except_handler (and dirtyfy_page below) */
+void run_sched_out_of_line(void)
+{
+ oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
+
+ if(do_stats) {
+ cpu_state.iqueue.insn_addr = cpu_state.pc;
+ cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
+ cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
+ runtime.cpu.instructions++;
+ analysis(&cpu_state.iqueue);
+ }
+
+ /* Run the scheduler */
+ scheduler.job_queue->time += cpu_state.cycles_dec;
+ runtime.sim.cycles -= cpu_state.cycles_dec;
+
+ op_join_mem_cycles();
+ if(scheduler.job_queue->time <= 0)
+ do_scheduler();
+}
+
+/* Signals a page as dirty */
+static void dirtyfy_page(struct dyn_page *dp)
+{
+ oraddr_t check;
+
+ printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
+
+ dp->dirty = 1;
+
+ /* If the execution is currently in the page that was touched then recompile
+ * it now and jump back to the point of execution */
+ check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4;
+ if(IADDR_PAGE(check) == dp->or_page) {
+ run_sched_out_of_line();
+ recompile_page(dp);
+
+ cpu_state.delay_insn = 0;
+
+ /* Jump out to the next instruction */
+ do_jump(check);
+ }
+}
+
+/* Checks to see if a write happened to a recompiled page. If so marks it as
+ * dirty */
+void dyn_checkwrite(oraddr_t addr)
+{
+ /* FIXME: Do this with mprotect() */
+ struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2];
+
+ /* Since the locations 0x0-0xff are nearly always written to in an exception
+ * handler, ignore any writes to these locations. If code ends up jumping
+ * out there, we'll recompile when the jump actually happens. */
+ if((addr > 0x100) && dp && !dp->dirty)
+ dirtyfy_page(dp);
+}
+
+/* Moves the temprary t to its permanent storage if it has been used as a
+ * destination register */
+static void ship_t_out(struct op_queue *opq, unsigned int t)
+{
+ unsigned int gpr = opq->reg_t[t];
+
+ for(; opq; opq = opq->prev) {
+ if(opq->reg_t[t] != gpr)
+ return;
+ if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) {
+ opq->tflags[t] |= TFLAG_SAVED;
+
+ /* FIXME: Check if this is still neccesary */
+ /* Before takeing the temporaries out, temporarily remove the op_do_sched
+ * operation such that dyn_page->ts_bound shall be correct before the
+ * scheduler runs */
+ if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
+ opq->num_ops--;
+ gen_op_move_gpr_t[t][gpr](opq, 1);
+ gen_op_do_sched(opq, 1);
+ return;
+ }
+
+ gen_op_move_gpr_t[t][gpr](opq, 1);
+
+ return;
+ }
+ }
+}
+
+static void ship_gprs_out_t(struct op_queue *opq)
+{
+ int i;
+
+ if(!opq)
+ return;
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] < 32)
+ /* Ship temporaries out in the last opq that actually touched it */
+ ship_t_out(opq, i);
+ }
+}
+
+/* FIXME: Look at the following instructions to make a better guess at which
+ * temporary to return */
+static int find_t(struct op_queue *opq, unsigned int reg)
+{
+ int i, j, t = -1;
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == reg)
+ return i;
+
+ /* Ok, we have found an as-yet unused temporary, check if it is needed
+ * later in this instruction */
+ for(j = 0; j < opq->param_num; j++) {
+ if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i]))
+ break;
+ }
+
+ if(j != opq->param_num)
+ continue;
+
+ /* We have found the temporary (temporarily:) fit for use */
+ if((t == -1) || (opq->reg_t[i] == 32))
+ t = i;
+ }
+
+ return t;
+}
+
+/* Checks if there is enough space in dp->host_page, if not grow it */
+void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
+ unsigned int amount)
+{
+ unsigned int used = cur - dp->host_page;
+
+ /* The array is long enough */
+ if((used + amount) <= *len)
+ return cur;
+
+ /* Reallocate */
+ *len += RECED_PAGE_ENLARGE_BY;
+
+ if(!(dp->host_page = realloc(dp->host_page, *len))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+
+ return dp->host_page + used;
+}
+
+/* Adds an operation to the opq */
+void add_to_opq(struct op_queue *opq, int end, int op)
+{
+ if(opq->num_ops == opq->ops_len) {
+ opq->ops_len += OPS_ENLARGE_BY;
+ if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ }
+
+ if(end)
+ opq->ops[opq->num_ops] = op;
+ else {
+ /* Shift everything over by one */
+ memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
+ opq->ops[0] = op;
+ }
+
+ opq->num_ops++;
+}
+
+static void gen_op_mark_loc(struct op_queue *opq, int end)
+{
+ add_to_opq(opq, end, op_mark_loc_indx);
+}
+
+/* Adds a parameter to the opq */
+void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
+{
+ if(opq->num_ops_param == opq->ops_param_len) {
+ opq->ops_param_len += OPS_ENLARGE_BY;
+ if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ }
+
+ if(end)
+ opq->ops_param[opq->num_ops_param] = param;
+ else {
+ /* Shift everything over by one */
+ memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
+ opq->ops_param[0] = param;
+ }
+
+ opq->num_ops_param++;
+}
+
+/* Initialises the recompiler */
+void init_dyn_recomp(void)
+{
+ struct sigaction sigact;
+ struct op_queue *opq = NULL;
+ unsigned int i;
+
+ cpu_state.opqs = NULL;
+
+ /* Allocate the operation queue list (+1 for the page chaining) */
+ for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) {
+ if(!(opq = malloc(sizeof(struct op_queue)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+
+ /* initialise some fields */
+ opq->ops_len = 0;
+ opq->ops = NULL;
+ opq->ops_param_len = 0;
+ opq->ops_param = NULL;
+ opq->xref = 0;
+
+ if(cpu_state.opqs)
+ cpu_state.opqs->prev = opq;
+
+ opq->next = cpu_state.opqs;
+ cpu_state.opqs = opq;
+ }
+
+ opq->prev = NULL;
+
+ cpu_state.curr_page = NULL;
+ if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
+ immu_state->pagesize_log2))))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ memset(cpu_state.dyn_pages, 0,
+ sizeof(void *) * (2 << (32 - immu_state->pagesize_log2)));
+
+ /* Register our segmentation fault handler */
+ sigact.sa_sigaction = dyn_sigsegv_debug;
+ memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
+ sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
+ if(sigaction(SIGSEGV, &sigact, NULL))
+ printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
+
+ /* FIXME: Find a better place for this */
+ { /* Needed by execution */
+ extern int do_stats;
+ do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
+ || config.sim.history || config.sim.exe_log;
+ }
+
+ printf("Recompile engine up and running\n");
+}
+
+/* Parses instructions and their operands and populates opq with them */
+static void eval_insn_ops(struct op_queue *opq, oraddr_t addr)
+{
+ int breakp;
+ struct insn_op_struct *opd;
+
+ for(; opq->next; opq = opq->next, addr += 4) {
+ opq->param_num = 0;
+ breakp = 0;
+ opq->insn = eval_insn(addr, &breakp);
+
+ /* FIXME: If a breakpoint is set at this location, insert exception code */
+ if(breakp) {
+ fprintf(stderr, "FIXME: Insert breakpoint code\n");
+ }
+
+ opq->insn_index = insn_decode(opq->insn);
+
+ if(opq->insn_index == -1)
+ continue;
+
+ opd = op_start[opq->insn_index];
+
+ do {
+ opq->param[opq->param_num] = eval_operand_val(opq->insn, opd);
+ opq->param_type[opq->param_num] = opd->type;
+
+ opq->param_num++;
+ while(!(opd->type & OPTYPE_OP)) opd++;
+ } while(!(opd++->type & OPTYPE_LAST));
+ }
+}
+
+/* Adds code to the opq for the instruction pointed to by addr */
+static void recompile_insn(struct op_queue *opq, int delay_insn)
+{
+ int j, k;
+ int param_t[5]; /* Which temporary the parameters reside in */
+
+ /* Check if we have an illegal instruction */
+ if(opq->insn_index == -1) {
+ gen_l_invalid(opq, NULL, delay_insn);
+ return;
+ }
+
+ /* If we are recompileing an instruction that has a delay slot and is in the
+ * delay slot, ignore it. This is undefined behavour. */
+ if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY))
+ return;
+
+ param_t[0] = T_NONE;
+ param_t[1] = T_NONE;
+ param_t[2] = T_NONE;
+ param_t[3] = T_NONE;
+ param_t[4] = T_NONE;
+
+ /* Jump instructions are special since they have a delay slot and thus they
+ * need to control the exact operation sequence. Special case these here to
+ * avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */
+ if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) {
+ /* Jump instructions don't have a disposition */
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+
+ /* Analysis is done by the individual jump instructions */
+ /* Jump instructions don't touch runtime.sim.mem_cycles */
+ /* Jump instructions run their own scheduler */
+ return;
+ }
+
+ /* Before an exception takes place, all registers must be stored. */
+ if((or32_opcodes[opq->insn_index].func_unit == it_exception)) {
+ ship_gprs_out_t(opq);
+
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+ return;
+ }
+
+ for(j = 0; j < opq->param_num; j++) {
+ if(!(opq->param_type[j] & OPTYPE_REG))
+ continue;
+
+ /* Never, ever, move r0 into a temporary */
+ if(!opq->param[j])
+ continue;
+
+ k = find_t(opq, opq->param[j]);
+
+ param_t[j] = k;
+
+ if(opq->reg_t[k] == opq->param[j]) {
+ if(!(opq->param_type[j] & OPTYPE_DST) &&
+ !(opq->tflags[k] & TFLAG_SOURCED)) {
+ gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
+ opq->tflags[k] |= TFLAG_SOURCED;
+ }
+
+ if(opq->param_type[j] & OPTYPE_DST)
+ opq->tflags[k] |= TFLAG_DST;
+ else
+ opq->tflags[k] |= TFLAG_SRC;
+
+ continue;
+ }
+
+ if(opq->reg_t[k] < 32) {
+ /* Only ship the temporary out if it has been used as a destination
+ * register */
+ ship_t_out(opq, k);
+ }
+
+ if(opq->param_type[j] & OPTYPE_DST)
+ opq->tflags[k] = TFLAG_DST;
+ else
+ opq->tflags[k] = TFLAG_SRC;
+
+ opq->reg_t[k] = opq->param[j];
+
+ /* Only generate code to move the register into a temporary if it is used as
+ * a source operand */
+ if(!(opq->param_type[j] & OPTYPE_DST)) {
+ gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
+ opq->tflags[k] |= TFLAG_SOURCED;
+ }
+ }
+
+ /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
+ * effective address needs to be calculated before the instruction is
+ * simulated */
+ if(do_stats) {
+ for(j = 0; j < opq->param_num; j++) {
+ if(!(opq->param_type[j] & OPTYPE_DIS))
+ continue;
+
+ if(!opq->param[j + 1])
+ gen_op_store_insn_ea(opq, 1, opq->param[j]);
+ else
+ calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]);
+ }
+ }
+
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+
+ if(do_stats) {
+ ship_gprs_out_t(opq);
+ gen_op_analysis(opq, 1);
+ }
+
+ /* The call to join_mem_cycles() could be put into the individual operations
+ * that emulate the load/store instructions, but then it would be added to
+ * the cycle counter before analysis() is called, which is not how the complex
+ * execution model does it. */
+ if((or32_opcodes[opq->insn_index].func_unit == it_load) ||
+ (or32_opcodes[opq->insn_index].func_unit == it_store))
+ gen_op_join_mem_cycles(opq, 1);
+
+ /* Delay slot instructions get a special scheduler, thus don't generate it
+ * here */
+ if(!delay_insn)
+ gen_op_do_sched(opq, 1);
+}
+
+/* Recompiles the page associated with *dyn */
+void recompile_page(struct dyn_page *dyn)
+{
+ unsigned int j;
+ struct op_queue *opq = cpu_state.opqs;
+ oraddr_t rec_addr = dyn->or_page;
+ oraddr_t rec_page = dyn->or_page;
+ void **loc;
+
+ /* The start of the next page */
+ rec_page += immu_state->pagesize;
+
+ printf("Recompileing page %"PRIxADDR"\n", rec_addr);
+ fflush(stdout);
+
+ /* Mark all temporaries as not containing a register */
+ for(j = 0; j < NUM_T_REGS; j++) {
+ opq->reg_t[j] = 32; /* Out-of-range registers */
+ opq->tflags[j] = 0;
+ }
+
+ dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr;
+
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+
+ eval_insn_ops(opq, rec_addr);
+
+ /* Insert code to check if the first instruction is exeucted in a delay slot*/
+ gen_op_check_delay_slot(opq, 1, 0);
+ recompile_insn(opq, 1);
+ ship_gprs_out_t(opq);
+ gen_op_do_sched_delay(opq, 1);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_jump_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+ gen_op_mark_loc(opq, 1);
+
+ for(j = 0; j < NUM_T_REGS; j++)
+ opq->reg_t[j] = 32; /* Out-of-range registers */
+
+ for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
+ if(opq->prev) {
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+ }
+ opq->jump_local = -1;
+ opq->not_jump_loc = -1;
+
+ opq->insn_addr = rec_addr;
+
+ for(j = 0; j < NUM_T_REGS; j++)
+ opq->tflags[j] = TFLAG_SOURCED;
+
+ /* Check if this location is cross referenced */
+ if(opq->xref) {
+ /* If the current address is cross-referenced, the temporaries shall be
+ * in an undefined state, so we must assume that no registers reside in
+ * them */
+ /* Ship out the current set of registers from the temporaries */
+ if(opq->prev) {
+ ship_gprs_out_t(opq->prev);
+ for(j = 0; j < NUM_T_REGS; j++) {
+ opq->reg_t[j] = 32;
+ opq->prev->reg_t[j] = 32;
+ }
+ }
+ }
+
+ recompile_insn(opq, 0);
+
+ /* Store the state of the temporaries */
+ memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
+ }
+
+ dyn->dirty = 0;
+
+ /* Ship temporaries out to the corrisponding registers */
+ ship_gprs_out_t(opq->prev);
+
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+ opq->not_jump_loc = -1;
+ opq->jump_local = -1;
+
+ /* Insert code to jump to the next page */
+ gen_op_do_jump(opq, 1);
+
+ /* Generate the code */
+ gen_code(cpu_state.opqs, dyn);
+
+ /* Fix up the locations */
+ for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++)
+ *loc += (unsigned int)dyn->host_page;
+
+ cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
+
+ /* Search for page-local jumps */
+ opq = cpu_state.opqs;
+ for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) {
+ if(opq->jump_local != -1)
+ opq->ops_param[opq->jump_local] =
+ (unsigned int)dyn->locs[opq->jump_local_loc >> 2];
+
+ if(opq->not_jump_loc != -1)
+ opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
+
+ /* Store the state of the temporaries into dyn->ts_bound */
+ dyn->ts_bound[j] = 0;
+ if(opq->reg_t[0] < 32)
+ dyn->ts_bound[j] = opq->reg_t[0];
+ if(opq->reg_t[1] < 32)
+ dyn->ts_bound[j] |= opq->reg_t[1] << 5;
+ if(opq->reg_t[2] < 32)
+ dyn->ts_bound[j] |= opq->reg_t[2] << 10;
+
+ /* Reset for the next page to be recompiled */
+ opq->xref = 0;
+ }
+
+ /* Patch the relocations */
+ patch_relocs(cpu_state.opqs, dyn->host_page);
+
+ if(do_stats) {
+ opq = cpu_state.opqs;
+ for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) {
+ dyn->insns[j] = opq->insn;
+ dyn->insn_indexs[j] = opq->insn_index;
+ }
+ }
+
+ /* FIXME: Fix the issue below in a more elegent way */
+ /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
+ * updated but the recompiler expectes it to start a 0, so reset it */
+ runtime.sim.mem_cycles = 0;
+}
+
+/* Recompiles a delay-slot instruction (opq is the opq of the instruction
+ * haveing the delay-slot) */
+static void recompile_delay_insn(struct op_queue *opq)
+{
+ struct op_queue delay_opq;
+ int i;
+
+ /* Setup a fake opq that looks very much like the delay slot instruction */
+ memcpy(&delay_opq, opq, sizeof(struct op_queue));
+ /* `Fix' a couple of bits */
+ for(i = 0; i < NUM_T_REGS; i++)
+ delay_opq.tflags[i] = TFLAG_SOURCED;
+ delay_opq.insn_index = opq->next->insn_index;
+ memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type));
+ memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param));
+ delay_opq.param_num = opq->next->param_num;
+ delay_opq.insn = opq->next->insn;
+
+ delay_opq.xref = 0;
+ delay_opq.insn_addr = opq->insn_addr + 4;
+ delay_opq.prev = opq->prev;
+ delay_opq.next = NULL;
+
+ /* Generate the delay slot instruction */
+ recompile_insn(&delay_opq, 1);
+
+ ship_gprs_out_t(&delay_opq);
+
+ opq->num_ops = delay_opq.num_ops;
+ opq->ops_len = delay_opq.ops_len;
+ opq->ops = delay_opq.ops;
+ opq->num_ops_param = delay_opq.num_ops_param;
+ opq->ops_param_len = delay_opq.ops_param_len;
+ opq->ops_param = delay_opq.ops_param;
+
+ for(i = 0; i < NUM_T_REGS; i++)
+ opq->reg_t[i] = 32;
+}
+
+/* Returns non-zero if the jump is into this page, 0 otherwise */
+static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
+{
+ int i;
+
+ /* Mark the jump as non page local if the delay slot instruction is on the
+ * next page to the jump instruction. This should not be needed */
+ if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr))
+ /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
+ * VIRTUAL offset and the next physical page may not be the next VIRTUAL
+ * page */
+ return 0;
+
+ /* The jump is into the page currently undergoing dynamic recompilation */
+
+ /* If we haven't got to the location of the jump, everything is ok */
+ if(j_ea > opq->insn_addr) {
+ /* Find the corissponding opq and mark it as cross referenced */
+ for(i = (j_ea - opq->insn_addr) / 4; i; i--)
+ opq = opq->next;
+ opq->xref = 1;
+ return 1;
+ }
+
+ /* Insert temporary -> register code before the jump ea and register ->
+ * temporary at the x-ref address */
+ for(i = (opq->insn_addr - j_ea) / 4; i; i--)
+ opq = opq->prev;
+
+ if(!opq->prev)
+ /* We're at the begining of a page, no need to do anything */
+ return 1;
+
+ /* Found location, insert code */
+
+ ship_gprs_out_t(opq->prev);
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->prev->reg_t[i] < 32)
+ /* FIXME: Ship temporaries in the begining of the opq that needs it */
+ gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0);
+ }
+
+ opq->xref = 1;
+
+ return 1;
+}
+
+static void gen_j_imm(struct op_queue *opq, oraddr_t off)
+{
+ int jump_local;
+
+ off <<= 2;
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_set_pc_delay_imm(opq, 1, off);
+ gen_op_do_sched(opq, 1);
+ return;
+ }
+
+ jump_local = find_jump_loc(opq->insn_addr + off, opq);
+
+ gen_op_set_delay_insn(opq, 1);
+ gen_op_do_sched(opq, 1);
+
+ recompile_delay_insn(opq);
+
+ gen_op_add_pc(opq, 1, (orreg_t)off - 8);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_sched_delay(opq, 1);
+
+ if(jump_local) {
+ gen_op_jmp_imm(opq, 1, 0);
+ opq->jump_local = opq->num_ops_param - 1;
+ opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask;
+ } else
+ gen_op_do_jump(opq, 1);
+}
+
+static const generic_gen_op set_pc_delay_gpr[32] = {
+ NULL,
+ gen_op_move_gpr1_pc_delay,
+ gen_op_move_gpr2_pc_delay,
+ gen_op_move_gpr3_pc_delay,
+ gen_op_move_gpr4_pc_delay,
+ gen_op_move_gpr5_pc_delay,
+ gen_op_move_gpr6_pc_delay,
+ gen_op_move_gpr7_pc_delay,
+ gen_op_move_gpr8_pc_delay,
+ gen_op_move_gpr9_pc_delay,
+ gen_op_move_gpr10_pc_delay,
+ gen_op_move_gpr11_pc_delay,
+ gen_op_move_gpr12_pc_delay,
+ gen_op_move_gpr13_pc_delay,
+ gen_op_move_gpr14_pc_delay,
+ gen_op_move_gpr15_pc_delay,
+ gen_op_move_gpr16_pc_delay,
+ gen_op_move_gpr17_pc_delay,
+ gen_op_move_gpr18_pc_delay,
+ gen_op_move_gpr19_pc_delay,
+ gen_op_move_gpr20_pc_delay,
+ gen_op_move_gpr21_pc_delay,
+ gen_op_move_gpr22_pc_delay,
+ gen_op_move_gpr23_pc_delay,
+ gen_op_move_gpr24_pc_delay,
+ gen_op_move_gpr25_pc_delay,
+ gen_op_move_gpr26_pc_delay,
+ gen_op_move_gpr27_pc_delay,
+ gen_op_move_gpr28_pc_delay,
+ gen_op_move_gpr29_pc_delay,
+ gen_op_move_gpr30_pc_delay,
+ gen_op_move_gpr31_pc_delay };
+
+static void gen_j_reg(struct op_queue *opq, unsigned int gpr)
+{
+ int i;
+
+ /* Ship the jump-to register out (if it exists). It requires special
+ * handleing */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == opq->param[0])
+ /* Ship temporary out in the last opq that used it */
+ ship_t_out(opq, i);
+ }
+
+ if(do_stats)
+ gen_op_analysis(opq, 1);
+
+ if(!gpr)
+ gen_op_clear_pc_delay(opq, 1);
+ else
+ set_pc_delay_gpr[gpr](opq, 1);
+
+ gen_op_do_sched(opq, 1);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4))
+ return;
+
+ recompile_delay_insn(opq);
+
+ gen_op_set_pc_pc_delay(opq, 1);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_sched_delay(opq, 1);
+
+ gen_op_do_jump_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/*------------------------------[ Operation generation for an instruction ]---*/
+/* FIXME: Flag setting is not done in any instruction */
+/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
+
+DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear);
+DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move);
+DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm);
+
+DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm);
+DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add);
+
+void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ /* Just clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if(opq->param[0] != opq->param[1])
+ /* This just moves a register */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Check if we are moveing an immediate */
+ if(param_t[2] == T_NONE) {
+ /* Yep, an immediate */
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ /* Just another move */
+ if(opq->param[0] != opq->param[2])
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ /* Ok, This _IS_ an add... */
+ if(param_t[2] == T_NONE)
+ /* immediate */
+ l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc);
+
+void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ /* FIXME: More optimisations !! (...and immediate...) */
+ l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm);
+DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and);
+
+void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ /* Just clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if((opq->param[0] == opq->param[1]) &&
+ (opq->param[0] == opq->param[2]) &&
+ (param_t[2] != T_NONE))
+ return;
+
+ if(param_t[2] == T_NONE)
+ l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ /* The temporaries are expected to be shiped out after the execution of the
+ * branch instruction wether it branched or not */
+ ship_gprs_out_t(opq->prev);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_check_flag_delay(opq, 1, opq->param[0] << 2);
+ gen_op_do_sched(opq, 1);
+ opq->not_jump_loc = -1;
+ return;
+ }
+
+ gen_op_check_flag(opq, 1, 0);
+ opq->not_jump_loc = opq->num_ops_param - 1;
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ /* The temporaries are expected to be shiped out after the execution of the
+ * branch instruction wether it branched or not */
+ ship_gprs_out_t(opq->prev);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2);
+ gen_op_do_sched(opq, 1);
+ opq->not_jump_loc = -1;
+ return;
+ }
+
+ gen_op_check_not_flag(opq, 1, 0);
+ opq->not_jump_loc = opq->num_ops_param - 1;
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov);
+
+/* FIXME: Check if either opperand 1 or 2 is r0 */
+void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1]))
+ return;
+
+ if(opq->param[1] == opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+/* FIXME: All registers need to be stored before the div instructions as they
+ * have the potenticial to cause an exception */
+
+DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except);
+DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay);
+DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div);
+
+void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[2]) {
+ /* There is no option. This _will_ cause an illeagal exception */
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+ return;
+ }
+
+ if(!delay_slot)
+ check_null_excpt[param_t[2]](opq, 1);
+ else
+ check_null_excpt_delay[param_t[2]](opq, 1);
+
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ /* Clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu);
+
+void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[2]) {
+ /* There is no option. This _will_ cause an illeagal exception */
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+ return;
+ }
+
+ if(!delay_slot)
+ check_null_excpt[param_t[2]](opq, 1);
+ else
+ check_null_excpt_delay[param_t[2]](opq, 1);
+
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ /* Clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs);
+
+void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz);
+
+void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths);
+
+void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz);
+
+void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(opq->param[0] == opq->param[1])
+ return;
+
+ /* In the 32-bit architechture this instruction reduces to a move */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(opq->param[0] == opq->param[1])
+ return;
+
+ /* In the 32-bit architechture this instruction reduces to a move */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1);
+
+void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ int i;
+
+ /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
+ * a temporary. The problem is that the l.jal(r) instruction stores the
+ * `return address' in LINK_REGNO. The temporaries are shiped out only
+ * after the delay slot instruction has executed and so it overwrittes the
+ * `return address'. */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == LINK_REGNO) {
+ /* Don't bother storeing the register, it is going to get clobered in this
+ * instruction anyway */
+ opq->reg_t[i] = 32;
+ break;
+ }
+ }
+
+ /* Store the return address */
+ gen_op_store_link_addr_gpr(opq, 1);
+
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_j_reg(opq, opq->param[0]);
+}
+
+void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ int i;
+
+ /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
+ * a temporary. The problem is that the l.jal(r) instruction stores the
+ * `return address' in LINK_REGNO. The temporaries are shiped out only
+ * after the delay slot instruction has executed and so it overwrittes the
+ * `return address'. */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == LINK_REGNO) {
+ /* Don't bother storeing the register, it is going to get clobered in this
+ * instruction anyway */
+ opq->reg_t[i] = 32;
+ break;
+ }
+ }
+
+ /* Store the return address */
+ gen_op_store_link_addr_gpr(opq, 1);
+
+ gen_j_reg(opq, opq->param[0]);
+}
+
+/* FIXME: Optimise all load instruction when the disposition == 0 */
+
+DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm);
+DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs);
+
+void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm);
+DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz);
+
+void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm);
+DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs);
+
+void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm);
+DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz);
+
+void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm);
+DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws);
+
+void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm);
+DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz);
+
+void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm);
+DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac);
+
+void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] || !opq->param[1])
+ return;
+
+ if(param_t[1] == T_NONE)
+ l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc);
+
+void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ gen_op_macc(opq, 1);
+ return;
+ }
+
+ l_macrc_t_table[param_t[0]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm);
+DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr);
+
+void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+}
+
+void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16);
+}
+
+DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb);
+
+void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] || !opq->param[1])
+ return;
+
+ l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear);
+DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm);
+DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr);
+
+void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[0]) {
+ if(!opq->param[1]) {
+ /* Clear the immediate SPR */
+ gen_op_mtspr_imm_clear(opq, 1, opq->param[2]);
+ return;
+ }
+ l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+}
+
+DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm);
+DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul);
+
+void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu);
+
+void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Do parameter switch now */
+ switch(opq->param[0]) {
+ case NOP_NOP:
+ break;
+ case NOP_EXIT:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_exit(opq, 1);
+ break;
+ case NOP_CNT_RESET:
+ gen_op_nop_reset(opq, 1);
+ break;
+ case NOP_PRINTF:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_printf(opq, 1);
+ break;
+ case NOP_REPORT:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_report(opq, 1);
+ break;
+ default:
+ if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) {
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST);
+ }
+ break;
+ }
+}
+
+DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm);
+DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or);
+
+void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((opq->param[0] == opq->param[1]) &&
+ (opq->param[0] == opq->param[2]) &&
+ (param_t[2] != T_NONE))
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
+ return;
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Check if we are moveing an immediate */
+ if(param_t[2] == T_NONE) {
+ /* Yep, an immediate */
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ /* Just another move */
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_op_prep_rfe(opq, 1);
+ /* FIXME: rename op_do_sched_delay */
+ gen_op_do_sched_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/* FIXME: All store instructions should be optimised when the disposition = 0 */
+
+DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear);
+DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm);
+DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb);
+
+void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sb_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear);
+DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm);
+DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh);
+
+void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sh_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear);
+DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm);
+DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw);
+
+void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sw_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null);
+DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm);
+DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq);
+
+void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ if(param_t[1] == T_NONE) {
+ if(!opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfeq_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfeq_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null);
+DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null);
+DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm);
+DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges);
+
+void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfles IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 >= (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfles_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfges_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null);
+DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null);
+DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm);
+DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu);
+
+void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfleu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 >= opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfleu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgeu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+ if(param_t[1] == T_NONE)
+ l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null);
+DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null);
+DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm);
+DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts);
+
+void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sflts IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 > (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sflts_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgts_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null);
+DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null);
+DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm);
+DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu);
+
+void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfltu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 > opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfltu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgtu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm);
+DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles);
+
+void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfges IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 <= (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfges_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfles_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm);
+DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu);
+
+void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfleu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 <= opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgeu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfleu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm);
+DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts);
+
+void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfgts IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 < (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgts_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sflts_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm);
+DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu);
+
+void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfgtu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 < opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgtu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfltu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null);
+DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm);
+DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne);
+
+void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ if(param_t[1] == T_NONE)
+ if(opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ else
+ l_sfne_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfne_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm);
+DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll);
+
+void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm);
+DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra);
+
+void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm);
+DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl);
+
+void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg);
+DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub);
+
+void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ if(param_t[2] == T_NONE)
+ mov_t_imm[param_t[0]](opq, 1, -opq->param[2]);
+ else
+ l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+/* FIXME: This will not work if the l.sys is in a delay slot */
+void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ if(!delay_slot)
+ gen_op_prep_sys(opq, 1);
+ else
+ gen_op_prep_sys_delay(opq, 1);
+
+ gen_op_do_sched(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/* FIXME: This will not work if the l.trap is in a delay slot */
+void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ if(!delay_slot)
+ gen_op_prep_trap(opq, 1);
+ else
+ gen_op_prep_trap_delay(opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm);
+/* FIXME: Make unused elements NULL */
+DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor);
+
+void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
+ return;
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ if(param_t[2] == T_NONE) {
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+}
+
+/*----------------------------------[ Floating point instructions (stubs) ]---*/
+void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
dyn-rec.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-arith-op.h
===================================================================
--- op-arith-op.h (nonexistent)
+++ op-arith-op.h (revision 388)
@@ -0,0 +1,33 @@
+/* op-arith-op.h -- Micro operations template for arithmetic operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef OP_3T
+__or_dynop void glue(glue(op_, OP_NAME), T)(void)
+{
+ T0 = OP_CAST(T1) OP OP_CAST(T2) OP_EXTRA;
+}
+#endif
+
+#ifdef OP_2T
+__or_dynop void glue(glue(glue(op_, OP_NAME), _imm), T)(void)
+{
+ T0 = OP_CAST(T1) OP OP_CAST(OP_PARAM1) OP_EXTRA;
+}
+#endif
+
op-arith-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-1t.h
===================================================================
--- op-1t.h (nonexistent)
+++ op-1t.h (revision 388)
@@ -0,0 +1,38 @@
+/* op-1t.h -- Instantiation of operatations that work on only 1 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define OP_1T
+#define T glue(_, T0)
+
+#if NUM_T_REGS == 3
+#define T0 t0
+#include OP_FILE
+#undef T0
+#define T0 t1
+#include OP_FILE
+#undef T0
+#define T0 t2
+#include OP_FILE
+#undef T0
+#else
+#error Update op_1t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_1T
op-1t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn-rec.h
===================================================================
--- dyn-rec.h (nonexistent)
+++ dyn-rec.h (revision 388)
@@ -0,0 +1,70 @@
+/* dyn-rec.h -- Recompiler specific definitions
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef DYN_REC__H
+#define DYN_REC__H
+
+typedef void (*gen_code_ent)(void);
+
+/* Each dynamically recompiled page has one of these */
+struct dyn_page {
+ oraddr_t or_page;
+ void *host_page;
+ unsigned int host_len;
+ int dirty; /* Is recompiled page invalid? */
+ int delayr; /* delayr of memory backing this page */
+ uint16_t ts_bound[2049]; /* What registers the temporaries back (on the
+ * begining boundry of the instruction) */
+ void **locs; /* Openrisc locations in the recompiled code */
+ uint32_t *insns; /* Copy of instructions on this page */
+ unsigned int *insn_indexs; /* Decoded instructions on this page */
+};
+
+/* Function prototypes for external use */
+extern void recompile_page(struct dyn_page *dyn);
+extern struct dyn_page *new_dp(oraddr_t page);
+extern void add_to_opq(struct op_queue *opq, int end, int op);
+extern void add_to_op_params(struct op_queue *opq, int end, unsigned long param);
+extern void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
+ unsigned int amount);
+extern void init_dyn_recomp(void);
+extern void run_sched_out_of_line(void);
+extern void recheck_immu(int got_en_dis);
+extern void enter_dyn_code(oraddr_t addr, struct dyn_page *dp);
+extern void dyn_checkwrite(oraddr_t addr);
+extern void dyn_main(void);
+
+/* Global variables for external use */
+extern void *rec_stack_base;
+
+#define IMMU_GOT_ENABLED 1
+#define IMMU_GOT_DISABLED 2
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+
+#endif /* DYN_REC__H */
+
dyn-rec.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-3t.h
===================================================================
--- op-3t.h (nonexistent)
+++ op-3t.h (revision 388)
@@ -0,0 +1,135 @@
+/* op-3t.h -- Instantiation of operatations that work on only 3 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define OP_3T
+#define T glue(glue(glue(glue(glue(_, T0), _), T1), _), T2)
+
+#if NUM_T_REGS == 3
+# define T0 t0
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+# define T0 t1
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+# define T0 t2
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+#else
+#error Update op_3t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_3T
op-3t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-ff1-op.h
===================================================================
--- op-ff1-op.h (nonexistent)
+++ op-ff1-op.h (revision 388)
@@ -0,0 +1,35 @@
+/* op-ff1-op.h -- Micro operations template for the ff1 instruction
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(glue(glue(op_ff1_, DST_T), _), SRC_T)(void)
+{
+ int i;
+
+ for(i = 0; i < 32; i++, SRC_T >>= 1) {
+ if(SRC_T & 1) {
+ DST_T = i;
+ break;
+ }
+ }
+
+ FORCE_RET;
+}
+
+
op-ff1-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-t-reg-mov-op.h
===================================================================
--- op-t-reg-mov-op.h (nonexistent)
+++ op-t-reg-mov-op.h (revision 388)
@@ -0,0 +1,330 @@
+/* op-t-reg-mov-op.h -- Micro operations template for reg<->temporary operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(op_gtt_gpr1, T)(void)
+{
+ T0 = env->reg[1];
+}
+
+__or_dynop void glue(op_gtt_gpr2, T)(void)
+{
+ T0 = env->reg[2];
+}
+
+__or_dynop void glue(op_gtt_gpr3, T)(void)
+{
+ T0 = env->reg[3];
+}
+
+__or_dynop void glue(op_gtt_gpr4, T)(void)
+{
+ T0 = env->reg[4];
+}
+
+__or_dynop void glue(op_gtt_gpr5, T)(void)
+{
+ T0 = env->reg[5];
+}
+
+__or_dynop void glue(op_gtt_gpr6, T)(void)
+{
+ T0 = env->reg[6];
+}
+
+__or_dynop void glue(op_gtt_gpr7, T)(void)
+{
+ T0 = env->reg[7];
+}
+
+__or_dynop void glue(op_gtt_gpr8, T)(void)
+{
+ T0 = env->reg[8];
+}
+
+__or_dynop void glue(op_gtt_gpr9, T)(void)
+{
+ T0 = env->reg[9];
+}
+
+__or_dynop void glue(op_gtt_gpr10, T)(void)
+{
+ T0 = env->reg[10];
+}
+
+__or_dynop void glue(op_gtt_gpr11, T)(void)
+{
+ T0 = env->reg[11];
+}
+
+__or_dynop void glue(op_gtt_gpr12, T)(void)
+{
+ T0 = env->reg[12];
+}
+
+__or_dynop void glue(op_gtt_gpr13, T)(void)
+{
+ T0 = env->reg[13];
+}
+
+__or_dynop void glue(op_gtt_gpr14, T)(void)
+{
+ T0 = env->reg[14];
+}
+
+__or_dynop void glue(op_gtt_gpr15, T)(void)
+{
+ T0 = env->reg[15];
+}
+
+__or_dynop void glue(op_gtt_gpr16, T)(void)
+{
+ T0 = env->reg[16];
+}
+
+__or_dynop void glue(op_gtt_gpr17, T)(void)
+{
+ T0 = env->reg[17];
+}
+
+__or_dynop void glue(op_gtt_gpr18, T)(void)
+{
+ T0 = env->reg[18];
+}
+
+__or_dynop void glue(op_gtt_gpr19, T)(void)
+{
+ T0 = env->reg[19];
+}
+
+__or_dynop void glue(op_gtt_gpr20, T)(void)
+{
+ T0 = env->reg[20];
+}
+
+__or_dynop void glue(op_gtt_gpr21, T)(void)
+{
+ T0 = env->reg[21];
+}
+
+__or_dynop void glue(op_gtt_gpr22, T)(void)
+{
+ T0 = env->reg[22];
+}
+
+__or_dynop void glue(op_gtt_gpr23, T)(void)
+{
+ T0 = env->reg[23];
+}
+
+__or_dynop void glue(op_gtt_gpr24, T)(void)
+{
+ T0 = env->reg[24];
+}
+
+__or_dynop void glue(op_gtt_gpr25, T)(void)
+{
+ T0 = env->reg[25];
+}
+
+__or_dynop void glue(op_gtt_gpr26, T)(void)
+{
+ T0 = env->reg[26];
+}
+
+__or_dynop void glue(op_gtt_gpr27, T)(void)
+{
+ T0 = env->reg[27];
+}
+
+__or_dynop void glue(op_gtt_gpr28, T)(void)
+{
+ T0 = env->reg[28];
+}
+
+__or_dynop void glue(op_gtt_gpr29, T)(void)
+{
+ T0 = env->reg[29];
+}
+
+__or_dynop void glue(op_gtt_gpr30, T)(void)
+{
+ T0 = env->reg[30];
+}
+
+__or_dynop void glue(op_gtt_gpr31, T)(void)
+{
+ T0 = env->reg[31];
+}
+
+__or_dynop void glue(op_ttg_gpr1, T)(void)
+{
+ env->reg[1] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr2, T)(void)
+{
+ env->reg[2] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr3, T)(void)
+{
+ env->reg[3] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr4, T)(void)
+{
+ env->reg[4] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr5, T)(void)
+{
+ env->reg[5] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr6, T)(void)
+{
+ env->reg[6] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr7, T)(void)
+{
+ env->reg[7] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr8, T)(void)
+{
+ env->reg[8] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr9, T)(void)
+{
+ env->reg[9] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr10, T)(void)
+{
+ env->reg[10] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr11, T)(void)
+{
+ env->reg[11] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr12, T)(void)
+{
+ env->reg[12] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr13, T)(void)
+{
+ env->reg[13] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr14, T)(void)
+{
+ env->reg[14] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr15, T)(void)
+{
+ env->reg[15] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr16, T)(void)
+{
+ env->reg[16] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr17, T)(void)
+{
+ env->reg[17] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr18, T)(void)
+{
+ env->reg[18] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr19, T)(void)
+{
+ env->reg[19] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr20, T)(void)
+{
+ env->reg[20] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr21, T)(void)
+{
+ env->reg[21] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr22, T)(void)
+{
+ env->reg[22] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr23, T)(void)
+{
+ env->reg[23] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr24, T)(void)
+{
+ env->reg[24] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr25, T)(void)
+{
+ env->reg[25] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr26, T)(void)
+{
+ env->reg[26] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr27, T)(void)
+{
+ env->reg[27] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr28, T)(void)
+{
+ env->reg[28] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr29, T)(void)
+{
+ env->reg[29] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr30, T)(void)
+{
+ env->reg[30] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr31, T)(void)
+{
+ env->reg[31] = T0;
+}
+
op-t-reg-mov-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen-i386.c
===================================================================
--- dyngen-i386.c (nonexistent)
+++ dyngen-i386.c (revision 388)
@@ -0,0 +1,75 @@
+/* dyngen-i386.c -- i386 parts of dyngen
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include
+
+#include "dyngen.h"
+
+#define RET_OPCODE 0xc3
+
+unsigned int i386_get_real_func_len(void *f_start, unsigned int f_len, char *name)
+{
+ if(((uint8_t *)f_start)[f_len - 1] != RET_OPCODE) {
+ fprintf(stderr, "`%s' does not have a ret at the end!\n", name);
+ exit(1);
+ }
+
+ return f_len - 1;
+}
+
+void i386_gen_reloc(FILE *f, struct reloc *reloc, unsigned int param)
+{
+ switch(reloc->type) {
+ case R_386_32:
+ fprintf(f, " *(uint32_t *)(host_page + %d) = *(ops_param + %u) + %d;\n",
+ reloc->func_offset, param - 1, reloc->addend);
+ break;
+ default:
+ fprintf(stderr, "Unknown i386 relocation: %i (%s)\n", reloc->type,
+ reloc->name);
+ }
+}
+
+void i386_gen_func_reloc(FILE *f, struct reloc *reloc)
+{
+ switch(reloc->type) {
+ case R_386_32:
+ /* This relocation is absolute. There is nothing to relocate (The linker
+ * handles this fine). */
+ break;
+ case R_386_PC32:
+ fprintf(f, " *(uint32_t *)(host_page + %d) = (uint32_t)((%s + %d) - (unsigned int)(host_page + %d));\n",
+ reloc->func_offset, reloc->name, reloc->addend, reloc->func_offset);
+ break;
+ default:
+ fprintf(stderr, "Unknown i386 relocation: %i (symbol: %s)\n", reloc->type,
+ reloc->name);
+ }
+}
+
+const struct archf archfs = {
+ i386_get_real_func_len,
+ i386_gen_reloc,
+ i386_gen_func_reloc
+};
dyngen-i386.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: def-op-t.h
===================================================================
--- def-op-t.h (nonexistent)
+++ def-op-t.h (revision 388)
@@ -0,0 +1,138 @@
+/* def_op_t.h -- Operation-generation strucutre definitions helpers
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define GPR_T(op_name, temp) \
+ { NULL, \
+ glue(glue(op_name, 1), temp), \
+ glue(glue(op_name, 2), temp), \
+ glue(glue(op_name, 3), temp), \
+ glue(glue(op_name, 4), temp), \
+ glue(glue(op_name, 5), temp), \
+ glue(glue(op_name, 6), temp), \
+ glue(glue(op_name, 7), temp), \
+ glue(glue(op_name, 8), temp), \
+ glue(glue(op_name, 9), temp), \
+ glue(glue(op_name, 10), temp), \
+ glue(glue(op_name, 11), temp), \
+ glue(glue(op_name, 12), temp), \
+ glue(glue(op_name, 13), temp), \
+ glue(glue(op_name, 14), temp), \
+ glue(glue(op_name, 15), temp), \
+ glue(glue(op_name, 16), temp), \
+ glue(glue(op_name, 17), temp), \
+ glue(glue(op_name, 18), temp), \
+ glue(glue(op_name, 19), temp), \
+ glue(glue(op_name, 20), temp), \
+ glue(glue(op_name, 21), temp), \
+ glue(glue(op_name, 22), temp), \
+ glue(glue(op_name, 23), temp), \
+ glue(glue(op_name, 24), temp), \
+ glue(glue(op_name, 25), temp), \
+ glue(glue(op_name, 26), temp), \
+ glue(glue(op_name, 27), temp), \
+ glue(glue(op_name, 28), temp), \
+ glue(glue(op_name, 29), temp), \
+ glue(glue(op_name, 30), temp), \
+ glue(glue(op_name, 31), temp) }
+
+#if NUM_T_REGS == 3
+
+#define OP_ROW(op_name) \
+ { glue(op_name, _t0), glue(op_name, _t1), glue(op_name, _t2) }
+
+#define OP_ROW_NEQ0(op_name) \
+ { NULL, glue(op_name, _t1), glue(op_name, _t2) }
+
+#define OP_ROW_NEQ1(op_name) \
+ { glue(op_name, _t0), NULL, glue(op_name, _t2) }
+
+#define OP_ROW_NEQ2(op_name) \
+ { glue(op_name, _t0), glue(op_name, _t1), NULL }
+
+#define OP_ROW_COL(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)), }
+
+/* In 3D space: row, column, ??? */
+#define OP_ROW_COL_3D(op_name) { \
+ OP_ROW_COL(glue(op_name, _t0)), \
+ OP_ROW_COL(glue(op_name, _t1)), \
+ OP_ROW_COL(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ(op_name) { \
+ OP_ROW_NEQ0(glue(op_name, _t0)), \
+ OP_ROW_NEQ1(glue(op_name, _t1)), \
+ OP_ROW_NEQ2(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ0(op_name) { \
+ OP_ROW_NEQ0(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ1(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW_NEQ1(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ2(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW_NEQ2(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_3D_NEQ(op_name) { \
+ OP_ROW_COL_NEQ0(glue(op_name, _t0)), \
+ OP_ROW_COL_NEQ1(glue(op_name, _t1)), \
+ OP_ROW_COL_NEQ2(glue(op_name, _t2)) }
+
+#define GPR_ROW_COL(op_name) { \
+ GPR_T(op_name, _t0), \
+ GPR_T(op_name, _t1), \
+ GPR_T(op_name, _t2) }
+
+#else
+#error Update def_op_t.h for NUM_T_REGS temporaries
+#endif
+
+#define DEF_1T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS] = \
+ OP_ROW(op_name)
+
+#define DEF_2T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL(op_name)
+
+#define DEF_3T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_3D(op_name)
+
+/* Same as above but put NULL in places where T0 == T1 */
+#define DEF_2T_OP_NEQ(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_NEQ(op_name)
+
+/* Same as above but put NULL in places where T0 == T1 == T2 */
+#define DEF_3T_OP_NEQ(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_3D_NEQ(op_name)
+
+#define DEF_GPR_OP(type, name, op_name) \
+ static const generic_gen_op name[NUM_T_REGS][32] = \
+ GPR_ROW_COL(op_name)
+
def-op-t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-1t-op.h
===================================================================
--- op-1t-op.h (nonexistent)
+++ op-1t-op.h (revision 388)
@@ -0,0 +1,75 @@
+/* op-1t-op.h -- Micro operations useing only one temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+__or_dynop void glue(op_imm, T)(void)
+{
+ T0 = OP_PARAM1;
+}
+
+__or_dynop void glue(op_clear, T)(void)
+{
+ T0 = 0;
+}
+
+__or_dynop void glue(op_check_null_except_delay, T)(void)
+{
+ if(!T0) {
+ /* Do exception */
+ env->sprs[SPR_EEAR_BASE] = env->pc - 4;
+ env->delay_insn = 0;
+ do_jump(EXCEPT_ILLEGAL);
+ }
+}
+
+__or_dynop void glue(op_check_null_except, T)(void)
+{
+ if(!T0) {
+ /* Do exception */
+ env->sprs[SPR_EEAR_BASE] = env->pc;
+ do_jump(EXCEPT_ILLEGAL);
+ }
+}
+
+__or_dynop void glue(op_calc_insn_ea, T)(void)
+{
+ env->insn_ea = T0 + OP_PARAM1;
+}
+
+__or_dynop void glue(op_macrc, T)(void)
+{
+ /* FIXME: How is this supposed to work? The architechture manual says that
+ * the low 32-bits shall be saved into rD. I have just copied this code from
+ * insnset.c to make testbench/mul pass */
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ T0 = (orreg_t)(temp >> 28);
+ env->sprs[SPR_MACLO] = 0;
+ env->sprs[SPR_MACHI] = 0;
+}
+
+__or_dynop void glue(op_mac_imm, T)(void)
+{
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ temp += (int64_t)T0 * (int64_t)OP_PARAM1;
+
+ env->sprs[SPR_MACLO] = temp & 0xffffffff;
+ env->sprs[SPR_MACHI] = temp >> 32;
+}
+
op-1t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-2t-op.h
===================================================================
--- op-2t-op.h (nonexistent)
+++ op-2t-op.h (revision 388)
@@ -0,0 +1,44 @@
+/* op-1t-op.h -- Micro operations useing two temporaries
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+__or_dynop void glue(op_move, T)(void)
+{
+ T0 = T1;
+}
+
+__or_dynop void glue(op_ff1, T)(void)
+{
+ int i;
+
+ for(i = 0; i < 32; i++, T0 >>= 1) {
+ if(T0 & 1) {
+ T1 = i;
+ break;
+ }
+ }
+
+ FORCE_RET;
+}
+
+
+__or_dynop void glue(op_neg, T)(void)
+{
+ T0 = -T1;
+}
+
op-2t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-3t-op.h
===================================================================
--- op-3t-op.h (nonexistent)
+++ op-3t-op.h (revision 388)
@@ -0,0 +1,25 @@
+/* op-3t-op.h -- Micro operations useing three temporaries
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(op_cmov, T)(void)
+{
+ T0 = env->sprs[SPR_SR] & SPR_SR_F ? T1 : T2;
+}
+
op-3t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen.c
===================================================================
--- dyngen.c (nonexistent)
+++ dyngen.c (revision 388)
@@ -0,0 +1,289 @@
+/* dyngen.c -- Generates micro operation generating functions
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include "dyngen.h"
+
+#define OP_FUNC_PREFIX "op_"
+#define OP_FUNC_PARAM_PREFIX "__op_param"
+/* Have to add to to make sure that the param[] is 0 */
+#define MAX_PARAMS (3 + 1)
+
+static const char *c_file_head =
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"abstract.h\"\n"
+"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"%s\"\n"
+"\n";
+
+static const char *gen_code_proto =
+"void gen_code(struct op_queue *opq, struct dyn_page *dp);\n"
+"void patch_relocs(struct op_queue *opq, void *host_page);\n"
+"\n";
+
+static const char *c_sw_file_head =
+"#include \n"
+"#include \n"
+"\n"
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"abstract.h\"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"%s\"\n"
+"\n"
+"void gen_code(struct op_queue *opq, struct dyn_page *dp)\n"
+"{\n"
+" unsigned int *ops, i;\n"
+" unsigned int host_len = dp->host_len;\n"
+" void *host_cur = dp->host_page;\n"
+" oraddr_t pc = dp->or_page;\n"
+" void **loc = dp->locs;\n"
+"\n"
+" while(opq) {\n"
+" if(opq->next)\n"
+" *loc++ = (void *)(host_cur - dp->host_page);"
+"\n"
+" for(i = 0, ops = opq->ops; i < opq->num_ops; i++, ops++) {\n"
+" switch(*ops) {\n"
+" case op_mark_loc_indx:\n"
+" opq->ops_param[0] = host_cur - dp->host_page;\n"
+" break;\n";
+
+static const char *c_sw_file_tail =
+" }\n"
+" }\n"
+" opq = opq->next;\n"
+" pc += 4;\n"
+" }\n"
+"\n"
+" dp->host_len = host_cur - dp->host_page;\n"
+" dp->host_page = realloc(dp->host_page, dp->host_len);\n"
+"}\n";
+
+static const char *c_rel_file_head =
+"#include /* To get printf... */\n"
+"#include \n"
+"\n"
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"abstract.h\"\n"
+"#include \"tick.h\"\n"
+"#include \"execute.h\"\n"
+"#include \"sprs.h\"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"op-support.h\"\n"
+"#include \"%s\"\n"
+"\n"
+"void do_scheduler(void); /* FIXME: Remove */\n"
+"void do_sched_wrap(void); /* FIXME: Remove */\n"
+"void do_sched_wrap_delay(void); /* FIXME: Remove */\n"
+"void simprintf(oraddr_t stackaddr, unsigned long regparam); /* FIXME: Remove */\n"
+"\n"
+"void patch_relocs(struct op_queue *opq, void *host_page)\n"
+"{\n"
+" unsigned int *ops, *ops_param, i;\n"
+"\n"
+" while(opq) {\n"
+" for(i = 0, ops = opq->ops, ops_param = opq->ops_param; i < opq->num_ops; i++, ops++) {\n"
+" switch(*ops) {\n";
+
+static const char *c_rel_file_tail =
+" }\n"
+" }\n"
+" opq = opq->next;\n"
+" }\n"
+"}\n";
+
+static void gen_func_proto(FILE *f, const char *name, int *params)
+{
+ int i;
+
+ fprintf(f, "void gen_%s(struct op_queue *opq, int end", name);
+ for(i = 0; (i < MAX_PARAMS) && params[i]; i++) {
+ fprintf(f, ", uorreg_t param%i", i + 1);
+ }
+ fprintf(f, ")");
+}
+
+int main(int argc, char **argv)
+{
+ void *obj;
+ int i, j;
+ unsigned int len;
+ char *name;
+ int params[MAX_PARAMS];
+ struct reloc reloc;
+
+ FILE *c_file;
+ FILE *h_file;
+ FILE *c_sw_file;
+ FILE *c_rel_file;
+
+ if(argc != 6) {
+ fprintf(stderr, "Usage: %s
dyngen.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: common-i386.h
===================================================================
--- common-i386.h (nonexistent)
+++ common-i386.h (revision 388)
@@ -0,0 +1,63 @@
+/* common-i386.h -- Assembler routines used in rec_i386.h and op_i386.h
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This is needed because we can't move an mmx register to a general purpose
+ * register. */
+static union {
+ struct {
+ uint32_t low32;
+ uint32_t high32;
+ } val3232;
+ uint64_t val64;
+} useless_x86;
+
+/* Sets the PC with a specified value */
+static void set_pc(oraddr_t pc)
+{
+ /* I could just use pc as a memory argument, but if I do that then gcc may put
+ * the value of pc onto the stack, in which case gcc would also shift the
+ * stack twice, which would result in two add 4, %esp instructions and a
+ * mov %eax, *%esp, which would not only be slow but it would take up more
+ * space. */
+ asm("movq %%mm0, %0\n"
+ "\tmovl %2, %1\n"
+ "\tmovq %3, %%mm0"
+ : "=m" (useless_x86.val64),
+ "=m" (useless_x86.val3232.high32)
+ : "r" (pc),
+ "m" (useless_x86.val64));
+}
+
+/* Returns the current value of the pc */
+static oraddr_t get_pc(void)
+{
+ asm("movq %%mm0, %0" : "=m" (useless_x86.val64));
+ return useless_x86.val3232.high32;
+}
+
+/* Updates the runtime.sim.cycles counter */
+static void upd_sim_cycles(void)
+{
+ asm volatile ("movq %%mm0, %0\n" : "=m" (useless_x86.val64));
+ runtime.sim.cycles += scheduler.job_queue->time - useless_x86.val3232.low32;
+ scheduler.job_queue->time = useless_x86.val3232.low32;
+ cpu_state.pc = useless_x86.val3232.high32;
+}
+
common-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-extend-op.h
===================================================================
--- op-extend-op.h (nonexistent)
+++ op-extend-op.h (revision 388)
@@ -0,0 +1,27 @@
+/* op-extend-op.h -- Micro operations template for sign extention operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+void glue(glue(op_, EXT_NAME), T)(void)
+{
+ register EXT_TYPE x;
+ x = T1;
+ T0 = EXT_CAST x;
+}
+
op-extend-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 388)
@@ -0,0 +1,196 @@
+# Makefile -- Makefile for OR32 dependent simulation
+#
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+# Copyright (C) 2008 Embecosm Limited
+#
+# Contributor Jeremy Bennett
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+
+
+if DYNAMIC_EXECUTION
+
+noinst_LTLIBRARIES = libarch.la
+
+noinst_PROGRAMS = dyngen
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ op.c \
+ dyn-rec.c \
+ op-support.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+nodist_libarch_la_SOURCES = gen-ops.h \
+ gen-ops.c \
+ gen-ops-gen.c \
+ gen-ops-rel.c
+
+BUILT_SOURCES = gen-ops.h \
+ gen-ops.c \
+ gen-ops-gen.c \
+ gen-ops-rel.c
+
+dyngen_SOURCES = dyngen.c \
+ dyngen-i386.c \
+ dyngen-elf.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+dyngen_CFLAGS = $(AM_CFLAGS)
+
+gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o
+ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h
+
+OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2
+
+op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \
+ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \
+ op-swhb-op.h
+ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $<
+else
+
+noinst_LTLIBRARIES = libarch.la
+
+if GENERATE_NEEDED
+
+EXTRA_DIST = insnset.c
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+BUILT_SOURCES = execgen.c
+
+noinst_PROGRAMS = generate$(EXEEXT)
+
+generate_SOURCES = or32.c \
+ generate.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+generate_CFLAGS = $(AM_CFLAGS)
+
+execgen.c: generate$(EXEEXT) insnset.c
+ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c
+
+else
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+dist_EXTRA_libarch_la_SOURCES = insnset.c
+
+endif
+endif
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+
+CLEANFILES = execgen.c \
+ generate \
+ gen-ops.c \
+ gen-ops.h \
+ gen-ops-rel.c \
+ gen-ops-gen.c
Makefile.am
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen-elf.c
===================================================================
--- dyngen-elf.c (nonexistent)
+++ dyngen-elf.c (revision 388)
@@ -0,0 +1,359 @@
+/* dyngen-elf.c -- Elf parser for dyngen
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "dyngen.h"
+
+struct elf_obj {
+ Elf32_Ehdr e_hdr;
+ Elf32_Shdr *e_shdrs;
+ void **e_sections;
+ Elf32_Sym *e_syms; /* The symbol table in the elf file */
+ unsigned int e_sym_num; /* The number of symbols */
+ unsigned int e_sym_str_tab; /* The string-table associated with symbols */
+ Elf32_Rel *e_rels;
+ unsigned int e_rel_num; /* The number of relocations (in e_rel) */
+ unsigned int e_rel_sym;
+ unsigned int e_rel_sec; /* The section to modify */
+ Elf32_Rela *e_relas;
+ unsigned int e_rela_num; /* The number of relocations (in e_rela) */
+ unsigned int e_rela_sym;
+ unsigned int e_rela_sec; /* The section to modify */
+};
+
+void *elf_open_obj(const char *file)
+{
+ struct elf_obj *obj;
+ FILE *f;
+ int i;
+
+ if(!(obj = malloc(sizeof(struct elf_obj)))) {
+ fprintf(stderr, "OOM\n");
+ return NULL;
+ }
+
+ if(!(f = fopen(file, "r"))) {
+ free(obj);
+ return NULL;
+ }
+
+ fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f);
+
+ /* Do some sanity checks */
+ if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) ||
+ (obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) ||
+ (obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) ||
+ (obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) {
+ fprintf(stderr, "%s is not an elf file!\n", file);
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) {
+ fprintf(stderr, "Invalid class in ELF header\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) {
+ fprintf(stderr, "Invalid data format in ELF header\n");
+ goto error_load;
+ }
+
+ /* FIXME: Swap data as necessary */
+
+ if((obj->e_hdr.e_ident[EI_VERSION] != 1) ||
+ (obj->e_hdr.e_version != 1)) {
+ fprintf(stderr, "Unexpected elf version found: %i (%li)\n",
+ obj->e_hdr.e_ident[EI_VERSION], (long int)obj->e_hdr.e_version);
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_type != ET_REL) {
+ fprintf(stderr, "Appears that we did not receive a object file\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_phoff) {
+ fprintf(stderr, "What am I supposed to do with a program header??\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+ fprintf(stderr, "Unknown size of elf header\n");
+ goto error_load;
+ }
+
+ if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) {
+ fprintf(stderr, "The elf file contains no sections!\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) {
+ fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize);
+ goto error_load;
+ }
+
+ /* Load the section headers */
+ if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){
+ fprintf(stderr, "OOM\n");
+ goto error_load;
+ }
+
+ fseek(f, obj->e_hdr.e_shoff, SEEK_SET);
+ fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f);
+
+ /* FIXME: swap data */
+
+ /* Load the sections */
+ if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) {
+ fprintf(stderr, "OOM\n");
+ free(obj->e_shdrs);
+ goto error_load;
+ }
+
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_shdrs[i].sh_type == SHT_NOBITS)
+ continue;
+ if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) {
+ fprintf(stderr, "OOM\n");
+ goto post_sec_error_load;
+ }
+ fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET);
+ fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f);
+ }
+
+ obj->e_rels = NULL;
+ obj->e_syms = NULL;
+ obj->e_relas = NULL;
+
+ /* Find the symbol table and relocation table(s) */
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ switch(obj->e_shdrs[i].sh_type) {
+ case SHT_SYMTAB:
+ if(obj->e_syms) {
+ fprintf(stderr, "ELF file has more than one symbol table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) {
+ fprintf(stderr, "ELF symbol table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n");
+ goto post_sec_error_load;
+ }
+ obj->e_syms = obj->e_sections[i];
+ obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ obj->e_sym_str_tab = obj->e_shdrs[i].sh_link;
+ break;
+ case SHT_REL:
+ if(obj->e_rels) {
+ fprintf(stderr, "ELF file has more than one relocation table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) {
+ fprintf(stderr, "ELF relocation table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n");
+ goto post_sec_error_load;
+ }
+ obj->e_rels = obj->e_sections[i];
+ obj->e_rel_sec = obj->e_shdrs[i].sh_info;
+ obj->e_rel_sym = obj->e_shdrs[i].sh_link;
+ obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ break;
+ case SHT_RELA:
+ if(obj->e_relas) {
+ fprintf(stderr, "ELF file has more than one a-relocation table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) {
+ fprintf(stderr, "ELF a-relocation table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n");
+ goto post_sec_error_load;
+ }
+ obj->e_relas = obj->e_sections[i];
+ obj->e_rela_sec = obj->e_shdrs[i].sh_info;
+ obj->e_rela_sym = obj->e_shdrs[i].sh_link;
+ obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ break;
+ }
+ }
+
+ fclose(f);
+ return obj;
+
+post_sec_error_load:
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_sections[i])
+ free(obj->e_sections[i]);
+ }
+ free(obj->e_sections);
+ free(obj->e_shdrs);
+error_load:
+ free(obj);
+ fclose(f);
+ return NULL;
+}
+
+void elf_close_obj(void *e_obj)
+{
+ struct elf_obj *obj = e_obj;
+ int i;
+
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_sections[i])
+ free(obj->e_sections[i]);
+ }
+ free(obj->e_sections);
+ free(obj->e_shdrs);
+ free(obj);
+}
+
+static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func)
+{
+ int i, j;
+ Elf32_Sym *cur;
+
+ for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) {
+ if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL)
+ continue;
+ if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC)
+ continue;
+ if(j == func)
+ return cur;
+ j++;
+ }
+ return NULL;
+}
+
+char *elf_get_func_name(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(func_sym)
+ return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name;
+
+ return NULL;
+}
+
+unsigned int elf_get_func_len(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(func_sym)
+ return func_sym->st_size;
+ return 0;
+}
+
+void *elf_get_func_start(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(!func_sym)
+ return NULL;
+
+ if(func_sym->st_shndx == SHN_COMMON) {
+ fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n");
+ return NULL;
+ }
+
+ return obj->e_sections[func_sym->st_shndx] + func_sym->st_value;
+}
+
+static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym)
+{
+ char *name;
+
+ name = obj->e_sections[obj->e_sym_str_tab];
+ name += obj->e_syms[sym].st_name;
+
+ return name;
+}
+
+int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn,
+ struct reloc *reloc)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+ Elf32_Rel *cur;
+ Elf32_Rela *cura;
+ int i, j;
+
+/*
+ if(obj->e_rel_sec != func_sym->st_shndx) {
+ fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n");
+ return 0;
+ }
+*/
+
+ for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) {
+ if((cur->r_offset - func_sym->st_value) > func_sym->st_size)
+ continue;
+ if(relocn == j) {
+ reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
+ reloc->func_offset = cur->r_offset - func_sym->st_value;
+ reloc->type = ELF32_R_TYPE(cur->r_info);
+ /* FIXME: Byte-swap */
+ reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset);
+ return 1;
+ }
+ j++;
+ }
+
+ if(!obj->e_relas)
+ return 0;
+
+ for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) {
+ if((cura->r_offset - func_sym->st_value) > func_sym->st_size)
+ continue;
+ if(relocn == j) {
+ reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
+ reloc->func_offset = cura->r_offset - func_sym->st_value;
+ reloc->type = ELF32_R_TYPE(cur->r_info);
+ reloc->addend = cura->r_addend;
+ return 1;
+ }
+ j++;
+ }
+
+ return 0;
+}
+
+const struct bff bffs = {
+ elf_open_obj,
+ elf_close_obj,
+ elf_get_func_name,
+ elf_get_func_start,
+ elf_get_func_len,
+ elf_get_func_reloc };
dyngen-elf.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen.h
===================================================================
--- dyngen.h (nonexistent)
+++ dyngen.h (revision 388)
@@ -0,0 +1,45 @@
+/* dyngen.h -- Definitions for dyngen.c
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+struct reloc {
+ unsigned int func_offset;
+ unsigned int addend;
+ int type;
+ const char *name;
+};
+
+struct bff {
+ void *(*open_obj)(const char *object); /* Open the object file */
+ void (*close_obj)(void *);
+ char *(*get_func_name)(void *, unsigned int func); /* Gets the name of func */
+ void *(*get_func_start)(void *, unsigned int func);
+ unsigned int (*get_func_len)(void *, unsigned int func);
+ int (*get_func_reloc)(void *, unsigned int func, unsigned int relocn, struct reloc *reloc);
+};
+
+extern const struct bff bffs;
+
+struct archf {
+ unsigned int (*get_real_func_len)(void *func, unsigned int len, char *name);
+ void (*gen_reloc)(FILE *f, struct reloc *reloc, unsigned int param);
+ void (*gen_func_reloc)(FILE *f, struct reloc *reloc);
+};
+
+extern const struct archf archfs;
dyngen.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: i386-regs.h
===================================================================
--- i386-regs.h (nonexistent)
+++ i386-regs.h (revision 388)
@@ -0,0 +1,26 @@
+/* i386_regs.h -- Register definitions for i386
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define CPU_STATE_REG "ebp"
+#define T0_REG "ebx"
+#define T1_REG "esi"
+#define T2_REG "edi"
+
+#define NUM_T_REGS 3
i386-regs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-mac-op.h
===================================================================
--- op-mac-op.h (nonexistent)
+++ op-mac-op.h (revision 388)
@@ -0,0 +1,30 @@
+/* op-mac-op.h -- Micro operations template for mac operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(glue(op_, OP_NAME), T)(void)
+{
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ temp OP (int64_t)T0 * (int64_t)T1;
+
+ env->sprs[SPR_MACLO] = temp & 0xffffffff;
+ env->sprs[SPR_MACHI] = temp >> 32;
+}
+
op-mac-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property