URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/nog_patch_38/or1ksim/cpu/or32
- from Rev 1401 to Rev 1765
- ↔ Reverse comparison
Rev 1401 → Rev 1765
/execute.c
0,0 → 1,810
/* execute.c -- OR1K architecture dependent simulation |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ |
|
/* Most of the OR1K simulation is done in here. |
|
When SIMPLE_EXECUTION is defined below a file insnset.c is included! |
*/ |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <ctype.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "branch_predict.h" |
#include "abstract.h" |
#include "labels.h" |
#include "parse.h" |
#include "execute.h" |
#include "except.h" |
#include "sprs.h" |
#include "sim-config.h" |
#include "debug_unit.h" |
#include "opcode/or32.h" |
#include "immu.h" |
#include "dmmu.h" |
#include "debug.h" |
#include "stats.h" |
|
/* General purpose registers. */ |
uorreg_t reg[MAX_GPRS]; |
|
/* Instruction queue */ |
struct iqueue_entry iqueue[20]; |
|
/* Is current insn in execution a delay insn? */ |
int delay_insn; |
|
/* Benchmark multi issue execution */ |
int multissue[20]; |
int issued_per_cycle = 4; |
|
/* Completition queue */ |
struct iqueue_entry icomplet[20]; |
|
/* Program counter (and translated PC) */ |
oraddr_t pc; |
|
/* Previous program counter */ |
oraddr_t pcprev = 0; |
|
/* Temporary program counter */ |
oraddr_t pcnext; |
|
/* Delay instruction effective address register */ |
oraddr_t pcdelay; |
|
/* CCR */ |
int flag; |
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */ |
static int sbuf_head = 0, sbuf_tail = 0, sbuf_count = 0; |
static int sbuf_buf[MAX_SBUF_LEN] = {0}; |
static int sbuf_prev_cycles = 0; |
|
/* Num cycles waiting for stores to complete */ |
int sbuf_wait_cyc = 0; |
|
/* Number of total store cycles */ |
int sbuf_total_cyc = 0; |
|
/* Whether we are doing statistical analysis */ |
int do_stats = 0; |
|
/* Local data needed for execution. */ |
static int next_delay_insn; |
static int breakpoint; |
|
/* Effective address of instructions that have an effective address. This is |
* only used to get dump_exe_log correct */ |
static oraddr_t insn_ea; |
|
/* History of execution */ |
struct hist_exec *hist_exec_tail = NULL; |
|
/* Implementation specific. |
Get an actual value of a specific register. */ |
|
uorreg_t evalsim_reg(unsigned int regno) |
{ |
if (regno < MAX_GPRS) { |
return reg[regno]; |
} else { |
PRINTF("\nABORT: read out of registers\n"); |
runtime.sim.cont_run = 0; |
return 0; |
} |
} |
|
/* Implementation specific. |
Set a specific register with value. */ |
|
void setsim_reg(unsigned int regno, uorreg_t value) |
{ |
if (regno == 0) /* gpr0 is always zero */ |
value = 0; |
|
if (regno < MAX_GPRS) { |
reg[regno] = value; |
} else { |
PRINTF("\nABORT: write out of registers\n"); |
runtime.sim.cont_run = 0; |
} |
} |
|
/* Implementation specific. |
Set a specific register with value. */ |
|
inline static void set_reg(int regno, uorreg_t value) |
{ |
#if 0 |
if (strcmp(regstr, FRAME_REG) == 0) { |
PRINTF("FP (%s) modified by insn at %x. ", FRAME_REG, pc); |
PRINTF("Old:%.8lx New:%.8lx\n", eval_reg(regno), value); |
} |
|
if (strcmp(regstr, STACK_REG) == 0) { |
PRINTF("SP (%s) modified by insn at %x. ", STACK_REG, pc); |
PRINTF("Old:%.8lx New:%.8lx\n", eval_reg(regno), value); |
} |
#endif |
|
if (regno < MAX_GPRS) { |
reg[regno] = value; |
#if RAW_RANGE_STATS |
raw_stats.reg[regno] = runtime.sim.cycles; |
#endif /* RAW_RANGE */ |
} else { |
PRINTF("\nABORT: write out of registers\n"); |
runtime.sim.cont_run = 0; |
} |
} |
|
/* Implementation specific. |
Evaluates source operand opd. */ |
|
static 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; |
} |
|
/* Does source operand depend on computation of dstoperand? Return |
non-zero if yes. |
|
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 |
*/ |
|
int depend_operands(prev, next) |
struct iqueue_entry *prev; |
struct iqueue_entry *next; |
{ |
/* Find destination type. */ |
unsigned long type = 0; |
int prev_dis, next_dis; |
orreg_t prev_reg_val = 0; |
struct insn_op_struct *opd; |
|
if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG |
&& or32_opcodes[next->insn_index].flags & OR32_R_FLAG) |
return 1; |
|
opd = 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 = 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; |
} |
|
/* Sets a new SPR_SR_OV value, based on next register value */ |
|
#if SET_OV_FLAG |
#define set_ov_flag(value) if((value) & 0x80000000) setsprbits (SPR_SR, SPR_SR_OV, 1); else setsprbits (SPR_SR, SPR_SR_OV, 0) |
#else |
#define set_ov_flag(value) |
#endif |
|
/* Modified by CZ 26/05/01 for new mode execution */ |
/* Fetch returns nonzero if instruction should NOT be executed. */ |
static inline int fetch() |
{ |
static int break_just_hit = 0; |
|
if (CHECK_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 (pc)) && !break_just_hit) { |
break_just_hit = 1; |
return 1; /* Breakpoint set. */ |
} |
break_just_hit = 0; |
} |
|
breakpoint = 0; |
/* Fetch instruction. */ |
iqueue[0].insn_addr = pc; |
iqueue[0].insn = eval_insn (pc, &breakpoint); |
|
if (!except_pending) |
runtime.cpu.instructions++; |
|
/* update_pc will be called after execution */ |
|
return 0; |
} |
|
/* This code actually updates the PC value. */ |
static inline void update_pc () |
{ |
delay_insn = next_delay_insn; |
pcprev = pc; /* Store value for later */ |
pc = pcnext; |
pcnext = delay_insn ? pcdelay : pcnext + 4; |
} |
|
#if SIMPLE_EXECUTION |
static inline |
#endif |
void analysis (struct iqueue_entry *current) |
{ |
if (config.cpu.dependstats) { |
/* Dynamic, dependency stats. */ |
adddstats(icomplet[0].insn_index, current->insn_index, 1, check_depend()); |
|
/* Dynamic, functional units stats. */ |
addfstats(or32_opcodes[icomplet[0].insn_index].func_unit, |
or32_opcodes[current->insn_index].func_unit, 1, check_depend()); |
|
/* Dynamic, single stats. */ |
addsstats(current->insn_index, 1); |
} |
|
if (config.cpu.superscalar) { |
if ((or32_opcodes[current->insn_index].func_unit == it_branch) || |
(or32_opcodes[current->insn_index].func_unit == it_jump)) |
runtime.sim.storecycles += 0; |
|
if (or32_opcodes[current->insn_index].func_unit == it_store) |
runtime.sim.storecycles += 1; |
|
if (or32_opcodes[current->insn_index].func_unit == it_load) |
runtime.sim.loadcycles += 1; |
#if 0 |
if ((icomplet[0].func_unit == it_load) && check_depend()) |
runtime.sim.loadcycles++; |
#endif |
|
/* Pseudo multiple issue benchmark */ |
if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) || |
(check_depend()) || (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()) |
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[or32_opcodes[current->insn_index].func_unit]--; |
issued_per_cycle--; |
} |
|
if (config.cpu.dependstats) |
/* Instruction waits in completition buffer until retired. */ |
memcpy (&icomplet[0], current, sizeof (struct iqueue_entry)); |
|
if (config.sim.history) { |
/* History of execution */ |
hist_exec_tail = hist_exec_tail->next; |
hist_exec_tail->addr = icomplet[0].insn_addr; |
} |
|
if (config.sim.exe_log) dump_exe_log(); |
} |
|
/* Store buffer analysis - stores are accumulated and commited when IO is idle */ |
static inline void sbuf_store (int cyc) { |
int delta = runtime.sim.cycles - sbuf_prev_cycles; |
sbuf_total_cyc += cyc; |
sbuf_prev_cycles = runtime.sim.cycles; |
|
//PRINTF (">STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]); |
//PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc); |
/* 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++; |
//PRINTF ("|STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]); |
} |
|
/* Store buffer analysis - previous stores should commit, before any load */ |
static inline void sbuf_load () { |
int delta = runtime.sim.cycles - sbuf_prev_cycles; |
sbuf_prev_cycles = runtime.sim.cycles; |
|
//PRINTF (">LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]); |
//PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc); |
/* 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--; |
} |
//PRINTF ("|LOAD %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]); |
} |
|
/* Outputs dissasembled instruction */ |
void dump_exe_log () |
{ |
oraddr_t insn_addr = iqueue[0].insn_addr; |
unsigned int i, 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))) { |
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", evalsim_mem8_void(insn_addr), |
evalsim_mem8_void(insn_addr + 1)); |
fprintf (runtime.sim.fexe_log, "%.2x%.2x", |
evalsim_mem8_void(insn_addr + 2), |
evalsim_mem8_void(insn_addr + 3)); |
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, reg[i]); |
} |
fprintf (runtime.sim.fexe_log, "\n"); |
fprintf (runtime.sim.fexe_log, "SR : %.8lx ", mfspr(SPR_SR)); |
fprintf (runtime.sim.fexe_log, "EPCR0: %.8lx ", mfspr(SPR_EPCR_BASE)); |
fprintf (runtime.sim.fexe_log, "EEAR0: %.8lx ", mfspr(SPR_EEAR_BASE)); |
fprintf (runtime.sim.fexe_log, "ESR0 : %.8lx\n", mfspr(SPR_ESR_BASE)); |
break; |
case EXE_LOG_SIMPLE: |
case EXE_LOG_SOFTWARE: |
{ |
extern char *disassembled; |
disassemble_index (iqueue[0].insn, iqueue[0].insn_index); |
{ |
struct label_entry *entry; |
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 = op_start[iqueue[0].insn_index]; |
|
j = 0; |
while (1) { |
operand = eval_operand_val (iqueue[0].insn, opd); |
while (!(opd->type & OPTYPE_OP)) |
opd++; |
if (opd->type & OPTYPE_DIS) { |
fprintf (runtime.sim.fexe_log, "EA =%"PRIxADDR" PA =%"PRIxADDR" ", |
insn_ea, peek_into_dtlb(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++; |
} |
while(j < 3) { |
fprintf (runtime.sim.fexe_log, " "); |
j++; |
} |
} |
fprintf (runtime.sim.fexe_log, "%"PRIxADDR" ", insn_addr); |
fprintf (runtime.sim.fexe_log, "%s\n", disassembled); |
} |
} |
} |
} |
|
/* Dump registers - 'r' or 't' command */ |
void dumpreg() |
{ |
int i; |
oraddr_t physical_pc; |
|
if ((physical_pc = peek_into_itlb(iqueue[0].insn_addr))) { |
/* |
* PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", iqueue[0].insn_addr, physical_pc); |
*/ |
dumpmemory(physical_pc, physical_pc + 4, 1, 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(pc))) { |
/* |
* PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", pc, physical_pc); |
*/ |
dumpmemory(physical_pc, physical_pc + 4, 1, 0); |
} |
else |
PRINTF("%"PRIxADDR": : xxxxxxxx ITLB miss follows", pc); |
|
PRINTF(" (next insn) %s", (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", flag); |
} |
|
/* Generated/built in decoding/executing function */ |
static inline void decode_execute (struct iqueue_entry *current); |
|
/* Wrapper around real decode_execute function -- some statistics here only */ |
static inline void decode_execute_wrapper (struct iqueue_entry *current) |
{ |
breakpoint = 0; |
|
#ifndef HAS_EXECUTION |
#error HAS_EXECUTION has to be defined in order to execute programs. |
#endif |
|
decode_execute (current); |
|
#if SET_OV_FLAG |
/* Check for range exception */ |
if (testsprbits (SPR_SR, SPR_SR_OVE) && testsprbits (SPR_SR, SPR_SR_OV)) |
except_handle (EXCEPT_RANGE, mfspr(SPR_EEAR_BASE)); |
#endif |
|
if(breakpoint) |
except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE)); |
} |
|
/* 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++) |
set_reg (i, 0); |
memset(iqueue, 0, sizeof(iqueue)); |
memset(icomplet, 0, sizeof(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; |
|
/* Cpu configuration */ |
mtspr(SPR_UPR, config.cpu.upr); |
setsprbits(SPR_VR, SPR_VR_VER, config.cpu.ver); |
setsprbits(SPR_VR, SPR_VR_REV, config.cpu.rev); |
mtspr(SPR_SR, config.cpu.sr); |
|
pcnext = 0x0; /* MM1409: All programs should start at reset vector entry! */ |
if (config.sim.verbose) PRINTF ("Starting at 0x%"PRIxADDR"\n", pcnext); |
pc = pcnext; |
pcnext += 4; |
debug(1, "reset ...\n"); |
|
/* MM1409: All programs should set their stack pointer! */ |
except_handle(EXCEPT_RESET, 0); |
update_pc(); |
except_pending = 0; |
} |
|
/* Simulates one CPU clock cycle */ |
inline int cpu_clock () |
{ |
except_pending = 0; |
next_delay_insn = 0; |
if(fetch()) { |
PRINTF ("Breakpoint hit.\n"); |
runtime.sim.cont_run = 0; /* memory breakpoint encountered */ |
return 1; |
} |
|
if(except_pending) { |
update_pc(); |
except_pending = 0; |
return 0; |
} |
|
if(breakpoint) { |
except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE)); |
update_pc(); |
except_pending = 0; |
return 0; |
} |
|
decode_execute_wrapper (&iqueue[0]); |
update_pc(); |
return 0; |
} |
|
/* 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, iqueue[0].insn_addr); |
} |
|
#if !SIMPLE_EXECUTION |
|
/* Include decode_execute function */ |
#include "execgen.c" |
|
#else /* SIMPLE_EXECUTION */ |
|
|
#define INSTRUCTION(name) void name (struct iqueue_entry *current) |
|
/* Implementation specific. |
Get an actual value of a specific register. */ |
|
static uorreg_t eval_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)MAX_RAW_RANGE) |
raw_stats.range[delta]++; |
#endif /* RAW_RANGE */ |
return reg[regno]; |
} else { |
PRINTF("\nABORT: read out of registers\n"); |
runtime.sim.cont_run = 0; |
return 0; |
} |
} |
|
/* Implementation specific. |
Evaluates source operand op_no. */ |
|
static uorreg_t eval_operand (int op_no, unsigned long insn_index, uint32_t insn) |
{ |
struct insn_op_struct *opd = 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 += eval_reg (eval_operand_val (insn, opd)); |
insn_ea = ret; |
return ret; |
} |
if (opd->type & OPTYPE_REG) |
return eval_reg (eval_operand_val (insn, opd)); |
|
return eval_operand_val (insn, opd); |
} |
|
/* Implementation specific. |
Set destination operand (reister direct) with value. */ |
|
inline static void set_operand(int op_no, orreg_t value, |
unsigned long insn_index, uint32_t insn) |
{ |
struct insn_op_struct *opd = 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); |
} |
set_reg (eval_operand_val (insn, opd), value); |
} |
|
/* Simple and rather slow decoding function based on built automata. */ |
static inline void decode_execute (struct iqueue_entry *current) |
{ |
int insn_index; |
|
current->insn_index = insn_index = insn_decode(current->insn); |
|
if (insn_index < 0) |
l_invalid(current); |
else { |
or32_opcodes[insn_index].exec(current); |
} |
if (do_stats) analysis(&iqueue[0]); |
} |
|
#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) |
|
#include "insnset.c" |
|
#endif /* !SIMPLE_EXECUTION */ |
/insnset.c
0,0 → 1,565
/* execute.c -- Instruction specific functions. |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
2000-2002 Marko Mlinar, markom@opencores.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. */ |
|
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_ov_flag (temp1); |
if (ARITH_SET_FLAG) { |
flag = temp1 == 0; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
if ((uorreg_t) temp1 < (uorreg_t) temp2) |
setsprbits(SPR_SR, SPR_SR_CY, 1); |
else |
setsprbits(SPR_SR, SPR_SR_CY, 0); |
|
temp4 = temp1; |
if (temp4 == temp1) |
or1k_mstats.byteadd++; |
} |
INSTRUCTION (l_addc) { |
orreg_t temp1, temp2, temp3; |
int8_t temp4; |
|
temp2 = (orreg_t)PARAM2; |
temp3 = (orreg_t)PARAM1; |
temp1 = temp2 + temp3 + getsprbits(SPR_SR, SPR_SR_CY); |
SET_PARAM0(temp1); |
set_ov_flag (temp1); |
if (ARITH_SET_FLAG) { |
flag = temp1 == 0; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
if ((uorreg_t) temp1 < (uorreg_t) temp2) |
setsprbits(SPR_SR, SPR_SR_CY, 1); |
else |
setsprbits(SPR_SR, SPR_SR_CY, 0); |
|
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_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 */ |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lbs) { |
int8_t val; |
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem8(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lbz) { |
uint8_t val; |
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem8(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lhs) { |
int16_t val; |
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem16(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_lhz) { |
uint16_t val; |
if (config.cpu.sbuf_len) sbuf_load (); |
val = eval_mem16(PARAM1, &breakpoint); |
/* If eval opreand produced exception don't set anything */ |
if (!except_pending) |
SET_PARAM0(val); |
} |
INSTRUCTION (l_movhi) { |
SET_PARAM0(PARAM1 << 16); |
} |
INSTRUCTION (l_and) { |
uorreg_t temp1; |
temp1 = PARAM1 & PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
if (ARITH_SET_FLAG) { |
flag = temp1 == 0; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
} |
INSTRUCTION (l_or) { |
uorreg_t temp1; |
temp1 = PARAM1 | PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
} |
INSTRUCTION (l_xor) { |
uorreg_t temp1; |
temp1 = PARAM1 ^ PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
} |
INSTRUCTION (l_sub) { |
orreg_t temp1; |
temp1 = (orreg_t)PARAM1 - (orreg_t)PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
} |
/*int mcount = 0;*/ |
INSTRUCTION (l_mul) { |
orreg_t temp1; |
|
temp1 = (orreg_t)PARAM1 * (orreg_t)PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
/*if (!(mcount++ & 1023)) { |
PRINTF ("[%i]\n",mcount); |
}*/ |
} |
INSTRUCTION (l_div) { |
orreg_t temp3, temp2, temp1; |
|
temp3 = PARAM2; |
temp2 = PARAM1; |
if (temp3) |
temp1 = temp2 / temp3; |
else { |
except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr); |
return; |
} |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
} |
INSTRUCTION (l_divu) { |
uorreg_t temp3, temp2, temp1; |
|
temp3 = PARAM2; |
temp2 = PARAM1; |
if (temp3) |
temp1 = temp2 / temp3; |
else { |
except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr); |
return; |
} |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
/* runtime.sim.cycles += 16; */ |
} |
INSTRUCTION (l_sll) { |
uorreg_t temp1; |
|
temp1 = PARAM1 << PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
/* runtime.sim.cycles += 2; */ |
} |
INSTRUCTION (l_sra) { |
orreg_t temp1; |
|
temp1 = (orreg_t)PARAM1 >> PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
/* runtime.sim.cycles += 2; */ |
} |
INSTRUCTION (l_srl) { |
uorreg_t temp1; |
temp1 = PARAM1 >> PARAM2; |
set_ov_flag (temp1); |
SET_PARAM0(temp1); |
/* runtime.sim.cycles += 2; */ |
} |
INSTRUCTION (l_bf) { |
if (config.bpb.enabled) { |
int fwd = (PARAM0 >= pc) ? 1 : 0; |
or1k_mstats.bf[flag][fwd]++; |
bpb_update(current->insn_addr, flag); |
} |
if (flag) { |
pcdelay = pc + (orreg_t)PARAM0 * 4; |
btic_update(pcnext); |
next_delay_insn = 1; |
} else { |
btic_update(pc); |
} |
} |
INSTRUCTION (l_bnf) { |
if (config.bpb.enabled) { |
int fwd = (PARAM0 >= pc) ? 1 : 0; |
or1k_mstats.bnf[!flag][fwd]++; |
bpb_update(current->insn_addr, flag == 0); |
} |
if (flag == 0) { |
pcdelay = pc + (orreg_t)PARAM0 * 4; |
btic_update(pcnext); |
next_delay_insn = 1; |
} else { |
btic_update(pc); |
} |
} |
INSTRUCTION (l_j) { |
pcdelay = pc + (orreg_t)PARAM0 * 4; |
next_delay_insn = 1; |
} |
INSTRUCTION (l_jal) { |
pcdelay = pc + (orreg_t)PARAM0 * 4; |
|
set_reg(LINK_REGNO, pc + 8); |
next_delay_insn = 1; |
if (config.sim.profile) { |
struct label_entry *tmp; |
if (verify_memoryarea(pcdelay) && (tmp = get_label (pcdelay))) |
fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n", |
runtime.sim.cycles, pc + 8, pcdelay, tmp->name); |
else |
fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n", |
runtime.sim.cycles, pc + 8, pcdelay, pcdelay); |
} |
} |
INSTRUCTION (l_jalr) { |
pcdelay = PARAM0; |
set_reg(LINK_REGNO, pc + 8); |
next_delay_insn = 1; |
} |
INSTRUCTION (l_jr) { |
pcdelay = PARAM0; |
next_delay_insn = 1; |
if (config.sim.profile) |
fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n", runtime.sim.cycles, |
pcdelay); |
} |
INSTRUCTION (l_rfe) { |
pcnext = mfspr(SPR_EPCR_BASE); |
mtspr(SPR_SR, mfspr(SPR_ESR_BASE)); |
} |
INSTRUCTION (l_nop) { |
oraddr_t stackaddr; |
uint32_t k = PARAM0; |
switch (k) { |
case NOP_NOP: |
break; |
case NOP_EXIT: |
PRINTF("exit(%"PRIdREG")\n", evalsim_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); |
if (config.debug.gdb_enabled) |
set_stall_state (1); |
else |
runtime.sim.cont_run = 0; |
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_PRINTF: |
stackaddr = evalsim_reg(4); |
simprintf(stackaddr, evalsim_reg(3)); |
debug(5, "simprintf %x\n", stackaddr); |
break; |
case NOP_REPORT: |
PRINTF("report(0x%"PRIdREG");\n", evalsim_reg(3)); |
default: |
if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST) |
PRINTF("report %i (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST, |
evalsim_reg(3)); |
break; |
} |
} |
INSTRUCTION (l_sfeq) { |
flag = PARAM0 == PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfne) { |
flag = PARAM0 != PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfgts) { |
flag = (orreg_t)PARAM0 > (orreg_t)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfges) { |
flag = (orreg_t)PARAM0 >= (orreg_t)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sflts) { |
flag = (orreg_t)PARAM0 < (orreg_t)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfles) { |
flag = (orreg_t)PARAM0 <= (orreg_t)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfgtu) { |
flag = PARAM0 > PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfgeu) { |
flag = PARAM0 >= PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfltu) { |
flag = PARAM0 < PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (l_sfleu) { |
flag = PARAM0 <= PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
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 (runtime.sim.fspr_log) { |
fprintf(runtime.sim.fspr_log, "Write to SPR : [%08"PRIx16"] <- [%08"PRIx32"]\n", regno, value); |
} |
|
if (mfspr(SPR_SR) & SPR_SR_SM) |
mtspr(regno, value); |
else { |
PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n"); |
runtime.sim.cont_run = 0; |
} |
} |
INSTRUCTION (l_mfspr) { |
uint16_t regno = PARAM1 + PARAM2; |
uorreg_t value = mfspr(regno); |
|
if (runtime.sim.fspr_log) { |
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08"PRIx16"] -> [%08"PRIx32"]\n", regno, value); |
} |
|
if (mfspr(SPR_SR) & SPR_SR_SM) |
SET_PARAM0(value); |
else { |
SET_PARAM0(0); |
PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n"); |
runtime.sim.cont_run = 0; |
} |
} |
INSTRUCTION (l_sys) { |
except_handle(EXCEPT_SYSCALL, mfspr(SPR_EEAR_BASE)); |
} |
INSTRUCTION (l_trap) { |
/* TODO: some SR related code here! */ |
except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE)); |
} |
INSTRUCTION (l_mac) { |
sprword lo, hi; |
LONGEST l; |
orreg_t x, y; |
|
lo = mfspr (SPR_MACLO); |
hi = mfspr (SPR_MACHI); |
x = PARAM0; |
y = PARAM1; |
PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); |
l = (ULONGEST)lo | ((LONGEST)hi << 32); |
l += (LONGEST) x * (LONGEST) y; |
|
/* This implementation is very fast - it needs only one cycle for mac. */ |
lo = ((ULONGEST)l) & 0xFFFFFFFF; |
hi = ((LONGEST)l) >> 32; |
mtspr (SPR_MACLO, lo); |
mtspr (SPR_MACHI, hi); |
PRINTF ("(%08lx,%08lx)\n", hi, lo); |
} |
INSTRUCTION (l_msb) { |
sprword lo, hi; |
LONGEST l; |
orreg_t x, y; |
|
lo = mfspr (SPR_MACLO); |
hi = mfspr (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; |
mtspr (SPR_MACLO, lo); |
mtspr (SPR_MACHI, hi); |
PRINTF ("(%08lx,%08lx)\n", hi, lo); |
} |
INSTRUCTION (l_macrc) { |
sprword lo, hi; |
LONGEST l; |
/* No need for synchronization here -- all MAC instructions are 1 cycle long. */ |
lo = mfspr (SPR_MACLO); |
hi = mfspr (SPR_MACHI); |
l = (ULONGEST) lo | ((LONGEST)hi << 32); |
l >>= 28; |
//PRINTF ("<%08x>\n", (unsigned long)l); |
SET_PARAM0((orreg_t)l); |
mtspr (SPR_MACLO, 0); |
mtspr (SPR_MACHI, 0); |
} |
INSTRUCTION (l_cmov) { |
SET_PARAM0(flag ? PARAM1 : PARAM2); |
} |
INSTRUCTION (l_ff1) { |
SET_PARAM0(ffs(PARAM1)); |
} |
/******* Floating point instructions *******/ |
/* Single precision */ |
INSTRUCTION (lf_add_s) { |
SET_PARAM0((float)PARAM1 + (float)PARAM2); |
} |
INSTRUCTION (lf_div_s) { |
SET_PARAM0((float)PARAM1 / (float)PARAM2); |
} |
INSTRUCTION (lf_ftoi_s) { |
// set_operand32(0, freg[get_operand(1)], &breakpoint); |
} |
INSTRUCTION (lf_itof_s) { |
// freg[get_operand(0)] = eval_operand32(1, &breakpoint); |
} |
INSTRUCTION (lf_madd_s) { |
SET_PARAM0((float)PARAM0 + (float)PARAM1 * (float)PARAM2); |
} |
INSTRUCTION (lf_mul_s) { |
SET_PARAM0((float)PARAM1 * (float)PARAM2); |
} |
INSTRUCTION (lf_rem_s) { |
float temp = (float)PARAM1 / (float)PARAM2; |
SET_PARAM0(temp - (uint32_t)temp); |
} |
INSTRUCTION (lf_sfeq_s) { |
flag = (float)PARAM0 == (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sfge_s) { |
flag = (float)PARAM0 >= (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sfgt_s) { |
flag = (float)PARAM0 > (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sfle_s) { |
flag = (float)PARAM0 <= (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sflt_s) { |
flag = (float)PARAM0 < (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sfne_s) { |
flag = (float)PARAM0 != (float)PARAM1; |
setsprbits(SPR_SR, SPR_SR_F, flag); |
} |
INSTRUCTION (lf_sub_s) { |
SET_PARAM0((float)PARAM1 - (float)PARAM2); |
} |
|
/******* 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) { |
} |
insnset.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: or32.c
===================================================================
--- or32.c (nonexistent)
+++ or32.c (revision 1765)
@@ -0,0 +1,1295 @@
+/* Table of opcodes for the OpenRISC 1000 ISA.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Damjan Lampret (lampret@opencores.org).
+
+This file is part of gen_or1k_isa, or1ksim, 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.41 2005/02/09 17:41:03 nogj
+ * Mark a simulated cpu address as such, by introducing the new oraddr_t type
+ *
+ * Revision 1.40 2005/01/27 14:14:13 nogj
+ * Remove the global op structure
+ *
+ * Revision 1.39 2005/01/27 13:35:40 nogj
+ * * Fix generate.c to produce a execgen.c with less warnings.
+ * * Fix the --enable-simple configure option.
+ *
+ * Revision 1.38 2005/01/27 13:15:50 nogj
+ * Mark wich operand is the destination operand in the architechture definition
+ *
+ * Revision 1.37 2005/01/11 15:41:58 andreje
+ * l.ff1 instruction added
+ *
+ * Revision 1.36 2004/07/22 20:17:23 phoenix
+ * removed includes
+ *
+ * Revision 1.35 2004/07/19 23:07:37 phoenix
+ * Gyorgy Jeney: extensive cleanup
+ *
+ * Revision 1.34 2004/06/27 22:56:48 lampret
+ * Updated instruction set descriptions. Changed FP instructions encoding.
+ *
+ * Revision 1.33 2004/05/09 19:52:31 lampret
+ * Changed desciption of the l.cust5 insns
+ *
+ * Revision 1.31 2003/07/01 19:34:49 csanchez
+ * Added support for l.addc instruction.
+ *
+ * Revision 1.30 2003/01/28 03:49:24 lampret
+ * Added cvs log keywords
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#ifdef HAS_EXECUTION
+# ifdef HAVE_INTTYPES_H
+# include /* ...but to get arch.h we need uint{8,16,32}_t... */
+# endif
+# include "port.h"
+# include "arch.h" /* ...but to get abstract.h, we need oraddr_t... */
+# include "abstract.h" /* To get struct iqueue_entry... */
+#endif
+#include "opcode/or32.h"
+
+/* **INDENT-OFF** */
+
+/* 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 HAS_EXECUTION
+# if SIMPLE_EXECUTION
+# define EFN &l_none
+# define EF(func) &(func)
+# define EFI &l_invalid
+# else /* SIMPLE_EXECUTION */
+# define EFN "l_none"
+# define EFI "l_invalid"
+# ifdef __GNUC__
+# define EF(func) #func
+# else
+# define EF(func) "func"
+# endif
+# endif /* SIMPLE_EXECUTION */
+#else /* HAS_EXECUTION */
+# define EFN &l_none
+# define EF(func) EFN
+# define EFI EFN
+#endif /* HAS_EXECUTION */
+
+CONST struct or32_opcode 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_unknown },
+{ "l.trap", "K", "00 0x8 01000 00000 KKKK KKKK KKKK KKKK",
+ EF(l_trap), 0, it_unknown },
+{ "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), OR32_IF_DELAY, 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 IIIII ----- AAAA AIII 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", EFI,
+ 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", EFI,
+ 0, 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 },
+{ "l.xori", "rD,rA,I", "10 0xB DDDDD AAAAA IIII IIII IIII IIII",
+ EF(l_xor), 0, it_arith },
+{ "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", EFI,
+ 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(rD),rB", "11 0x4 IIIII DDDDD BBBB BIII IIII IIII", EFI,
+ 0, it_store },
+{ "l.sw", "I(rD),rB", "11 0x5 IIIII DDDDD BBBB BIII IIII IIII",
+ EF(l_sw), 0, it_store },
+{ "l.sb", "I(rD),rB", "11 0x6 IIIII DDDDD BBBB BIII IIII IIII",
+ EF(l_sb), 0, it_store },
+{ "l.sh", "I(rD),rB", "11 0x7 IIIII DDDDD 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", EFI,
+ 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", EFI,
+ 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", EFI, 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
+
+/* **INDENT-ON** */
+
+/* Define dummy, if debug is not defined. */
+#ifndef HAS_DEBUG
+#define debug(l, fmt...) ;
+#endif
+
+CONST int num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1;
+
+/* Calculates instruction length in bytes. Always 4 for OR32. */
+int
+insn_len(int insn_index)
+{
+ insn_index = 0; /* Just to get rid that warning. */
+ return 4;
+}
+
+/* Is individual insn's operand signed or unsigned? */
+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. */
+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 = 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);
+}
+
+/* MM: Returns index of given instruction name. */
+int
+insn_index (char *insn)
+{
+ int i, found = -1;
+ for (i = 0; i < num_opcodes; i++)
+ if (!strcmp (or32_opcodes[i].name, insn))
+ {
+ found = i;
+ break;
+ }
+ return found;
+}
+
+/* Returns name of the specified instruction index */
+CONST char *
+insn_name(int index)
+{
+ if (index >= 0 && index < num_opcodes)
+ return or32_opcodes[index].name;
+ else
+ return "???";
+}
+
+#if defined(HAS_EXECUTION) && SIMPLE_EXECUTION
+void
+l_none(struct iqueue_entry *current)
+{
+}
+#else
+void
+l_none()
+{
+}
+#endif
+
+/*** Finite automata for instruction decoding building code ***/
+
+/* Find symbols in encoding. */
+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(*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 *automata;
+int nuncovered;
+int curpass = 0;
+
+/* MM: Struct that holds runtime build information about instructions. */
+struct temp_insn_struct *ti;
+
+struct insn_op_struct *op_data, **op_start;
+
+/* 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 (ti[i].in_pass == pass)
+ {
+ cur_mask &= ti[i].insn_mask;
+ ninstr++;
+ last_match = i;
+ }
+
+ debug(8, "%08X %08X\n", mask, cur_mask);
+ if (ninstr == 0)
+ return 0;
+ if (ninstr == 1)
+ {
+ /* Leaf holds instruction index. */
+ debug(8, "%i>I%i %s\n", cur - automata, last_match, 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;
+ debug(9, " (%i(%08X & %08X>>%i = %08X, %08X)",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;
+ debug(9, "!");
+ }
+ else
+ break;
+ }
+ }
+ 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 (ti[i].in_pass == pass)
+ fprintf (stderr, "%s ", or32_opcodes[i].name);
+
+ fprintf (stderr, "\n");
+ exit (1);
+ }
+ debug(8, "%i> #### %i << %i (%i) ####\n", cur - 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 (ti[j].in_pass == pass
+ && ((ti[j].insn >> best_first) & cur_mask) == (unsigned long) i
+ && ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
+ ti[j].in_pass = curpass;
+
+ debug(9, "%08X %08X %i\n", mask, cur_mask, best_first);
+ c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
+ if (c)
+ {
+ debug(8, "%i> #%X -> %u\n", next - automata, i, cur - automata);
+ *next = cur - automata;
+ cur = c;
+ }
+ else
+ {
+ debug(8, "%i> N/A\n", next - 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 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;
+ debug(9, "#%08X %08X\n", cur->type, cur->data);
+ cur++;
+ return cur;
+ }
+
+ while (*args != '\0')
+ {
+ if (*args == 'r')
+ {
+ args++;
+ type |= OPTYPE_REG;
+ if(args[1] == 'D')
+ type |= OPTYPE_DST;
+ }
+ else if (isalpha (*args))
+ {
+ unsigned long arg;
+ arg = insn_extract(*args, opcode->encoding);
+ debug(9, "%s : %08X ------\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);
+ debug(6, "|%08X %08X\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;
+ debug(9, ">%08X %08X\n", cur->type, cur->data);
+ type = 0;
+ i++;
+ args++;
+ }
+ else if (*args == OPERAND_DELIM)
+ {
+ cur--;
+ cur->type = type | cur->type | OPTYPE_OP;
+ debug(9, ">%08X %08X\n", cur->type, cur->data);
+ cur++;
+ type = 0;
+ i++;
+ args++;
+ }
+ else if (*args == '0')
+ {
+ cur->type = type;
+ cur->data = 0;
+ debug(9, ">%08X %08X\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;
+ debug(9, "#%08X %08X\n", cur->type, cur->data);
+ cur++;
+ return cur;
+}
+
+/* Constructs new automata based on or32_opcodes array. */
+
+void
+build_automata()
+{
+ int i;
+ unsigned long *end;
+ struct insn_op_struct *cur;
+
+ automata = (unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
+ ti = (struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) * num_opcodes);
+
+ nuncovered = num_opcodes;
+
+#ifdef HAS_EXECUTION
+ printf("Building automata... ");
+#endif
+
+ /* Build temporary information about instructions. */
+ for (i = 0; i < num_opcodes; i++)
+ {
+ unsigned long ones, zeros;
+ char *encoding = or32_opcodes[i].encoding;
+ ones = insn_extract('1', encoding);
+ zeros = insn_extract('0', encoding);
+ ti[i].insn_mask = ones | zeros;
+ ti[i].insn = ones;
+ ti[i].in_pass = curpass = 0;
+ /*debug(9, "%s: %s %08X %08X\n", or32_opcodes[i].name,
+ or32_opcodes[i].encoding, ti[i].insn_mask, ti[i].insn);*/
+ }
+
+ /* Until all are covered search for best criteria to separate them. */
+ end = cover_insn (automata, curpass, 0xFFFFFFFF);
+ if (end - automata > MAX_AUTOMATA_SIZE)
+ {
+ fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
+ exit (1);
+ }
+#ifdef HAS_EXECUTION
+ printf("done, num uncovered: %i/%i.\n", nuncovered, num_opcodes);
+#endif
+
+#ifdef HAS_EXECUTION
+ printf("Parsing operands data... ");
+#endif
+ op_data = (struct insn_op_struct *) malloc (MAX_OP_TABLE_SIZE * sizeof (struct insn_op_struct));
+ op_start = (struct insn_op_struct **) malloc (num_opcodes * sizeof (struct insn_op_struct *));
+ cur = op_data;
+ for (i = 0; i < num_opcodes; i++)
+ {
+ op_start[i] = cur;
+ cur = parse_params (&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 HAS_EXECUTION
+ printf("done.\n");
+#endif
+}
+
+void destruct_automata ()
+{
+ free (ti);
+ free (automata);
+ free (op_data);
+ free (op_start);
+}
+
+/* Decodes instruction and returns instruction index. */
+int insn_decode (unsigned int insn)
+{
+ unsigned long *a = automata;
+ int i;
+ while (!(*a & LEAF_FLAG))
+ {
+ unsigned int first = *a;
+ //debug(9, "%i ", a - automata);
+ a++;
+ i = (insn >> first) & *a;
+ a++;
+ if (!*(a + i))
+ { /* Invalid instruction found? */
+ //debug(9, "XXX\n", i);
+ return -1;
+ }
+ a = automata + *(a + i);
+ }
+ i = *a & ~LEAF_FLAG;
+ //debug(9, "%i\n", i);
+ /* Final check - do we have direct match?
+ (based on or32_opcodes this should be the only possibility,
+ but in case of invalid/missing instruction we must perform a check) */
+ if ((ti[i].insn_mask & insn) == ti[i].insn)
+ return i;
+ else
+ return -1;
+}
+
+static char disassembled_str[50];
+char *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
+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
+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("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(param_ch))
+ ret -= ((insn >> opc_pos) & 0x1) << param_pos;
+ else
+ ret += ((insn >> opc_pos) & 0x1) << param_pos;
+ enc++;
+ }
+ else if (isalpha(*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 = 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 = or32_extract (param_ch, encoding, insn);
+
+ imm = 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
+disassemble_insn (insn)
+ unsigned long insn;
+{
+ return disassemble_index (insn, insn_decode (insn));
+}
+
+/* Disassemble one instruction from insn index.
+ Return the size of the instruction. */
+
+int
+disassemble_index (insn, index)
+ unsigned long insn;
+ int index;
+{
+ char *dest = disassembled;
+ if (index >= 0)
+ {
+ struct or32_opcode const *opcode = &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 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 insn_len (insn);
+}
Index: Makefile.in
===================================================================
--- Makefile.in (nonexistent)
+++ Makefile.in (revision 1765)
@@ -0,0 +1,368 @@
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# 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
+#
+# 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.
+#
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+AWK = @AWK@
+BUILD_DIR = @BUILD_DIR@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPU_ARCH = @CPU_ARCH@
+DEPDIR = @DEPDIR@
+INCLUDES = @INCLUDES@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
+LOCAL_DEFS = @LOCAL_DEFS@
+MAKE_SHELL = @MAKE_SHELL@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+SUMVERSION = @SUMVERSION@
+TERMCAP_LIB = @TERMCAP_LIB@
+VERSION = @VERSION@
+am__include = @am__include@
+am__quote = @am__quote@
+host = @host@
+host_cpu = @host_cpu@
+host_os = @host_os@
+install_sh = @install_sh@
+
+noinst_LIBRARIES = libarch.a
+libarch_a_SOURCES = execute.c or32.c
+
+@SIMPLE_EXECUTION_TRUE@noinst_PROGRAMS =
+@SIMPLE_EXECUTION_FALSE@noinst_PROGRAMS = generate
+@SIMPLE_EXECUTION_TRUE@generate_SOURCES =
+@SIMPLE_EXECUTION_FALSE@generate_SOURCES = or32.c generate.c
+@SIMPLE_EXECUTION_FALSE@BUILT_SOURCES = execgen.c
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+CLEANFILES = execgen.c generate
+subdir = cpu/or32
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libarch_a_AR = $(AR) cru
+libarch_a_LIBADD =
+am_libarch_a_OBJECTS = execute.$(OBJEXT) or32.$(OBJEXT)
+libarch_a_OBJECTS = $(am_libarch_a_OBJECTS)
+@SIMPLE_EXECUTION_TRUE@noinst_PROGRAMS =
+@SIMPLE_EXECUTION_FALSE@noinst_PROGRAMS = generate$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+
+@SIMPLE_EXECUTION_TRUE@am_generate_OBJECTS =
+@SIMPLE_EXECUTION_FALSE@am_generate_OBJECTS = or32.$(OBJEXT) \
+@SIMPLE_EXECUTION_FALSE@ generate.$(OBJEXT)
+generate_OBJECTS = $(am_generate_OBJECTS)
+generate_LDADD = $(LDADD)
+generate_DEPENDENCIES =
+generate_LDFLAGS =
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/execute.Po ./$(DEPDIR)/generate.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/or32.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libarch_a_SOURCES) $(generate_SOURCES)
+DIST_COMMON = Makefile.am Makefile.in
+SOURCES = $(libarch_a_SOURCES) $(generate_SOURCES)
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu cpu/or32/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libarch.a: $(libarch_a_OBJECTS) $(libarch_a_DEPENDENCIES)
+ -rm -f libarch.a
+ $(libarch_a_AR) libarch.a $(libarch_a_OBJECTS) $(libarch_a_LIBADD)
+ $(RANLIB) libarch.a
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+generate$(EXEEXT): $(generate_OBJECTS) $(generate_DEPENDENCIES)
+ @rm -f generate$(EXEEXT)
+ $(LINK) $(generate_LDFLAGS) $(generate_OBJECTS) $(generate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or32.Po@am__quote@
+
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c `cygpath -w $<`
+CCDEPMODE = @CCDEPMODE@
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+tags: TAGS
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+
+installdirs:
+
+install: 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_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:
+ -rm -f Makefile $(CONFIG_CLEAN_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-noinstLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+uninstall-am: uninstall-info-am
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS distclean \
+ distclean-compile distclean-depend distclean-generic \
+ distclean-tags distdir dvi dvi-am info info-am install \
+ install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic tags uninstall \
+ uninstall-am uninstall-info-am
+
+
+@SIMPLE_EXECUTION_FALSE@execgen.c: generate $(srcdir)/insnset.c
+@SIMPLE_EXECUTION_FALSE@ ./generate $(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: generate.c
===================================================================
--- generate.c (nonexistent)
+++ generate.c (revision 1765)
@@ -0,0 +1,391 @@
+/* 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
+
+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 "config.h"
+#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;
+
+void 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
+}
+
+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;
+ fgets (str, sizeof (line), fi);
+ line[sizeof (line) - 1] = 0;
+ line_num++;
+ if (strncmp (str, "INSTRUCTION (", 13) == 0) {
+ char *s;
+ str += 13;
+ while (isspace (*str)) str++;
+ s = str;
+ while (*s && *s != ')') s++;
+ *s = 0;
+ while (isspace(*(s - 1))) s--;
+ *s = 0;
+ if (strcmp (str, func_name) == 0) {
+ olevel = 1;
+ str += strlen (str) + 1;
+ while (isspace (*str)) str++;
+ s = str;
+ while (*s && *s != '\n' && *s != '\r') s++;
+ *s = 0;
+ while (isspace(*(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 {
+ fgets (line, sizeof (line), fi);
+ 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 = 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, "(signed)%c += (signed)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) reg[a] = val\n");
+ set_param = 1;
+ }
+ shift_fprintf (level, fo, "#define PARAM%i 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, or32_opcodes[insn_index].function_name, level);
+
+ if (set_param)
+ shift_fprintf (level, fo, "#undef SET_PARAM\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, "insn_ea = %c;\n", 'a' + dis_op);
+
+ shift_fprintf (level, fo, "current->insn_index = %i; /* \"%s\" */\n", index,
+ insn_name (index));
+
+ shift_fprintf (level, fo, "analysis(current);\n");
+ shift_fprintf (--level, fo, "}\n");
+ if (write_to_reg)
+ shift_fprintf (level, fo, "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, "/* This file was automatically generated by generate (see cpu/or32/generate.c) */\n\n");
+ fprintf (fo, "static inline void decode_execute (struct iqueue_entry *current)\n{\n");
+ fprintf (fo, " uint32_t insn = current->insn;\n");
+ out_lines = 5;
+ 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 insn_decode, except it decodes all 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, 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, "break;\n");
+ }
+ shift_fprintf (level, fo, "}\n");
+ } else {
+ i = *a & ~LEAF_FLAG;
+
+ /* Final check - do we have direct match?
+ (based on or32_opcodes this should be the only possibility,
+ but in case of invalid/missing instruction we must perform a check) */
+
+ if (ti[i].insn_mask != cur_mask) {
+ shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", ti[i].insn_mask, cur_mask);
+ shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n",
+ ti[i].insn_mask, ti[i].insn);
+ }
+ shift_fprintf (level, fo, "/* Instruction: %s */\n", or32_opcodes[i].name);
+
+ output_call (fo, i, level);
+
+ if (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);
+ }
+
+ build_automata ();
+ if (generate_header (fo)) {
+ fprintf (stderr, "generate_header\n");
+ return 1;
+ }
+
+ if (generate_body (fo, automata, 0, 1)) {
+ fprintf (stderr, "generate_body\n");
+ return 1;
+ }
+
+ if (generate_footer (fo)) {
+ fprintf (stderr, "generate_footer\n");
+ return 1;
+ }
+
+ fclose (fo);
+ destruct_automata ();
+ return 0;
+}
+
generate.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 1765)
@@ -0,0 +1,40 @@
+# Makefile -- Makefile for OR32 dependent simulation
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.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.
+#
+
+noinst_LIBRARIES = libarch.a
+libarch_a_SOURCES = execute.c or32.c
+
+if SIMPLE_EXECUTION
+noinst_PROGRAMS =
+generate_SOURCES =
+
+else
+noinst_PROGRAMS = generate
+generate_SOURCES = or32.c generate.c
+BUILT_SOURCES = execgen.c
+
+execgen.c: generate $(srcdir)/insnset.c
+ ./generate $(srcdir)/insnset.c execgen.c
+
+endif
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+CLEANFILES=execgen.c generate
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 1765)
.
Property changes :
Added: svn:ignore
## -0,0 +1,3 ##
+Makefile
+.deps
+generate