URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/tags/or1ksim/or1ksim-0.4.0/cpu/or32
- from Rev 127 to Rev 135
- ↔ Reverse comparison
Rev 127 → Rev 135
/or32.c
0,0 → 1,1310
/* Table of opcodes for the OpenRISC 1000 ISA. |
|
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. |
Copyright (C) 2008 Embecosm Limited |
|
Contributed by Damjan Lampret (lampret@opencores.org). |
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com> |
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator. |
This file is also part of gen_or1k_isa, GDB and GAS. |
|
This program is free software; you can redistribute it and/or modify it |
under the terms of the GNU General Public License as published by the Free |
Software Foundation; either version 3 of the License, or (at your option) |
any later version. |
|
This program is distributed in the hope that it will be useful, but WITHOUT |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
more details. |
|
You should have received a copy of the GNU General Public License along |
with this program. If not, see <http://www.gnu.org/licenses/>. */ |
|
/* This program is commented throughout in a fashion suitable for processing |
with Doxygen. */ |
|
|
/* Autoconf and/or portability configuration */ |
#include "config.h" |
#include "port.h" |
|
/* System includes */ |
#include <stdlib.h> |
#include <stdio.h> |
|
/* Package includes */ |
#include "opcode/or32.h" |
|
/* We treat all letters the same in encode/decode routines so |
we need to assign some characteristics to them like signess etc.*/ |
CONST struct or32_letter or32_letters[] = { |
{'A', NUM_UNSIGNED}, |
{'B', NUM_UNSIGNED}, |
{'D', NUM_UNSIGNED}, |
{'I', NUM_SIGNED}, |
{'K', NUM_UNSIGNED}, |
{'L', NUM_UNSIGNED}, |
{'N', NUM_SIGNED}, |
{'0', NUM_UNSIGNED}, |
{'\0', 0} /* dummy entry */ |
}; |
|
/* Opcode encoding: |
machine[31:30]: first two bits of opcode |
00 - neither of source operands is GPR |
01 - second source operand is GPR (rB) |
10 - first source operand is GPR (rA) |
11 - both source operands are GPRs (rA and rB) |
machine[29:26]: next four bits of opcode |
machine[25:00]: instruction operands (specific to individual instruction) |
|
Recommendation: irrelevant instruction bits should be set with a value of |
bits in same positions of instruction preceding current instruction in the |
code (when assembling). |
*/ |
|
#ifdef HAVE_EXECUTION |
# if SIMPLE_EXECUTION |
# define EFN &l_none |
# define EF(func) &(func) |
# define EFI &l_invalid |
# elif COMPLEX_EXECUTION |
# define EFN "l_none" |
# define EFI "l_invalid" |
# ifdef __GNUC__ |
# define EF(func) #func |
# else |
# define EF(func) "func" |
# endif |
# else /* DYNAMIC_EXECUTION */ |
# define EFN &l_none |
# define EF(func) &(gen_ ##func) |
# define EFI &gen_l_invalid |
# endif |
#else /* HAVE_EXECUTION */ |
# define EFN &l_none |
# define EF(func) EFN |
# define EFI EFN |
#endif /* HAVE_EXECUTION */ |
|
CONST struct or32_opcode or32_opcodes[] = { |
|
{"l.j", "N", "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NNNN", |
EF (l_j), OR32_IF_DELAY, it_jump}, |
{"l.jal", "N", "00 0x1 NNNNN NNNNN NNNN NNNN NNNN NNNN", |
EF (l_jal), OR32_IF_DELAY, it_jump}, |
{"l.bnf", "N", "00 0x3 NNNNN NNNNN NNNN NNNN NNNN NNNN", |
EF (l_bnf), OR32_IF_DELAY | OR32_R_FLAG, it_branch}, |
{"l.bf", "N", "00 0x4 NNNNN NNNNN NNNN NNNN NNNN NNNN", |
EF (l_bf), OR32_IF_DELAY | OR32_R_FLAG, it_branch}, |
{"l.nop", "K", "00 0x5 01--- ----- KKKK KKKK KKKK KKKK", |
EF (l_nop), 0, it_nop}, |
{"l.movhi", "rD,K", "00 0x6 DDDDD ----0 KKKK KKKK KKKK KKKK", |
EF (l_movhi), 0, it_movimm}, |
{"l.macrc", "rD", "00 0x6 DDDDD ----1 0000 0000 0000 0000", |
EF (l_macrc), 0, it_mac}, |
{"l.sys", "K", "00 0x8 00000 00000 KKKK KKKK KKKK KKKK", |
EF (l_sys), 0, it_exception}, |
{"l.trap", "K", "00 0x8 01000 00000 KKKK KKKK KKKK KKKK", |
EF (l_trap), 0, it_exception}, |
{"l.msync", "", "00 0x8 10000 00000 0000 0000 0000 0000", EFN, |
0, it_unknown}, |
{"l.psync", "", "00 0x8 10100 00000 0000 0000 0000 0000", EFN, |
0, it_unknown}, |
{"l.csync", "", "00 0x8 11000 00000 0000 0000 0000 0000", EFN, |
0, it_unknown}, |
{"l.rfe", "", "00 0x9 ----- ----- ---- ---- ---- ----", |
EF (l_rfe), 0, it_exception}, |
{"lv.all_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0, |
it_unknown}, |
{"lv.all_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0, |
it_unknown}, |
{"lv.all_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0, |
it_unknown}, |
{"lv.all_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0, |
it_unknown}, |
{"lv.all_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x4", EFI, 0, |
it_unknown}, |
{"lv.all_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x5", EFI, 0, |
it_unknown}, |
{"lv.all_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0, |
it_unknown}, |
{"lv.all_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0, |
it_unknown}, |
{"lv.all_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x8", EFI, 0, |
it_unknown}, |
{"lv.all_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x9", EFI, 0, |
it_unknown}, |
{"lv.all_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xA", EFI, 0, |
it_unknown}, |
{"lv.all_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xB", EFI, 0, |
it_unknown}, |
{"lv.any_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x0", EFI, 0, |
it_unknown}, |
{"lv.any_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x1", EFI, 0, |
it_unknown}, |
{"lv.any_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x2", EFI, 0, |
it_unknown}, |
{"lv.any_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x3", EFI, 0, |
it_unknown}, |
{"lv.any_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x4", EFI, 0, |
it_unknown}, |
{"lv.any_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x5", EFI, 0, |
it_unknown}, |
{"lv.any_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x6", EFI, 0, |
it_unknown}, |
{"lv.any_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x7", EFI, 0, |
it_unknown}, |
{"lv.any_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x8", EFI, 0, |
it_unknown}, |
{"lv.any_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x9", EFI, 0, |
it_unknown}, |
{"lv.any_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xA", EFI, 0, |
it_unknown}, |
{"lv.any_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xB", EFI, 0, |
it_unknown}, |
{"lv.add.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x0", EFI, 0, |
it_unknown}, |
{"lv.add.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x1", EFI, 0, |
it_unknown}, |
{"lv.adds.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x2", EFI, 0, |
it_unknown}, |
{"lv.adds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x3", EFI, 0, |
it_unknown}, |
{"lv.addu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x4", EFI, 0, |
it_unknown}, |
{"lv.addu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x5", EFI, 0, |
it_unknown}, |
{"lv.addus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x6", EFI, 0, |
it_unknown}, |
{"lv.addus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x7", EFI, 0, |
it_unknown}, |
{"lv.and", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x8", EFI, 0, |
it_unknown}, |
{"lv.avg.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x9", EFI, 0, |
it_unknown}, |
{"lv.avg.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0xA", EFI, 0, |
it_unknown}, |
{"lv.cmp_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x0", EFI, 0, |
it_unknown}, |
{"lv.cmp_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x1", EFI, 0, |
it_unknown}, |
{"lv.cmp_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x2", EFI, 0, |
it_unknown}, |
{"lv.cmp_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x3", EFI, 0, |
it_unknown}, |
{"lv.cmp_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x4", EFI, 0, |
it_unknown}, |
{"lv.cmp_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x5", EFI, 0, |
it_unknown}, |
{"lv.cmp_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x6", EFI, 0, |
it_unknown}, |
{"lv.cmp_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x7", EFI, 0, |
it_unknown}, |
{"lv.cmp_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x8", EFI, 0, |
it_unknown}, |
{"lv.cmp_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x9", EFI, 0, |
it_unknown}, |
{"lv.cmp_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xA", EFI, 0, |
it_unknown}, |
{"lv.cmp_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xB", EFI, 0, |
it_unknown}, |
{"lv.madds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x4", EFI, 0, |
it_unknown}, |
{"lv.max.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x5", EFI, 0, |
it_unknown}, |
{"lv.max.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x6", EFI, 0, |
it_unknown}, |
{"lv.merge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x7", EFI, 0, |
it_unknown}, |
{"lv.merge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x8", EFI, 0, |
it_unknown}, |
{"lv.min.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x9", EFI, 0, |
it_unknown}, |
{"lv.min.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xA", EFI, 0, |
it_unknown}, |
{"lv.msubs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xB", EFI, 0, |
it_unknown}, |
{"lv.muls.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xC", EFI, 0, |
it_unknown}, |
{"lv.nand", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xD", EFI, 0, |
it_unknown}, |
{"lv.nor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xE", EFI, 0, |
it_unknown}, |
{"lv.or", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xF", EFI, 0, |
it_unknown}, |
{"lv.pack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x0", EFI, 0, |
it_unknown}, |
{"lv.pack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x1", EFI, 0, |
it_unknown}, |
{"lv.packs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x2", EFI, 0, |
it_unknown}, |
{"lv.packs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x3", EFI, 0, |
it_unknown}, |
{"lv.packus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x4", EFI, 0, |
it_unknown}, |
{"lv.packus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x5", EFI, 0, |
it_unknown}, |
{"lv.perm.n", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x6", EFI, 0, |
it_unknown}, |
{"lv.rl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x7", EFI, 0, |
it_unknown}, |
{"lv.rl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x8", EFI, 0, |
it_unknown}, |
{"lv.sll.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x9", EFI, 0, |
it_unknown}, |
{"lv.sll.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xA", EFI, 0, |
it_unknown}, |
{"lv.sll", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xB", EFI, 0, |
it_unknown}, |
{"lv.srl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xC", EFI, 0, |
it_unknown}, |
{"lv.srl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xD", EFI, 0, |
it_unknown}, |
{"lv.sra.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xE", EFI, 0, |
it_unknown}, |
{"lv.sra.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xF", EFI, 0, |
it_unknown}, |
{"lv.srl", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x0", EFI, 0, |
it_unknown}, |
{"lv.sub.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x1", EFI, 0, |
it_unknown}, |
{"lv.sub.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x2", EFI, 0, |
it_unknown}, |
{"lv.subs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x3", EFI, 0, |
it_unknown}, |
{"lv.subs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x4", EFI, 0, |
it_unknown}, |
{"lv.subu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x5", EFI, 0, |
it_unknown}, |
{"lv.subu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x6", EFI, 0, |
it_unknown}, |
{"lv.subus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x7", EFI, 0, |
it_unknown}, |
{"lv.subus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x8", EFI, 0, |
it_unknown}, |
{"lv.unpack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x9", EFI, 0, |
it_unknown}, |
{"lv.unpack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xA", EFI, 0, |
it_unknown}, |
{"lv.xor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xB", EFI, 0, |
it_unknown}, |
{"lv.cust1", "", "00 0xA ----- ----- ---- ---- 0xC ----", EFI, 0, |
it_unknown}, |
{"lv.cust2", "", "00 0xA ----- ----- ---- ---- 0xD ----", EFI, 0, |
it_unknown}, |
{"lv.cust3", "", "00 0xA ----- ----- ---- ---- 0xE ----", EFI, 0, |
it_unknown}, |
{"lv.cust4", "", "00 0xA ----- ----- ---- ---- 0xF ----", EFI, 0, |
it_unknown}, |
|
{"l.jr", "rB", "01 0x1 ----- ----- BBBB B--- ---- ----", |
EF (l_jr), OR32_IF_DELAY, it_jump}, |
{"l.jalr", "rB", "01 0x2 ----- ----- BBBB B--- ---- ----", |
EF (l_jalr), OR32_IF_DELAY, it_jump}, |
{"l.maci", "rA,I", "01 0x3 ----- AAAAA IIII IIII IIII IIII", |
EF (l_mac), 0, it_mac}, |
{"l.cust1", "", "01 0xC ----- ----- ---- ---- ---- ----", |
EF (l_cust1), 0, it_unknown}, |
{"l.cust2", "", "01 0xD ----- ----- ---- ---- ---- ----", |
EF (l_cust2), 0, it_unknown}, |
{"l.cust3", "", "01 0xE ----- ----- ---- ---- ---- ----", |
EF (l_cust3), 0, it_unknown}, |
{"l.cust4", "", "01 0xF ----- ----- ---- ---- ---- ----", |
EF (l_cust4), 0, it_unknown}, |
|
{"l.ld", "rD,I(rA)", "10 0x0 DDDDD AAAAA IIII IIII IIII IIII", EFI, |
0, it_load}, |
{"l.lwz", "rD,I(rA)", "10 0x1 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lwz), 0, it_load}, |
{"l.lws", "rD,I(rA)", "10 0x2 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lws), 0, it_load}, |
{"l.lbz", "rD,I(rA)", "10 0x3 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lbz), 0, it_load}, |
{"l.lbs", "rD,I(rA)", "10 0x4 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lbs), 0, it_load}, |
{"l.lhz", "rD,I(rA)", "10 0x5 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lhz), 0, it_load}, |
{"l.lhs", "rD,I(rA)", "10 0x6 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_lhs), 0, it_load}, |
|
{"l.addi", "rD,rA,I", "10 0x7 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_add), OR32_W_FLAG, it_arith}, |
{"l.addic", "rD,rA,I", "10 0x8 DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_addc), OR32_W_FLAG, it_arith}, |
{"l.andi", "rD,rA,K", "10 0x9 DDDDD AAAAA KKKK KKKK KKKK KKKK", |
EF (l_and), OR32_W_FLAG, it_arith}, |
{"l.ori", "rD,rA,K", "10 0xA DDDDD AAAAA KKKK KKKK KKKK KKKK", |
EF (l_or), 0, it_arith}, |
#if HAVE_UNSIGNED_XORI |
{"l.xori", "rD,rA,K", "10 0xB DDDDD AAAAA KKKK KKKK KKKK KKKK", |
EF (l_xor), 0, it_arith}, |
#else |
{"l.xori", "rD,rA,I", "10 0xB DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_xor), 0, it_arith}, |
#endif |
{"l.muli", "rD,rA,I", "10 0xC DDDDD AAAAA IIII IIII IIII IIII", |
EF (l_mul), 0, it_arith}, |
{"l.mfspr", "rD,rA,K", "10 0xD DDDDD AAAAA KKKK KKKK KKKK KKKK", |
EF (l_mfspr), 0, it_move}, |
{"l.slli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 00LL LLLL", |
EF (l_sll), 0, it_shift}, |
{"l.srli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 01LL LLLL", |
EF (l_srl), 0, it_shift}, |
{"l.srai", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 10LL LLLL", |
EF (l_sra), 0, it_shift}, |
{"l.rori", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 11LL LLLL", |
EF (l_ror), 0, it_shift}, |
|
{"l.sfeqi", "rA,I", "10 0xF 00000 AAAAA IIII IIII IIII IIII", |
EF (l_sfeq), OR32_W_FLAG, it_compare}, |
{"l.sfnei", "rA,I", "10 0xF 00001 AAAAA IIII IIII IIII IIII", |
EF (l_sfne), OR32_W_FLAG, it_compare}, |
{"l.sfgtui", "rA,I", "10 0xF 00010 AAAAA IIII IIII IIII IIII", |
EF (l_sfgtu), OR32_W_FLAG, it_compare}, |
{"l.sfgeui", "rA,I", "10 0xF 00011 AAAAA IIII IIII IIII IIII", |
EF (l_sfgeu), OR32_W_FLAG, it_compare}, |
{"l.sfltui", "rA,I", "10 0xF 00100 AAAAA IIII IIII IIII IIII", |
EF (l_sfltu), OR32_W_FLAG, it_compare}, |
{"l.sfleui", "rA,I", "10 0xF 00101 AAAAA IIII IIII IIII IIII", |
EF (l_sfleu), OR32_W_FLAG, it_compare}, |
{"l.sfgtsi", "rA,I", "10 0xF 01010 AAAAA IIII IIII IIII IIII", |
EF (l_sfgts), OR32_W_FLAG, it_compare}, |
{"l.sfgesi", "rA,I", "10 0xF 01011 AAAAA IIII IIII IIII IIII", |
EF (l_sfges), OR32_W_FLAG, it_compare}, |
{"l.sfltsi", "rA,I", "10 0xF 01100 AAAAA IIII IIII IIII IIII", |
EF (l_sflts), OR32_W_FLAG, it_compare}, |
{"l.sflesi", "rA,I", "10 0xF 01101 AAAAA IIII IIII IIII IIII", |
EF (l_sfles), OR32_W_FLAG, it_compare}, |
|
{"l.mtspr", "rA,rB,K", "11 0x0 KKKKK AAAAA BBBB BKKK KKKK KKKK", |
EF (l_mtspr), 0, it_move}, |
{"l.mac", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x1", |
EF (l_mac), 0, it_mac}, |
{"l.msb", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x2", |
EF (l_msb), 0, it_mac}, |
|
{"lf.add.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x0", |
EF (lf_add_s), 0, it_float}, |
{"lf.sub.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x1", |
EF (lf_sub_s), 0, it_float}, |
{"lf.mul.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x2", |
EF (lf_mul_s), 0, it_float}, |
{"lf.div.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x3", |
EF (lf_div_s), 0, it_float}, |
{"lf.itof.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x4", |
EF (lf_itof_s), 0, it_float}, |
{"lf.ftoi.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x5", |
EF (lf_ftoi_s), 0, it_float}, |
{"lf.rem.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x6", |
EF (lf_rem_s), 0, it_float}, |
{"lf.madd.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x7", |
EF (lf_madd_s), 0, it_float}, |
{"lf.sfeq.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x8", |
EF (lf_sfeq_s), 0, it_float}, |
{"lf.sfne.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x9", |
EF (lf_sfne_s), 0, it_float}, |
{"lf.sfgt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xA", |
EF (lf_sfgt_s), 0, it_float}, |
{"lf.sfge.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xB", |
EF (lf_sfge_s), 0, it_float}, |
{"lf.sflt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xC", |
EF (lf_sflt_s), 0, it_float}, |
{"lf.sfle.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xD", |
EF (lf_sfle_s), 0, it_float}, |
{"lf.cust1.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xD ----", EFI, |
0, it_float}, |
|
{"lf.add.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0, |
it_float}, |
{"lf.sub.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0, |
it_float}, |
{"lf.mul.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0, |
it_float}, |
{"lf.div.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0, |
it_float}, |
{"lf.itof.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x4", EFI, 0, |
it_float}, |
{"lf.ftoi.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x5", EFI, 0, |
it_float}, |
{"lf.rem.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0, |
it_float}, |
{"lf.madd.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0, |
it_float}, |
{"lf.sfeq.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x8", EFI, 0, |
it_float}, |
{"lf.sfne.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x9", EFI, 0, |
it_float}, |
{"lf.sfgt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xA", EFI, 0, |
it_float}, |
{"lf.sfge.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xB", EFI, 0, |
it_float}, |
{"lf.sflt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xC", EFI, 0, |
it_float}, |
{"lf.sfle.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xD", EFI, 0, |
it_float}, |
{"lf.cust1.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xE ----", EFI, 0, |
it_float}, |
|
{"l.sd", "I(rA),rB", "11 0x4 IIIII AAAAA BBBB BIII IIII IIII", EFI, |
0, it_store}, |
{"l.sw", "I(rA),rB", "11 0x5 IIIII AAAAA BBBB BIII IIII IIII", |
EF (l_sw), 0, it_store}, |
{"l.sb", "I(rA),rB", "11 0x6 IIIII AAAAA BBBB BIII IIII IIII", |
EF (l_sb), 0, it_store}, |
{"l.sh", "I(rA),rB", "11 0x7 IIIII AAAAA BBBB BIII IIII IIII", |
EF (l_sh), 0, it_store}, |
|
{"l.add", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x0", |
EF (l_add), OR32_W_FLAG, it_arith}, |
{"l.addc", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x1", |
EF (l_addc), OR32_W_FLAG, it_arith}, |
{"l.sub", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x2", |
EF (l_sub), 0, it_arith}, |
{"l.and", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x3", |
EF (l_and), OR32_W_FLAG, it_arith}, |
{"l.or", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x4", |
EF (l_or), 0, it_arith}, |
{"l.xor", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x5", |
EF (l_xor), 0, it_arith}, |
{"l.mul", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x6", |
EF (l_mul), 0, it_arith}, |
|
{"l.sll", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 00-- 0x8", |
EF (l_sll), 0, it_shift}, |
{"l.srl", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 01-- 0x8", |
EF (l_srl), 0, it_shift}, |
{"l.sra", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 10-- 0x8", |
EF (l_sra), 0, it_shift}, |
{"l.ror", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 11-- 0x8", |
EF (l_ror), 0, it_shift}, |
{"l.div", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x9", |
EF (l_div), 0, it_arith}, |
{"l.divu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xA", |
EF (l_divu), 0, it_arith}, |
{"l.mulu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xB", |
EF (l_mulu), 0, it_arith}, |
{"l.extbs", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xC", |
EF (l_extbs), 0, it_move}, |
{"l.exths", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xC", |
EF (l_exths), 0, it_move}, |
{"l.extws", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xD", |
EF (l_extws), 0, it_move}, |
{"l.extbz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 11-- 0xC", |
EF (l_extbz), 0, it_move}, |
{"l.exthz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 10-- 0xC", |
EF (l_exthz), 0, it_move}, |
{"l.extwz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xD", |
EF (l_extwz), 0, it_move}, |
{"l.cmov", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0xE", |
EF (l_cmov), OR32_R_FLAG, it_move}, |
{"l.ff1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 ---- 0xF", |
EF (l_ff1), 0, it_arith}, |
{"l.fl1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --01 ---- 0xF", |
EF (l_fl1), 0, it_arith}, |
|
{"l.sfeq", "rA,rB", "11 0x9 00000 AAAAA BBBB B--- ---- ----", |
EF (l_sfeq), OR32_W_FLAG, it_compare}, |
{"l.sfne", "rA,rB", "11 0x9 00001 AAAAA BBBB B--- ---- ----", |
EF (l_sfne), OR32_W_FLAG, it_compare}, |
{"l.sfgtu", "rA,rB", "11 0x9 00010 AAAAA BBBB B--- ---- ----", |
EF (l_sfgtu), OR32_W_FLAG, it_compare}, |
{"l.sfgeu", "rA,rB", "11 0x9 00011 AAAAA BBBB B--- ---- ----", |
EF (l_sfgeu), OR32_W_FLAG, it_compare}, |
{"l.sfltu", "rA,rB", "11 0x9 00100 AAAAA BBBB B--- ---- ----", |
EF (l_sfltu), OR32_W_FLAG, it_compare}, |
{"l.sfleu", "rA,rB", "11 0x9 00101 AAAAA BBBB B--- ---- ----", |
EF (l_sfleu), OR32_W_FLAG, it_compare}, |
{"l.sfgts", "rA,rB", "11 0x9 01010 AAAAA BBBB B--- ---- ----", |
EF (l_sfgts), OR32_W_FLAG, it_compare}, |
{"l.sfges", "rA,rB", "11 0x9 01011 AAAAA BBBB B--- ---- ----", |
EF (l_sfges), OR32_W_FLAG, it_compare}, |
{"l.sflts", "rA,rB", "11 0x9 01100 AAAAA BBBB B--- ---- ----", |
EF (l_sflts), OR32_W_FLAG, it_compare}, |
{"l.sfles", "rA,rB", "11 0x9 01101 AAAAA BBBB B--- ---- ----", |
EF (l_sfles), OR32_W_FLAG, it_compare}, |
|
{"l.cust5", "rD,rA,rB,L,K", "11 0xC DDDDD AAAAA BBBB BLLL LLLK KKKK", EFI, |
0, it_unknown}, |
{"l.cust6", "", "11 0xD ----- ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust7", "", "11 0xE ----- ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust8", "", "11 0xF ----- ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
|
/* This section should not be defined in or1ksim, since it contains duplicates, |
which would cause machine builder to complain. */ |
#ifdef HAS_CUST |
{"l.cust5_1", "rD", "11 0xC DDDDD ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust5_2", "rD,rA", "11 0xC DDDDD AAAAA ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust5_3", "rD,rA,rB", "11 0xC DDDDD AAAAA BBBB B--- ---- ----", EFI, |
0, it_unknown}, |
|
{"l.cust6_1", "rD", "11 0xD DDDDD ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust6_2", "rD,rA", "11 0xD DDDDD AAAAA ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust6_3", "rD,rA,rB", "11 0xD DDDDD AAAAA BBBB B--- ---- ----", EFI, |
0, it_unknown}, |
|
{"l.cust7_1", "rD", "11 0xE DDDDD ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust7_2", "rD,rA", "11 0xE DDDDD AAAAA ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust7_3", "rD,rA,rB", "11 0xE DDDDD AAAAA BBBB B--- ---- ----", EFI, |
0, it_unknown}, |
|
{"l.cust8_1", "rD", "11 0xF DDDDD ----- ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust8_2", "rD,rA", "11 0xF DDDDD AAAAA ---- ---- ---- ----", EFI, |
0, it_unknown}, |
{"l.cust8_3", "rD,rA,rB", "11 0xF DDDDD AAAAA BBBB B--- ---- ----", EFI, |
0, it_unknown}, |
#endif |
|
{"", "", "", EFI, 0, 0} /* Dummy entry, not included in num_opcodes. This |
* lets code examine entry i+1 without checking |
* if we've run off the end of the table. */ |
}; |
|
#undef EFI |
#undef EFN |
#undef EF |
|
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(HAVE_EXECUTION) && SIMPLE_EXECUTION |
void |
l_none (struct iqueue_entry *current) |
{ |
} |
#elif defined(HAVE_EXECUTION) && DYNAMIC_EXECUTION |
void |
l_none (struct op_queue *opq, int *param_t, int delay_slot) |
{ |
} |
#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; |
|
static void |
or32_debug (int level, const char *format, ...) |
{ |
#if DEBUG |
char *p; |
va_list ap; |
|
if ((p = malloc (1000)) == NULL) |
return; |
va_start (ap, format); |
(void) vsnprintf (p, 1000, format, ap); |
va_end (ap); |
printf ("%s\n", p); |
fflush (stdout); |
free (p); |
#endif |
} |
|
/* Recursive utility function used to find best match and to build automata. */ |
static unsigned long * |
cover_insn (unsigned long *cur, int pass, unsigned int mask) |
{ |
int best_first = 0, best_len = 0, i, last_match = -1, ninstr = 0; |
unsigned long cur_mask = mask; |
unsigned long *next; |
|
for (i = 0; i < num_opcodes; i++) |
if (ti[i].in_pass == pass) |
{ |
cur_mask &= ti[i].insn_mask; |
ninstr++; |
last_match = i; |
} |
|
or32_debug (8, "%08X %08lX\n", mask, cur_mask); |
if (ninstr == 0) |
return 0; |
if (ninstr == 1) |
{ |
/* Leaf holds instruction index. */ |
or32_debug (8, "%i>I%i %s\n", cur - 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; |
or32_debug (9, " (%i(%08lX & %08lX>>%i = %08lX, %08lX)", len, m, |
cur_mask, i, (cur_mask >> (unsigned) i), |
(cur_mask >> (unsigned) i) & m); |
if ((m & (cur_mask >> (unsigned) i)) == m) |
{ |
best_len = len; |
best_first = i; |
or32_debug (9, "!"); |
} |
else |
break; |
} |
} |
or32_debug (9, "\n"); |
if (!best_len) |
{ |
fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr, |
mask); |
for (i = 0; i < num_opcodes; i++) |
if (ti[i].in_pass == pass) |
fprintf (stderr, "%s ", or32_opcodes[i].name); |
|
fprintf (stderr, "\n"); |
exit (1); |
} |
or32_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; |
|
or32_debug (9, "%08X %08lX %i\n", mask, cur_mask, best_first); |
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first))); |
if (c) |
{ |
or32_debug (8, "%i> #%X -> %u\n", next - automata, i, |
cur - automata); |
*next = cur - automata; |
cur = c; |
} |
else |
{ |
or32_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; |
or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data); |
cur++; |
return cur; |
} |
|
while (*args != '\0') |
{ |
if (*args == 'r') |
{ |
args++; |
type |= OPTYPE_REG; |
if (*args == 'D') |
type |= OPTYPE_DST; |
} |
else if (isalpha (*args)) |
{ |
unsigned long arg; |
arg = insn_extract (*args, opcode->encoding); |
or32_debug (9, "%s : %08lX ------\n", opcode->name, arg); |
if (letter_signed (*args)) |
{ |
type |= OPTYPE_SIG; |
type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT; |
} |
|
num_cur_op = 0; |
/* Split argument to sequences of consecutive ones. */ |
while (arg) |
{ |
int shr = 0; |
unsigned long tmp = arg, mask = 0; |
while ((tmp & 1) == 0) |
{ |
shr++; |
tmp >>= 1; |
} |
while (tmp & 1) |
{ |
mask++; |
tmp >>= 1; |
} |
cur->type = type | shr; |
cur->data = mask; |
arg &= ~(((1 << mask) - 1) << shr); |
or32_debug (6, "|%08lX %08lX\n", cur->type, cur->data); |
cur++; |
num_cur_op++; |
} |
args++; |
} |
else if (*args == '(') |
{ |
/* Next param is displacement. Later we will treat them as one operand. */ |
/* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this |
* operand */ |
while (num_cur_op > 0) |
{ |
cur[-num_cur_op].type |= type | OPTYPE_DIS; |
num_cur_op--; |
} |
cur[-1].type |= OPTYPE_OP; |
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data); |
type = 0; |
i++; |
args++; |
} |
else if (*args == OPERAND_DELIM) |
{ |
cur--; |
cur->type = type | cur->type | OPTYPE_OP; |
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data); |
cur++; |
type = 0; |
i++; |
args++; |
} |
else if (*args == '0') |
{ |
cur->type = type; |
cur->data = 0; |
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data); |
cur++; |
type = 0; |
i++; |
args++; |
} |
else if (*args == ')') |
args++; |
else |
{ |
fprintf (stderr, "%s : parse error in args.\n", opcode->name); |
exit (1); |
} |
} |
cur--; |
cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST; |
or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data); |
cur++; |
return cur; |
} |
|
/* Constructs new automata based on 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 HAVE_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 HAVE_EXECUTION |
printf ("done, num uncovered: %i/%i.\n", nuncovered, num_opcodes); |
#endif |
|
#ifdef HAVE_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 HAVE_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); |
} |
or32.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: insnset.c
===================================================================
--- insnset.c (nonexistent)
+++ insnset.c (revision 135)
@@ -0,0 +1,937 @@
+/* insnset.c -- Instruction specific functions.
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ 2000-2002 Marko Mlinar, markom@opencores.org
+ Copyright (C) 2008 Embecosm Limited
+ Copyright (C) 2009 Jungsook yang, jungsook.yang@uci.edu
+
+ Contributor Jeremy Bennett
+ Contributor Julius Baxter julius@orsoc.se
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+INSTRUCTION (l_add) {
+ orreg_t temp1, temp2, temp3;
+ int8_t temp4;
+
+ temp2 = (orreg_t)PARAM2;
+ temp3 = (orreg_t)PARAM1;
+ temp1 = temp2 + temp3;
+ SET_PARAM0 (temp1);
+
+ /* Set overflow if two negative values gave a positive sum, or if two
+ positive values gave a negative sum. Otherwise clear it */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the result is smaller than
+ either operand (if it smaller than one, it will be smaller than both, so
+ we need only test one). */
+ if ((uorreg_t) temp1 < (uorreg_t) temp2)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+
+ temp4 = temp1;
+ if (temp4 == temp1)
+ or1k_mstats.byteadd++;
+}
+INSTRUCTION (l_addc) {
+ orreg_t temp1, temp2, temp3;
+ int8_t temp4;
+ int carry_in = (cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY;
+
+ temp2 = (orreg_t)PARAM2;
+ temp3 = (orreg_t)PARAM1;
+ temp1 = temp2 + temp3;
+
+ if(carry_in)
+ {
+ temp1++; /* Add in the carry bit */
+ }
+
+ SET_PARAM0(temp1);
+
+ /* Set overflow if two negative values gave a positive sum, or if two
+ positive values gave a negative sum. Otherwise clear it. There are no
+ corner cases with the extra bit carried in (unlike the carry flag - see
+ below). */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the result is smaller than
+ either operand (if it smaller than one, it will be smaller than both, so
+ we need only test one). If there is a carry in, the test should be less
+ than or equal, to deal with the 0 + 0xffffffff + c = 0 case (which
+ generates a carry). */
+ if ((carry_in && ((uorreg_t) temp1 <= (uorreg_t) temp2)) ||
+ ((uorreg_t) temp1 < (uorreg_t) temp2))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+
+ temp4 = temp1;
+ if (temp4 == temp1)
+ or1k_mstats.byteadd++;
+}
+INSTRUCTION (l_sw) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem32(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t - old_cyc);
+ }
+}
+INSTRUCTION (l_sb) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem8(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t- old_cyc);
+ }
+}
+INSTRUCTION (l_sh) {
+ int old_cyc = 0;
+ if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
+ set_mem16(PARAM0, PARAM1, &breakpoint);
+ if (config.cpu.sbuf_len) {
+ int t = runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = old_cyc;
+ sbuf_store (t - old_cyc);
+ }
+}
+INSTRUCTION (l_lws) {
+ uint32_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem32(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lwz) {
+ uint32_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem32(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lbs) {
+ int8_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem8(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lbz) {
+ uint8_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem8(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lhs) {
+ int16_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem16(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_lhz) {
+ uint16_t val;
+ if (config.cpu.sbuf_len) sbuf_load ();
+ val = eval_mem16(PARAM1, &breakpoint);
+ /* If eval operand produced exception don't set anything. JPB changed to
+ trigger on breakpoint, as well as except_pending (seemed to be a bug). */
+ if (!(except_pending || breakpoint))
+ SET_PARAM0(val);
+}
+INSTRUCTION (l_movhi) {
+ SET_PARAM0(PARAM1 << 16);
+}
+INSTRUCTION (l_and) {
+ uorreg_t temp1;
+ temp1 = PARAM1 & PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_or) {
+ uorreg_t temp1;
+ temp1 = PARAM1 | PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_xor) {
+ /* The argument is now specified as unsigned, but historically OR1K has
+ always treated the argument as signed (so l.xori rD,rA,-1 can be used in
+ the absence of l.not). Use this as the default behavior. This is
+ controlled from or32.c. */
+ uorreg_t temp1 = PARAM1 ^ PARAM2;
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_sub) {
+ orreg_t temp1, temp2, temp3;
+
+ temp3 = (orreg_t)PARAM2;
+ temp2 = (orreg_t)PARAM1;
+ temp1 = temp2 - temp3;
+ SET_PARAM0 (temp1);
+
+ /* Set overflow if a negative value minus a positive value gave a positive
+ sum, or if a positive value minus a negative value gave a negative
+ sum. Otherwise clear it */
+ if ((((long int) temp2 < 0) &&
+ ((long int) temp3 >= 0) &&
+ ((long int) temp1 >= 0)) ||
+ (((long int) temp2 >= 0) &&
+ ((long int) temp3 < 0) &&
+ ((long int) temp1 < 0)))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* Set the carry flag if (as unsigned values) the second operand is greater
+ than the first. */
+ if ((uorreg_t) temp3 > (uorreg_t) temp2)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+/*int mcount = 0;*/
+INSTRUCTION (l_mul) {
+ orreg_t temp0, temp1, temp2;
+ LONGEST ltemp0, ltemp1, ltemp2;
+ ULONGEST ultemp0, ultemp1, ultemp2;
+
+ /* Args in 32-bit */
+ temp2 = (orreg_t) PARAM2;
+ temp1 = (orreg_t) PARAM1;
+
+ /* Compute initially in 64-bit */
+ ltemp1 = (LONGEST) temp1;
+ ltemp2 = (LONGEST) temp2;
+ ltemp0 = ltemp1 * ltemp2;
+
+ temp0 = (orreg_t) (ltemp0 & 0xffffffffLL);
+ SET_PARAM0 (temp0);
+
+ /* We have 2's complement overflow, if the result is less than the smallest
+ possible 32-bit negative number, or greater than the largest possible
+ 32-bit positive number. */
+ if ((ltemp0 < (LONGEST) INT32_MIN) || (ltemp0 > (LONGEST) INT32_MAX))
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_OV;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+ }
+
+ /* We have 1's complement overflow, if, as an unsigned operation, the result
+ is greater than the largest possible 32-bit unsigned number. This is
+ probably quicker than unpicking the bits of the signed result. */
+ ultemp1 = (ULONGEST) temp1 & 0xffffffffULL;
+ ultemp2 = (ULONGEST) temp2 & 0xffffffffULL;
+ ultemp0 = ultemp1 * ultemp2;
+
+ if (ultemp0 > (ULONGEST) UINT32_MAX)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_OV) == SPR_SR_OV))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_mulu) {
+ uorreg_t temp0, temp1, temp2;
+ ULONGEST ultemp0, ultemp1, ultemp2;
+
+ /* Args in 32-bit */
+ temp2 = (uorreg_t) PARAM2;
+ temp1 = (uorreg_t) PARAM1;
+
+ /* Compute initially in 64-bit */
+ ultemp1 = (ULONGEST) temp1 & 0xffffffffULL;
+ ultemp2 = (ULONGEST) temp2 & 0xffffffffULL;
+ ultemp0 = ultemp1 * ultemp2;
+
+ temp0 = (uorreg_t) (ultemp0 & 0xffffffffULL);
+ SET_PARAM0 (temp0);
+
+ /* We never have 2's complement overflow */
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV;
+
+ /* We have 1's complement overflow, if the result is greater than the
+ largest possible 32-bit unsigned number. */
+ if (ultemp0 > (ULONGEST) UINT32_MAX)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+}
+INSTRUCTION (l_div) {
+ orreg_t temp3, temp2, temp1;
+
+ temp3 = (orreg_t) PARAM2;
+ temp2 = (orreg_t) PARAM1;
+
+ /* Check for divide by zero (sets carry) */
+ if (0 == temp3)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ temp1 = temp2 / temp3;
+ SET_PARAM0(temp1);
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV; /* Never set */
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_divu) {
+ uorreg_t temp3, temp2, temp1;
+
+ temp3 = (uorreg_t) PARAM2;
+ temp2 = (uorreg_t) PARAM1;
+
+ /* Check for divide by zero (sets carry) */
+ if (0 == temp3)
+ {
+ cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
+ }
+ else
+ {
+ temp1 = temp2 / temp3;
+ SET_PARAM0(temp1);
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
+ }
+
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV; /* Never set */
+
+ /* Trigger a range exception if the overflow flag is set and the SR[OVE] bit
+ is set. */
+ if (((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) == SPR_SR_OVE) &&
+ ((cpu_state.sprs[SPR_SR] & SPR_SR_CY) == SPR_SR_CY))
+ {
+ except_handle (EXCEPT_RANGE, cpu_state.pc);
+ }
+}
+INSTRUCTION (l_sll) {
+ uorreg_t temp1;
+
+ temp1 = PARAM1 << PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_sra) {
+ orreg_t temp1;
+
+ temp1 = (orreg_t)PARAM1 >> PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_srl) {
+ uorreg_t temp1;
+ temp1 = PARAM1 >> PARAM2;
+ SET_PARAM0(temp1);
+ /* runtime.sim.cycles += 2; */
+}
+INSTRUCTION (l_ror) {
+ uorreg_t temp1;
+ temp1 = PARAM1 >> (PARAM2 & 0x1f);
+ temp1 |= PARAM1 << (32 - (PARAM2 & 0x1f));
+ SET_PARAM0(temp1);
+}
+INSTRUCTION (l_bf) {
+ if (config.bpb.enabled) {
+ int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
+ or1k_mstats.bf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0][fwd]++;
+ bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
+ }
+ if(cpu_state.sprs[SPR_SR] & SPR_SR_F) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ btic_update(pcnext);
+ next_delay_insn = 1;
+ } else {
+ btic_update(cpu_state.pc);
+ }
+}
+INSTRUCTION (l_bnf) {
+ if (config.bpb.enabled) {
+ int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
+ or1k_mstats.bnf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1][fwd]++;
+ bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1);
+ }
+ if (!(cpu_state.sprs[SPR_SR] & SPR_SR_F)) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ btic_update(pcnext);
+ next_delay_insn = 1;
+ } else {
+ btic_update(cpu_state.pc);
+ }
+}
+INSTRUCTION (l_j) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+ next_delay_insn = 1;
+}
+INSTRUCTION (l_jal) {
+ cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
+
+ setsim_reg(LINK_REGNO, cpu_state.pc + 8);
+ next_delay_insn = 1;
+ if (config.sim.profile) {
+ struct label_entry *tmp;
+ if (verify_memoryarea(cpu_state.pc_delay) && (tmp = get_label (cpu_state.pc_delay)))
+ fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n",
+ runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
+ tmp->name);
+ else
+ fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n",
+ runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
+ cpu_state.pc_delay);
+ }
+}
+INSTRUCTION (l_jalr) {
+ /* Badly aligned destination or use of link register triggers an exception */
+ uorreg_t temp1 = PARAM0;
+
+ if (REG_PARAM0 == LINK_REGNO)
+ {
+ except_handle (EXCEPT_ILLEGAL, cpu_state.pc);
+ }
+ else if ((temp1 & 0x3) != 0)
+ {
+ except_handle (EXCEPT_ALIGN, cpu_state.pc);
+ }
+ else
+ {
+ cpu_state.pc_delay = temp1;
+ setsim_reg(LINK_REGNO, cpu_state.pc + 8);
+ next_delay_insn = 1;
+ }
+}
+INSTRUCTION (l_jr) {
+ /* Badly aligned destination triggers an exception */
+ uorreg_t temp1 = PARAM0;
+
+ if ((temp1 & 0x3) != 0)
+ {
+ except_handle (EXCEPT_ALIGN, cpu_state.pc);
+ }
+ else
+ {
+ cpu_state.pc_delay = temp1;
+ next_delay_insn = 1;
+
+ if (config.sim.profile)
+ {
+ fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n",
+ runtime.sim.cycles, cpu_state.pc_delay);
+ }
+ }
+}
+INSTRUCTION (l_rfe) {
+ pcnext = cpu_state.sprs[SPR_EPCR_BASE];
+ mtspr(SPR_SR, cpu_state.sprs[SPR_ESR_BASE]);
+}
+INSTRUCTION (l_nop) {
+ uint32_t k = PARAM0;
+ switch (k) {
+ case NOP_NOP:
+ break;
+ case NOP_EXIT:
+ 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
+ sim_done();
+ break;
+ case NOP_CNT_RESET:
+ PRINTF("****************** counters reset ******************\n");
+ PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
+ PRINTF("****************** counters reset ******************\n");
+ runtime.sim.reset_cycles = runtime.sim.cycles;
+ runtime.cpu.reset_instructions = runtime.cpu.instructions;
+ break;
+ case NOP_PUTC: /*JPB */
+ printf( "%c", (char)(evalsim_reg( 3 ) & 0xff));
+ fflush( stdout );
+ break;
+ case NOP_GET_TICKS:
+ cpu_state.reg[11] = runtime.sim.cycles & 0xffffffff;
+ cpu_state.reg[12] = runtime.sim.cycles >> 32;
+ break;
+ case NOP_GET_PS:
+ cpu_state.reg[11] = config.sim.clkcycle_ps;
+ break;
+ case NOP_REPORT:
+ PRINTF("report(0x%"PRIxREG");\n", evalsim_reg(3));
+ default:
+ if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST)
+ PRINTF("report %" PRIdREG " (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST,
+ evalsim_reg(3));
+ break;
+ }
+}
+INSTRUCTION (l_sfeq) {
+ if(PARAM0 == PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfne) {
+ if(PARAM0 != PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgts) {
+ if((orreg_t)PARAM0 > (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfges) {
+ if((orreg_t)PARAM0 >= (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sflts) {
+ if((orreg_t)PARAM0 < (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfles) {
+ if((orreg_t)PARAM0 <= (orreg_t)PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgtu) {
+ if(PARAM0 > PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfgeu) {
+ if(PARAM0 >= PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfltu) {
+ if(PARAM0 < PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_sfleu) {
+ if(PARAM0 <= PARAM1)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+}
+INSTRUCTION (l_extbs) {
+ int8_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_extbz) {
+ uint8_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_exths) {
+ int16_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_exthz) {
+ uint16_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_extws) {
+ int32_t x;
+ x = PARAM1;
+ SET_PARAM0((orreg_t)x);
+}
+INSTRUCTION (l_extwz) {
+ uint32_t x;
+ x = PARAM1;
+ SET_PARAM0((uorreg_t)x);
+}
+INSTRUCTION (l_mtspr) {
+ uint16_t regno = PARAM0 | PARAM2;
+ uorreg_t value = PARAM1;
+
+ if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
+ mtspr(regno, value);
+ else {
+ PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n");
+ sim_done();
+ }
+}
+INSTRUCTION (l_mfspr) {
+ uint16_t regno = PARAM1 | PARAM2;
+ uorreg_t value = mfspr(regno);
+
+ if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
+ SET_PARAM0(value);
+ else {
+ SET_PARAM0(0);
+ PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n");
+ sim_done();
+ }
+}
+INSTRUCTION (l_sys) {
+ except_handle(EXCEPT_SYSCALL, cpu_state.sprs[SPR_EEAR_BASE]);
+}
+INSTRUCTION (l_trap) {
+ /* TODO: some SR related code here! */
+ except_handle(EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
+}
+INSTRUCTION (l_mac) {
+ uorreg_t lo, hi;
+ LONGEST l;
+ orreg_t x, y, t;
+
+ lo = cpu_state.sprs[SPR_MACLO];
+ hi = cpu_state.sprs[SPR_MACHI];
+ x = PARAM0;
+ y = PARAM1;
+/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
+
+ /* Compute the temporary as (signed) 32-bits, then sign-extend to 64 when
+ adding in. */
+ l = (ULONGEST)lo | ((LONGEST)hi << 32);
+ t = x * y;
+ l += (LONGEST) t;
+
+ /* This implementation is very fast - it needs only one cycle for mac. */
+ lo = ((ULONGEST)l) & 0xFFFFFFFF;
+ hi = ((LONGEST)l) >> 32;
+ cpu_state.sprs[SPR_MACLO] = lo;
+ cpu_state.sprs[SPR_MACHI] = hi;
+/* PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo); */
+}
+INSTRUCTION (l_msb) {
+ uorreg_t lo, hi;
+ LONGEST l;
+ orreg_t x, y;
+
+ lo = cpu_state.sprs[SPR_MACLO];
+ hi = cpu_state.sprs[SPR_MACHI];
+ x = PARAM0;
+ y = PARAM1;
+
+/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
+
+ l = (ULONGEST)lo | ((LONGEST)hi << 32);
+ l -= x * y;
+
+ /* This implementation is very fast - it needs only one cycle for msb. */
+ lo = ((ULONGEST)l) & 0xFFFFFFFF;
+ hi = ((LONGEST)l) >> 32;
+ cpu_state.sprs[SPR_MACLO] = lo;
+ cpu_state.sprs[SPR_MACHI] = hi;
+/* PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo); */
+}
+INSTRUCTION (l_macrc) {
+ orreg_t lo;
+ /* No need for synchronization here -- all MAC instructions are 1 cycle long. */
+ lo = cpu_state.sprs[SPR_MACLO];
+ //PRINTF ("<%08x>\n", (unsigned long)l);
+ SET_PARAM0(lo);
+ cpu_state.sprs[SPR_MACLO] = 0;
+ cpu_state.sprs[SPR_MACHI] = 0;
+}
+INSTRUCTION (l_cmov) {
+ SET_PARAM0(cpu_state.sprs[SPR_SR] & SPR_SR_F ? PARAM1 : PARAM2);
+}
+INSTRUCTION (l_ff1) {
+ SET_PARAM0(ffs(PARAM1));
+}
+INSTRUCTION (l_fl1) {
+ orreg_t t = (orreg_t)PARAM1;
+
+ /* Reverse the word and use ffs */
+ t = (((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1));
+ t = (((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2));
+ t = (((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4));
+ t = (((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8));
+ t = ffs ((t >> 16) | (t << 16));
+
+ SET_PARAM0 (0 == t ? t : 33 - t);
+}
+/******* Floating point instructions *******/
+/* Single precision */
+INSTRUCTION (lf_add_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1, param2;
+ param1.hval = (uorreg_t)PARAM1;
+ param2.hval = (uorreg_t)PARAM2;
+ param0.fval = param1.fval + param2.fval;
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_div_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1, param2;
+ param1.hval = (uorreg_t)PARAM1;
+ param2.hval = (uorreg_t)PARAM2;
+ param0.fval = param1.fval / param2.fval;
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_ftoi_s) {
+ if (config.cpu.hardfloat) {
+ // no other way appeared to work --jb
+ float tmp_f; memcpy((void*)&tmp_f, (void*)&PARAM1, sizeof(float));
+ SET_PARAM0((int)tmp_f);
+ } else l_invalid();
+}
+INSTRUCTION (lf_itof_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0;
+ param0.fval = (float)((int)PARAM1);
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_madd_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0,param1, param2;
+ param0.hval = (uorreg_t)PARAM0;
+ param1.hval = (uorreg_t)PARAM1;
+ param2.hval = PARAM2;
+ param0.fval += param1.fval * param2.fval;
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_mul_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1, param2;
+ param1.hval = (uorreg_t)PARAM1;
+ param2.hval = (uorreg_t)PARAM2;
+ param0.fval = param1.fval * param2.fval;
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_rem_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1, param2;
+ param1.hval = PARAM1;
+ param2.hval = PARAM2;
+ param0.fval = fmodf (param1.fval, param2.fval);
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfeq_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval == param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfge_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval >= param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfgt_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval > param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfle_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval <= param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sflt_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval < param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sfne_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1;
+ param0.hval = PARAM0;
+ param1.hval = PARAM1;
+ if(param0.fval != param1.fval)
+ cpu_state.sprs[SPR_SR] |= SPR_SR_F;
+ else
+ cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
+ } else l_invalid();
+}
+INSTRUCTION (lf_sub_s) {
+ if (config.cpu.hardfloat) {
+ FLOAT param0, param1, param2;
+ param1.hval = PARAM1;
+ param2.hval = PARAM2;
+ param0.fval = param1.fval - param2.fval;
+ SET_PARAM0(param0.hval);
+ } else l_invalid();
+}
+
+/******* Custom instructions *******/
+INSTRUCTION (l_cust1) {
+ /*int destr = current->insn >> 21;
+ int src1r = current->insn >> 15;
+ int src2r = current->insn >> 9;*/
+}
+INSTRUCTION (l_cust2) {
+}
+INSTRUCTION (l_cust3) {
+}
+INSTRUCTION (l_cust4) {
+}
+INSTRUCTION (lf_cust1) {
+}
insnset.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: execute.c
===================================================================
--- execute.c (nonexistent)
+++ execute.c (revision 135)
@@ -0,0 +1,1174 @@
+/* execute.c -- OR1K architecture dependent simulation
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+/* Most of the OR1K simulation is done in here.
+
+ When SIMPLE_EXECUTION is defined below a file insnset.c is included!
+*/
+
+/* Autoconf and/or portability configuration */
+#include "config.h"
+#include "port.h"
+
+/* System includes */
+#include
+
+/* Package includes */
+#include "execute.h"
+#include "toplevel-support.h"
+#include "except.h"
+#include "labels.h"
+#include "gdbcomm.h"
+#include "sched.h"
+#include "stats.h"
+#include "opcode/or32.h"
+#include "dmmu.h"
+#include "immu.h"
+#include "sim-cmd.h"
+#include "vapi.h"
+#include "debug-unit.h"
+#include "branch-predict.h"
+#include "sprs.h"
+#include "rsp-server.h"
+
+
+/* Includes and macros for simple execution */
+#if SIMPLE_EXECUTION
+
+#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
+
+#define PARAM0 eval_operand(0, current->insn_index, current->insn)
+#define PARAM1 eval_operand(1, current->insn_index, current->insn)
+#define PARAM2 eval_operand(2, current->insn_index, current->insn)
+
+#define INSTRUCTION(name) void name (struct iqueue_entry *current)
+
+#endif /* SIMPLE_EXECUTION */
+
+
+/*! Current cpu state. Globally available. */
+struct cpu_state cpu_state;
+
+/*! Temporary program counter. Globally available */
+oraddr_t pcnext;
+
+/*! Num cycles waiting for stores to complete. Globally available */
+int sbuf_wait_cyc = 0;
+
+/*! Number of total store cycles. Globally available */
+int sbuf_total_cyc = 0;
+
+/*! Whether we are doing statistical analysis. Globally available */
+int do_stats = 0;
+
+/*! History of execution. Globally available */
+struct hist_exec *hist_exec_tail = NULL;
+
+/* Benchmark multi issue execution. This file only */
+static int multissue[20];
+static int issued_per_cycle = 4;
+
+/* Store buffer analysis - stores are accumulated and commited when IO is
+ idle. This file only */
+static int sbuf_head = 0;
+static int sbuf_tail = 0;
+static int sbuf_count = 0;
+#if !(DYNAMIC_EXECUTION)
+static int sbuf_buf[MAX_SBUF_LEN] = { 0 };
+#endif
+
+static int sbuf_prev_cycles = 0;
+
+/* Variables used throughout this file to share information */
+static int breakpoint;
+static int next_delay_insn;
+
+/* Forward declaration of static functions */
+#if !(DYNAMIC_EXECUTION)
+static void decode_execute (struct iqueue_entry *current);
+#endif
+
+/*---------------------------------------------------------------------------*/
+/*!Get an actual value of a specific register
+
+ Implementation specific. Abort if we are given a duff register. Only used
+ externally to support simprintf(), which is now obsolete.
+
+ @param[in] regno The register of interest
+
+ @return The value of the register */
+/*---------------------------------------------------------------------------*/
+uorreg_t
+evalsim_reg (unsigned int regno)
+{
+ if (regno < MAX_GPRS)
+ {
+#if RAW_RANGE_STATS
+ int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
+
+ if ((unsigned long) delta < (unsigned long) RAW_RANGE)
+ {
+ raw_stats.range[delta]++;
+ }
+#endif /* RAW_RANGE */
+
+ return cpu_state.reg[regno];
+ }
+ else
+ {
+ PRINTF ("\nABORT: read out of registers\n");
+ sim_done ();
+ return 0;
+ }
+} /* evalsim_reg() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Set a specific register with value
+
+ Implementation specific. Abort if we are given a duff register.
+
+ @param[in] regno The register of interest
+ @param[in] value The value to be set */
+/*---------------------------------------------------------------------------*/
+void
+setsim_reg (unsigned int regno,
+ uorreg_t value)
+{
+ if (regno == 0) /* gpr0 is always zero */
+ {
+ value = 0;
+ }
+
+ if (regno < MAX_GPRS)
+ {
+ cpu_state.reg[regno] = value;
+ }
+ else
+ {
+ PRINTF ("\nABORT: write out of registers\n");
+ sim_done ();
+ }
+
+#if RAW_RANGE_STATS
+ raw_stats.reg[regno] = runtime.sim.cycles;
+#endif /* RAW_RANGE */
+
+} /* setsim_reg() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Evaluates source operand operand
+
+ Implementation specific. Declared global, although this is only actually
+ required for DYNAMIC_EXECUTION,
+
+ @param[in] insn The instruction
+ @param[in] opd The operand
+
+ @return The value of the source operand */
+/*---------------------------------------------------------------------------*/
+uorreg_t
+eval_operand_val (uint32_t insn,
+ struct insn_op_struct *opd)
+{
+ unsigned long operand = 0;
+ unsigned long sbit;
+ unsigned int nbits = 0;
+
+ while (1)
+ {
+ operand |=
+ ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
+ nbits;
+ nbits += opd->data;
+
+ if (opd->type & OPTYPE_OP)
+ {
+ break;
+ }
+
+ opd++;
+ }
+
+ if (opd->type & OPTYPE_SIG)
+ {
+ sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+
+ if (operand & (1 << sbit))
+ {
+ operand |= ~REG_C (0) << sbit;
+ }
+ }
+
+ return operand;
+
+} /* eval_operand_val() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Does source operand depend on computation of dest operand?
+
+ Cycle t Cycle t+1
+ dst: irrelevant src: immediate always 0
+ dst: reg1 direct src: reg2 direct 0 if reg1 != reg2
+ dst: reg1 disp src: reg2 direct always 0
+ dst: reg1 direct src: reg2 disp 0 if reg1 != reg2
+ dst: reg1 disp src: reg2 disp always 1 (store must
+ finish before load)
+ dst: flag src: flag always 1
+
+ @param[in] prev Previous instruction
+ @param[in] next Next instruction
+
+ @return Non-zero if yes. */
+/*---------------------------------------------------------------------------*/
+static int
+check_depend (struct iqueue_entry *prev,
+ struct iqueue_entry *next)
+{
+ /* Find destination type. */
+ unsigned long type = 0;
+ int prev_dis;
+ int next_dis;
+ orreg_t prev_reg_val = 0;
+ struct insn_op_struct *opd;
+
+ if (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;
+
+} /* check_depend() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Should instruction NOT be executed?
+
+ Modified by CZ 26/05/01 for new mode execution.
+
+ @return Nonzero if instruction should NOT be executed */
+/*---------------------------------------------------------------------------*/
+static int
+fetch ()
+{
+ static int break_just_hit = 0;
+
+ if (NULL != breakpoints)
+ {
+ /* MM: Check for breakpoint. This has to be done in fetch cycle,
+ because of peripheria.
+ MM1709: if we cannot access the memory entry, we could not set the
+ breakpoint earlier, so just check the breakpoint list. */
+ if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit)
+ {
+ break_just_hit = 1;
+ return 1; /* Breakpoint set. */
+ }
+ break_just_hit = 0;
+ }
+
+ breakpoint = 0;
+ cpu_state.iqueue.insn_addr = cpu_state.pc;
+ cpu_state.iqueue.insn = eval_insn (cpu_state.pc, &breakpoint);
+
+ /* Fetch instruction. */
+ if (!except_pending)
+ {
+ runtime.cpu.instructions++;
+ }
+
+ /* update_pc will be called after execution */
+ return 0;
+
+} /* fetch() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!This code actually updates the PC value */
+/*---------------------------------------------------------------------------*/
+static void
+update_pc ()
+{
+ cpu_state.delay_insn = next_delay_insn;
+ cpu_state.sprs[SPR_PPC] = cpu_state.pc; /* Store value for later */
+ cpu_state.pc = pcnext;
+ pcnext = cpu_state.delay_insn ? cpu_state.pc_delay :
+ pcnext + 4;
+} /* update_pc() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Perform analysis of the instruction being executed
+
+ This could be static for SIMPLE_EXECUTION, but made global for general use.
+
+ @param[in] current The instruction being executed */
+/*---------------------------------------------------------------------------*/
+void
+analysis (struct iqueue_entry *current)
+{
+ if (config.cpu.dependstats)
+ {
+ /* Dynamic, dependency stats. */
+ adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
+ check_depend (&cpu_state.icomplet, current));
+
+ /* Dynamic, functional units stats. */
+ addfstats (or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
+ or32_opcodes[current->insn_index].func_unit, 1,
+ check_depend (&cpu_state.icomplet, current));
+
+ /* Dynamic, single stats. */
+ addsstats (current->insn_index, 1);
+ }
+
+ if (config.cpu.superscalar)
+ {
+ if ((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;
+
+ /* Pseudo multiple issue benchmark */
+ if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) ||
+ (check_depend (&cpu_state.icomplet, current))
+ || (issued_per_cycle < 1))
+ {
+ int i;
+ for (i = 0; i < 20; i++)
+ multissue[i] = 2;
+ issued_per_cycle = 2;
+ runtime.cpu.supercycles++;
+ if (check_depend (&cpu_state.icomplet, current))
+ runtime.cpu.hazardwait++;
+ multissue[it_unknown] = 2;
+ multissue[it_shift] = 2;
+ multissue[it_compare] = 1;
+ multissue[it_branch] = 1;
+ multissue[it_jump] = 1;
+ multissue[it_extend] = 2;
+ multissue[it_nop] = 2;
+ multissue[it_move] = 2;
+ multissue[it_movimm] = 2;
+ multissue[it_arith] = 2;
+ multissue[it_store] = 2;
+ multissue[it_load] = 2;
+ }
+ multissue[or32_opcodes[current->insn_index].func_unit]--;
+ issued_per_cycle--;
+ }
+
+ if (config.cpu.dependstats)
+ /* Instruction waits in completition buffer until retired. */
+ memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry));
+
+ if (config.sim.history)
+ {
+ /* History of execution */
+ hist_exec_tail = hist_exec_tail->next;
+ hist_exec_tail->addr = cpu_state.icomplet.insn_addr;
+ }
+
+ if (config.sim.exe_log)
+ dump_exe_log ();
+
+} /* analysis() */
+
+
+#if !(DYNAMIC_EXECUTION)
+
+/*---------------------------------------------------------------------------*/
+/*!Store buffer analysis for store instructions
+
+ Stores are accumulated and commited when IO is idle
+
+ @param[in] cyc Number of cycles being analysed */
+/*---------------------------------------------------------------------------*/
+static void
+sbuf_store (int cyc)
+{
+ int delta = runtime.sim.cycles - sbuf_prev_cycles;
+
+ sbuf_total_cyc += cyc;
+ sbuf_prev_cycles = runtime.sim.cycles;
+
+ /* Take stores from buffer, that occured meanwhile */
+ while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
+ {
+ delta -= sbuf_buf[sbuf_tail];
+ sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
+ sbuf_count--;
+ }
+
+ if (sbuf_count)
+ {
+ sbuf_buf[sbuf_tail] -= delta;
+ }
+
+ /* Store buffer is full, take one out */
+ if (sbuf_count >= config.cpu.sbuf_len)
+ {
+ sbuf_wait_cyc += sbuf_buf[sbuf_tail];
+ runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
+ sbuf_prev_cycles += sbuf_buf[sbuf_tail];
+ sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
+ sbuf_count--;
+ }
+
+ /* Put newest store in the buffer */
+ sbuf_buf[sbuf_head] = cyc;
+ sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN;
+ sbuf_count++;
+
+} /* sbuf_store() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Store buffer analysis for load instructions
+
+ Previous stores should commit, before any load */
+/*---------------------------------------------------------------------------*/
+static void
+sbuf_load ()
+{
+ int delta = runtime.sim.cycles - sbuf_prev_cycles;
+ sbuf_prev_cycles = runtime.sim.cycles;
+
+ /* Take stores from buffer, that occured meanwhile */
+ while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
+ {
+ delta -= sbuf_buf[sbuf_tail];
+ sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
+ sbuf_count--;
+ }
+
+ if (sbuf_count)
+ {
+ sbuf_buf[sbuf_tail] -= delta;
+ }
+
+ /* Wait for all stores to complete */
+ while (sbuf_count > 0)
+ {
+ sbuf_wait_cyc += sbuf_buf[sbuf_tail];
+ runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
+ sbuf_prev_cycles += sbuf_buf[sbuf_tail];
+ sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
+ sbuf_count--;
+ }
+} /* sbuf_load() */
+
+#endif /* !DYNAMIC_EXECUTION */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Outputs dissasembled instruction */
+/*---------------------------------------------------------------------------*/
+void
+dump_exe_log ()
+{
+ oraddr_t insn_addr = cpu_state.iqueue.insn_addr;
+ unsigned int i;
+ unsigned int j;
+ uorreg_t operand;
+
+ if (insn_addr == 0xffffffff)
+ {
+ return;
+ }
+
+ if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
+ ((config.sim.exe_log_end <= 0) ||
+ (runtime.cpu.instructions <= config.sim.exe_log_end)))
+ {
+ struct label_entry *entry;
+
+ if (config.sim.exe_log_marker &&
+ !(runtime.cpu.instructions % config.sim.exe_log_marker))
+ {
+ fprintf (runtime.sim.fexe_log,
+ "--------------------- %8lli instruction "
+ "---------------------\n",
+ runtime.cpu.instructions);
+ }
+
+ switch (config.sim.exe_log_type)
+ {
+ case EXE_LOG_HARDWARE:
+ fprintf (runtime.sim.fexe_log,
+ "\nEXECUTED(%11llu): %" PRIxADDR ": ",
+ runtime.cpu.instructions, insn_addr);
+ fprintf (runtime.sim.fexe_log, "%.2x%.2x",
+ eval_direct8 (insn_addr, 0, 0),
+ eval_direct8 (insn_addr + 1, 0, 0));
+ fprintf (runtime.sim.fexe_log, "%.2x%.2x",
+ eval_direct8 (insn_addr + 2, 0, 0),
+ eval_direct8 (insn_addr + 3, 0, 0));
+
+ for (i = 0; i < MAX_GPRS; i++)
+ {
+ if (i % 4 == 0)
+ {
+ fprintf (runtime.sim.fexe_log, "\n");
+ }
+
+ fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG " ", i,
+ cpu_state.reg[i]);
+ }
+
+ fprintf (runtime.sim.fexe_log, "\n");
+ fprintf (runtime.sim.fexe_log, "SR : %.8" PRIx32 " ",
+ cpu_state.sprs[SPR_SR]);
+ fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR " ",
+ cpu_state.sprs[SPR_EPCR_BASE]);
+ fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR " ",
+ cpu_state.sprs[SPR_EEAR_BASE]);
+ fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n",
+ cpu_state.sprs[SPR_ESR_BASE]);
+ break;
+
+ case EXE_LOG_SIMPLE:
+ case EXE_LOG_SOFTWARE:
+ disassemble_index (cpu_state.iqueue.insn,
+ cpu_state.iqueue.insn_index);
+
+ entry = get_label (insn_addr);
+ if (entry)
+ {
+ fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
+ }
+
+ if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
+ {
+ struct insn_op_struct *opd =
+ op_start[cpu_state.iqueue.insn_index];
+
+ j = 0;
+ while (1)
+ {
+ operand = eval_operand_val (cpu_state.iqueue.insn, opd);
+ while (!(opd->type & OPTYPE_OP))
+ {
+ opd++;
+ }
+ if (opd->type & OPTYPE_DIS)
+ {
+ fprintf (runtime.sim.fexe_log,
+ "EA =%" PRIxADDR " PA =%" PRIxADDR " ",
+ cpu_state.insn_ea,
+ peek_into_dtlb (cpu_state.insn_ea, 0, 0));
+ opd++; /* Skip of register operand */
+ j++;
+ }
+ else if ((opd->type & OPTYPE_REG) && operand)
+ {
+ fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ",
+ (int) operand, evalsim_reg (operand));
+ }
+ else
+ {
+ fprintf (runtime.sim.fexe_log, " ");
+ }
+ j++;
+ if (opd->type & OPTYPE_LAST)
+ {
+ break;
+ }
+ opd++;
+ }
+ if (or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
+ {
+ fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ",
+ cpu_state.sprs[SPR_SR]);
+ j++;
+ }
+ while (j < 3)
+ {
+ fprintf (runtime.sim.fexe_log, " ");
+ j++;
+ }
+ }
+ fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr);
+ fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
+ }
+ }
+} /* dump_exe_log() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Dump registers
+
+ Supports the CLI 'r' and 't' commands */
+/*---------------------------------------------------------------------------*/
+void
+dumpreg ()
+{
+ int i;
+ oraddr_t physical_pc;
+
+ if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
+ {
+ disassemble_memory (physical_pc, physical_pc + 4, 0);
+ }
+ else
+ {
+ PRINTF ("INTERNAL SIMULATOR ERROR:\n");
+ PRINTF ("no translation for currently executed instruction\n");
+ }
+
+ // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
+ PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
+ runtime.cpu.instructions);
+ if (config.cpu.superscalar)
+ {
+ PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
+ }
+ if (config.cpu.hazards)
+ {
+ PRINTF (" HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
+ }
+ else if (config.cpu.superscalar)
+ {
+ PRINTF ("\n");
+ }
+
+ if ((physical_pc = peek_into_itlb (cpu_state.pc)))
+ {
+ disassemble_memory (physical_pc, physical_pc + 4, 0);
+ }
+ else
+ {
+ PRINTF ("%" PRIxADDR ": : xxxxxxxx ITLB miss follows", cpu_state.pc);
+ }
+
+ PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : ""));
+
+ for (i = 0; i < MAX_GPRS; i++)
+ {
+ if (i % 4 == 0)
+ {
+ PRINTF ("\n");
+ }
+
+ PRINTF ("GPR%.2u: %" PRIxREG " ", i, evalsim_reg (i));
+ }
+
+ PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
+
+} /* dumpreg() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Wrapper around real decode_execute function
+
+ Some statistics here only
+
+ @param[in] current Instruction being executed */
+/*---------------------------------------------------------------------------*/
+static void
+decode_execute_wrapper (struct iqueue_entry *current)
+{
+ breakpoint = 0;
+
+#ifndef HAVE_EXECUTION
+#error HAVE_EXECUTION has to be defined in order to execute programs.
+#endif
+
+ /* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */
+#if !(DYNAMIC_EXECUTION)
+ decode_execute (current);
+#endif
+
+ if (breakpoint)
+ {
+ except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
+ }
+} /* decode_execute_wrapper() */
+
+/*---------------------------------------------------------------------------*/
+/*!Reset the CPU */
+/*---------------------------------------------------------------------------*/
+void
+cpu_reset ()
+{
+ int i;
+ struct hist_exec *hist_exec_head = NULL;
+ struct hist_exec *hist_exec_new;
+
+ runtime.sim.cycles = 0;
+ runtime.sim.loadcycles = 0;
+ runtime.sim.storecycles = 0;
+ runtime.cpu.instructions = 0;
+ runtime.cpu.supercycles = 0;
+ runtime.cpu.hazardwait = 0;
+
+ for (i = 0; i < MAX_GPRS; i++)
+ {
+ setsim_reg (i, 0);
+ }
+
+ memset (&cpu_state.iqueue, 0, sizeof (cpu_state.iqueue));
+ memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet));
+
+ sbuf_head = 0;
+ sbuf_tail = 0;
+ sbuf_count = 0;
+ sbuf_prev_cycles = 0;
+
+ /* Initialise execution history circular buffer */
+ for (i = 0; i < HISTEXEC_LEN; i++)
+ {
+ hist_exec_new = malloc (sizeof (struct hist_exec));
+
+ if (!hist_exec_new)
+ {
+ fprintf (stderr, "Out-of-memory\n");
+ exit (1);
+ }
+
+ if (!hist_exec_head)
+ {
+ hist_exec_head = hist_exec_new;
+ }
+ else
+ {
+ hist_exec_tail->next = hist_exec_new;
+ }
+
+ hist_exec_new->prev = hist_exec_tail;
+ hist_exec_tail = hist_exec_new;
+ }
+
+ /* Make hist_exec_tail->next point to hist_exec_head */
+ hist_exec_tail->next = hist_exec_head;
+ hist_exec_head->prev = hist_exec_tail;
+
+ /* MM1409: All progs should start at reset vector entry! This sorted out by
+ setting the cpu_state.pc field below. Not clear this is very good code! */
+
+ /* Patches suggested by Shinji Wakatsuki, so that the vector address takes
+ notice of the Exception Prefix High bit of the Supervision register */
+ pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000);
+
+ if (config.sim.verbose)
+ {
+ PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
+ }
+
+ cpu_state.pc = pcnext;
+ pcnext += 4;
+
+ /* MM1409: All programs should set their stack pointer! */
+#if !(DYNAMIC_EXECUTION)
+ except_handle (EXCEPT_RESET, 0);
+ update_pc ();
+#endif
+
+ except_pending = 0;
+ cpu_state.pc = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ?
+ 0xf0000000 + EXCEPT_RESET : EXCEPT_RESET;
+
+} /* cpu_reset() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Simulates one CPU clock cycle
+
+ @return non-zero if a breakpoint is hit, zero otherwise. */
+/*---------------------------------------------------------------------------*/
+int
+cpu_clock ()
+{
+ except_pending = 0;
+ next_delay_insn = 0;
+
+ if (fetch ())
+ {
+ PRINTF ("Breakpoint hit.\n");
+ return 1;
+ }
+
+ if (except_pending)
+ {
+ update_pc ();
+ except_pending = 0;
+ return 0;
+ }
+
+ if (breakpoint)
+ {
+ except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
+ update_pc ();
+ except_pending = 0;
+ return 0;
+ }
+
+ decode_execute_wrapper (&cpu_state.iqueue);
+ update_pc ();
+ return 0;
+
+} /* cpu_clock() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!If decoding cannot be found, call this function */
+/*---------------------------------------------------------------------------*/
+#if SIMPLE_EXECUTION
+void
+l_invalid (struct iqueue_entry *current)
+{
+#else
+void
+l_invalid ()
+{
+#endif
+ except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr);
+
+} /* l_invalid() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!The main execution loop */
+/*---------------------------------------------------------------------------*/
+void
+exec_main ()
+{
+ long long time_start;
+
+ while (1)
+ {
+ time_start = runtime.sim.cycles;
+ if (config.debug.enabled)
+ {
+ while (runtime.cpu.stalled)
+ {
+ if (config.debug.rsp_enabled)
+ {
+ handle_rsp ();
+ }
+ else if (config.debug.gdb_enabled)
+ {
+ block_jtag ();
+ handle_server_socket (FALSE);
+ }
+ else
+ {
+ fprintf (stderr, "ERROR: CPU stalled and GDB connection not "
+ "enabled: Invoking CLI and terminating.\n");
+ /* Dump the user into interactive mode. From there he or
+ she can decide what to do. */
+ handle_sim_command ();
+ sim_done ();
+ }
+ if (runtime.sim.iprompt)
+ handle_sim_command ();
+ }
+ }
+
+ /* Each cycle has counter of mem_cycles; this value is joined with cycles
+ at the end of the cycle; no sim originated memory accesses should be
+ performed inbetween. */
+ runtime.sim.mem_cycles = 0;
+
+ if (!config.pm.enabled ||
+ !(config.pm.enabled &
+ (cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME))))
+ {
+ if (cpu_clock ())
+ {
+ /* A breakpoint has been hit, drop to interactive mode */
+ handle_sim_command ();
+ }
+ }
+
+ if (config.vapi.enabled && runtime.vapi.enabled)
+ {
+ vapi_check ();
+ }
+
+ if (config.debug.gdb_enabled)
+ {
+ handle_server_socket (FALSE); /* block & check_stdin = false */
+ }
+
+ if (config.debug.enabled)
+ {
+ if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST)
+ {
+ set_stall_state (1);
+
+ if (config.debug.rsp_enabled)
+ {
+ rsp_exception (EXCEPT_TRAP);
+ }
+ }
+ }
+
+ runtime.sim.cycles += runtime.sim.mem_cycles;
+ scheduler.job_queue->time -= runtime.sim.cycles - time_start;
+
+ if (scheduler.job_queue->time <= 0)
+ {
+ do_scheduler ();
+ }
+ }
+} /* exec_main() */
+
+#if COMPLEX_EXECUTION
+
+/* Include generated/built in decode_execute function */
+#include "execgen.c"
+
+#elif SIMPLE_EXECUTION
+
+
+/*---------------------------------------------------------------------------*/
+/*!Evaluates source operand
+
+ Implementation specific.
+
+ @param[in] op_no The operand
+ @param[in] insn_index Address of the instruction
+ @param[in] insn The instruction
+
+ @return The value of the operand */
+/*---------------------------------------------------------------------------*/
+static uorreg_t
+eval_operand (int op_no,
+ unsigned long insn_index,
+ uint32_t insn)
+{
+ struct insn_op_struct *opd = op_start[insn_index];
+ uorreg_t ret;
+
+ while (op_no)
+ {
+ if (opd->type & OPTYPE_LAST)
+ {
+ fprintf (stderr,
+ "Instruction requested more operands than it has\n");
+ exit (1);
+ }
+
+ if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
+ {
+ op_no--;
+ }
+
+ opd++;
+ }
+
+ if (opd->type & OPTYPE_DIS)
+ {
+ ret = eval_operand_val (insn, opd);
+
+ while (!(opd->type & OPTYPE_OP))
+ {
+ opd++;
+ }
+
+ opd++;
+ ret += evalsim_reg (eval_operand_val (insn, opd));
+ cpu_state.insn_ea = ret;
+
+ return ret;
+ }
+
+ if (opd->type & OPTYPE_REG)
+ {
+ return evalsim_reg (eval_operand_val (insn, opd));
+ }
+
+ return eval_operand_val (insn, opd);
+
+} /* eval_operand() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Set destination operand (register direct) with value.
+
+ Implementation specific.
+
+ @param[in] op_no The operand
+ @param[in] value The value to set
+ @param[in] insn_index Address of the instruction
+ @param[in] insn The instruction */
+/*---------------------------------------------------------------------------*/
+static void
+set_operand (int op_no,
+ orreg_t value,
+ unsigned long insn_index,
+ uint32_t insn)
+{
+ struct insn_op_struct *opd = op_start[insn_index];
+
+ while (op_no)
+ {
+ if (opd->type & OPTYPE_LAST)
+ {
+ fprintf (stderr,
+ "Instruction requested more operands than it has\n");
+ exit (1);
+ }
+
+ if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
+ {
+ op_no--;
+ }
+
+ opd++;
+ }
+
+ if (!(opd->type & OPTYPE_REG))
+ {
+ fprintf (stderr, "Trying to set a non-register operand\n");
+ exit (1);
+ }
+
+ setsim_reg (eval_operand_val (insn, opd), value);
+
+} /* set_operand() */
+
+
+/*---------------------------------------------------------------------------*/
+/*!Simple and rather slow decoding function
+
+ Based on built automata.
+
+ @param[in] current The current instruction to execute */
+/*---------------------------------------------------------------------------*/
+static void
+decode_execute (struct iqueue_entry *current)
+{
+ int insn_index;
+
+ current->insn_index = insn_index = insn_decode (current->insn);
+
+ if (insn_index < 0)
+ {
+ l_invalid (current);
+ }
+ else
+ {
+ or32_opcodes[insn_index].exec (current);
+ }
+
+ if (do_stats)
+ analysis (&cpu_state.iqueue);
+}
+
+#include "insnset.c"
+
+#elif defined(DYNAMIC_EXECUTION)
+
+#else
+# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION"
+#endif
execute.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: Makefile.in
===================================================================
--- Makefile.in (nonexistent)
+++ Makefile.in (revision 135)
@@ -0,0 +1,817 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile -- Makefile for OR32 dependent simulation
+#
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+# Copyright (C) 2008 Embecosm Limited
+#
+# Contributor Jeremy Bennett
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@noinst_PROGRAMS = generate$(EXEEXT)
+@DYNAMIC_EXECUTION_TRUE@noinst_PROGRAMS = dyngen$(EXEEXT)
+subdir = cpu/or32
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libarch_la_LIBADD =
+am__libarch_la_SOURCES_DIST = execute.c or32.c common-i386.h \
+ dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
+ op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
+ op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
+ op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h op.c \
+ dyn-rec.c op-support.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@am_libarch_la_OBJECTS = \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ execute.lo \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.lo
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_libarch_la_OBJECTS = \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ execute.lo \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.lo
+@DYNAMIC_EXECUTION_TRUE@am_libarch_la_OBJECTS = execute.lo or32.lo \
+@DYNAMIC_EXECUTION_TRUE@ op.lo dyn-rec.lo op-support.lo
+@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_OBJECTS = gen-ops.lo \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.lo gen-ops-rel.lo
+am__dist_EXTRA_libarch_la_SOURCES_DIST = insnset.c
+libarch_la_OBJECTS = $(am_libarch_la_OBJECTS) \
+ $(nodist_libarch_la_OBJECTS)
+@DYNAMIC_EXECUTION_FALSE@am_libarch_la_rpath =
+@DYNAMIC_EXECUTION_TRUE@am_libarch_la_rpath =
+PROGRAMS = $(noinst_PROGRAMS)
+am__dyngen_SOURCES_DIST = dyngen.c dyngen-i386.c dyngen-elf.c \
+ common-i386.h dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h \
+ op-arith-op.h op-comp-op.h op-extend-op.h op-ff1-op.h \
+ op-i386.h op-lwhb-op.h op-mac-op.h op-mftspr-op.h op-support.h \
+ op-swhb-op.h op-t-reg-mov-op.h rec-i386.h sched-i386.h \
+ simpl32-defs.h
+@DYNAMIC_EXECUTION_TRUE@am_dyngen_OBJECTS = dyngen-dyngen.$(OBJEXT) \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-i386.$(OBJEXT) \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-elf.$(OBJEXT)
+dyngen_OBJECTS = $(am_dyngen_OBJECTS)
+dyngen_LDADD = $(LDADD)
+dyngen_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(dyngen_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__generate_SOURCES_DIST = or32.c generate.c common-i386.h \
+ dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
+ op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
+ op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
+ op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_generate_OBJECTS = generate-or32.$(OBJEXT) \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate-generate.$(OBJEXT)
+generate_OBJECTS = $(am_generate_OBJECTS)
+generate_LDADD = $(LDADD)
+generate_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(generate_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libarch_la_SOURCES) $(nodist_libarch_la_SOURCES) \
+ $(dist_EXTRA_libarch_la_SOURCES) $(dyngen_SOURCES) \
+ $(generate_SOURCES)
+DIST_SOURCES = $(am__libarch_la_SOURCES_DIST) \
+ $(am__dist_EXTRA_libarch_la_SOURCES_DIST) \
+ $(am__dyngen_SOURCES_DIST) $(am__generate_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_DIR = @BUILD_DIR@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPU_ARCH = @CPU_ARCH@
+CYGPATH_W = @CYGPATH_W@
+DEBUGFLAGS = @DEBUGFLAGS@
+DEFS = @DEFS@
+DEJAGNU = @DEJAGNU@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INCLUDES = @INCLUDES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
+LOCAL_DEFS = @LOCAL_DEFS@
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POW_LIB = @POW_LIB@
+RANLIB = @RANLIB@
+RUNTESTDEFAULTFLAGS = @RUNTESTDEFAULTFLAGS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUMVERSION = @SUMVERSION@
+TERMCAP_LIB = @TERMCAP_LIB@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@DYNAMIC_EXECUTION_FALSE@noinst_LTLIBRARIES = libarch.la
+@DYNAMIC_EXECUTION_TRUE@noinst_LTLIBRARIES = libarch.la
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@libarch_la_SOURCES = execute.c \
+@DYNAMIC_EXECUTION_TRUE@ or32.c \
+@DYNAMIC_EXECUTION_TRUE@ op.c \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.c \
+@DYNAMIC_EXECUTION_TRUE@ op-support.c \
+@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_SOURCES = gen-ops.h \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@BUILT_SOURCES = execgen.c
+@DYNAMIC_EXECUTION_TRUE@BUILT_SOURCES = gen-ops.h \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
+@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
+
+@DYNAMIC_EXECUTION_TRUE@dyngen_SOURCES = dyngen.c \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-i386.c \
+@DYNAMIC_EXECUTION_TRUE@ dyngen-elf.c \
+@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_TRUE@dyngen_CFLAGS = $(AM_CFLAGS)
+@DYNAMIC_EXECUTION_TRUE@OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@EXTRA_DIST = insnset.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_SOURCES = or32.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate.c \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_CFLAGS = $(AM_CFLAGS)
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@dist_EXTRA_libarch_la_SOURCES = insnset.c
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+CLEANFILES = execgen.c \
+ generate \
+ gen-ops.c \
+ gen-ops.h \
+ gen-ops-rel.c \
+ gen-ops-gen.c
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cpu/or32/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu cpu/or32/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libarch.la: $(libarch_la_OBJECTS) $(libarch_la_DEPENDENCIES)
+ $(LINK) $(am_libarch_la_rpath) $(libarch_la_OBJECTS) $(libarch_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+dyngen$(EXEEXT): $(dyngen_OBJECTS) $(dyngen_DEPENDENCIES)
+ @rm -f dyngen$(EXEEXT)
+ $(dyngen_LINK) $(dyngen_OBJECTS) $(dyngen_LDADD) $(LIBS)
+generate$(EXEEXT): $(generate_OBJECTS) $(generate_DEPENDENCIES)
+ @rm -f generate$(EXEEXT)
+ $(generate_LINK) $(generate_OBJECTS) $(generate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyn-rec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-elf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-i386.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-gen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-rel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-generate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-or32.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/insnset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-support.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or32.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+dyngen-dyngen.o: dyngen.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
+
+dyngen-dyngen.obj: dyngen.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
+
+dyngen-dyngen-i386.o: dyngen-i386.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
+
+dyngen-dyngen-i386.obj: dyngen-i386.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
+
+dyngen-dyngen-elf.o: dyngen-elf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
+
+dyngen-dyngen-elf.obj: dyngen-elf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
+
+generate-or32.o: or32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.o -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
+
+generate-or32.obj: or32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.obj -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
+
+generate-generate.o: generate.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.o -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
+
+generate-generate.obj: generate.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.obj -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
+
+
+@DYNAMIC_EXECUTION_TRUE@gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o
+@DYNAMIC_EXECUTION_TRUE@ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h
+
+@DYNAMIC_EXECUTION_TRUE@op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \
+@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h
+@DYNAMIC_EXECUTION_TRUE@ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $<
+
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@execgen.c: generate$(EXEEXT) insnset.c
+@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: generate.c
===================================================================
--- generate.c (nonexistent)
+++ generate.c (revision 135)
@@ -0,0 +1,440 @@
+/* generate.c -- generates file execgen.c from instruction set
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+/* Autoconf and/or portability configuration */
+#include "config.h"
+#include "port.h"
+
+/* System includes */
+#include
+#include
+#include
+
+/* Package includes */
+#include "opcode/or32.h"
+
+static char *in_file;
+static char *out_file;
+
+/* Whether this instruction stores something in register */
+static int write_to_reg;
+
+static int out_lines = 0;
+
+static int shift_fprintf(int level, FILE *f, const char *fmt, ...)
+{
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ for(i = 0; i < level; i++)
+ fprintf(f, " ");
+
+ i = vfprintf(f, fmt, ap);
+ va_end(ap);
+
+ out_lines++;
+ return i + (level * 2);
+}
+
+/* Generates a execute sequence for one instruction */
+int output_function (FILE *fo, const char *func_name, int level)
+{
+ FILE *fi;
+ int olevel;
+ int line_num = 0;
+
+ if ((fi = fopen (in_file, "rt")) == NULL) {
+ printf("could not open file\n");
+ return 1;
+ }
+
+ while (!feof (fi)) {
+ char line[10000], *str = line;
+ char *res;
+
+ res = fgets (str, sizeof (line), fi);
+
+ if (NULL == res)
+ {
+ fclose (fi); /* Mark Jarvin patch */
+ return 1;
+ }
+
+ line[sizeof (line) - 1] = 0;
+ line_num++;
+ if (strncmp (str, "INSTRUCTION (", 13) == 0) {
+ char *s;
+ str += 13;
+ while (isspace (*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 {
+ res = fgets (line, sizeof (line), fi);
+
+ if (NULL == res)
+ {
+ fclose (fi);
+ return 1;
+ }
+
+ line[sizeof(line) - 1] = 0;
+ for (str = line; *str; str++) {
+ if (*str == '{') olevel++;
+ else if (*str == '}') olevel--;
+ }
+ shift_fprintf (level, fo, "%s", line);
+ } while (olevel);
+ fclose(fi);
+ /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/
+ return 0;
+ }
+ }
+ }
+ shift_fprintf (level, fo, "%s ();\n", func_name);
+
+ fclose(fi);
+ return 0;
+}
+
+/* Parses operands. */
+
+static int
+gen_eval_operands (FILE *fo, int insn_index, int level)
+{
+ struct insn_op_struct *opd = op_start[insn_index];
+ int i;
+ int num_ops;
+ int nbits = 0;
+ int set_param = 0;
+ int dis = 0;
+ int sbit;
+ int dis_op = -1;
+
+ write_to_reg = 0;
+
+ shift_fprintf (level, fo, "uorreg_t ");
+
+ /* Count number of operands */
+ for (i = 0, num_ops = 0;; i++) {
+ if (!(opd[i].type & OPTYPE_OP))
+ continue;
+ if (opd[i].type & OPTYPE_DIS)
+ continue;
+ if (num_ops)
+ fprintf(fo, ", ");
+ fprintf(fo, "%c", 'a' + num_ops);
+ num_ops++;
+ if (opd[i].type & OPTYPE_LAST)
+ break;
+ }
+
+ fprintf (fo, ";\n");
+
+ shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops);
+
+ i = 0;
+ num_ops = 0;
+ do {
+/*
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0'); printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0');
+ printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0');
+ printf("opd[%i].type = %i\n", i, opd->type & OPTYPE_SHR);
+ printf("opd[%i].type = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR);
+ printf("opd[%i].data = %i\n", i, opd->data);
+*/
+
+ if (!nbits)
+ shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops,
+ opd->type & OPTYPE_SHR, (1 << opd->data) - 1);
+ else
+ shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n",
+ 'a' + num_ops, opd->type & OPTYPE_SHR,
+ (1 << opd->data) - 1, nbits);
+
+ nbits += opd->data;
+
+ if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) {
+ sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+ if (opd->type & OPTYPE_SIG)
+ shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
+ 'a' + num_ops, 1 << sbit, 'a' + num_ops,
+ 0xffffffff << sbit);
+ opd++;
+ shift_fprintf (level, fo, "*(orreg_t *)&%c += (orreg_t)cpu_state.reg[(insn >> %i) & 0x%x];\n",
+ 'a' + num_ops, opd->type & OPTYPE_SHR,
+ (1 << opd->data) - 1);
+ dis = 1;
+ dis_op = num_ops;
+ }
+
+ if (opd->type & OPTYPE_OP) {
+ sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+ if (opd->type & OPTYPE_SIG)
+ shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
+ 'a' + num_ops, 1 << sbit, 'a' + num_ops,
+ 0xffffffff << sbit);
+ if ((opd->type & OPTYPE_REG) && !dis) {
+ if(!i) {
+ shift_fprintf (level, fo, "#define SET_PARAM0(val) cpu_state.reg[a] = val\n");
+ shift_fprintf (level, fo, "#define REG_PARAM0 a\n");
+ set_param = 1;
+ }
+ shift_fprintf (level, fo, "#define PARAM%i cpu_state.reg[%c]\n", num_ops,
+ 'a' + num_ops);
+ if(opd->type & OPTYPE_DST)
+ write_to_reg = 1;
+ } else {
+ shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops,
+ 'a' + num_ops);
+ }
+ num_ops++;
+ nbits = 0;
+ dis = 0;
+ }
+
+ if ((opd->type & OPTYPE_LAST))
+ break;
+ opd++;
+ i++;
+ } while (1);
+
+ output_function (fo, or32_opcodes[insn_index].function_name, level);
+
+ if (set_param)
+ {
+ shift_fprintf (level, fo, "#undef SET_PARAM0\n");
+ shift_fprintf (level, fo, "#undef REG_PARAM0\n");
+ }
+
+ for (i = 0; i < num_ops; i++)
+ shift_fprintf (level, fo, "#undef PARAM%i\n", i);
+
+ return dis_op;
+}
+
+/* Generates decode and execute for one instruction instance */
+static int output_call (FILE *fo, int index, int level)
+{
+ int dis_op = -1;
+
+ /*printf ("%i:%s\n", index, insn_name (index));*/
+
+ shift_fprintf (level++, fo, "{\n");
+
+ if (index >= 0)
+ dis_op = gen_eval_operands (fo, index, level);
+
+ if (index < 0) output_function (fo, "l_invalid", level);
+
+ fprintf (fo, "\n");
+
+ shift_fprintf (level++, fo, "if (do_stats) {\n");
+
+ if (dis_op >= 0)
+ shift_fprintf (level, fo, "cpu_state.insn_ea = %c;\n", 'a' + dis_op);
+
+ shift_fprintf (level, fo, "current->insn_index = %i; /* \"%s\" */\n", index,
+ insn_name (index));
+
+ shift_fprintf (level, fo, "analysis(current);\n");
+ shift_fprintf (--level, fo, "}\n");
+
+ if (write_to_reg)
+ shift_fprintf (level, fo, "cpu_state.reg[0] = 0; /* Repair in case we changed it */\n");
+ shift_fprintf (--level, fo, "}\n");
+ return 0;
+}
+
+/* Generates .c file header */
+static int generate_header (FILE *fo)
+{
+ fprintf (fo, "/* execgen.c -- Automatically generated decoder\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
+ fprintf (fo, " Copyright (C) 2008 Embecosm Limited\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " Contributor Jeremy Bennett \n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This program is free software; you can redistribute it and/or modify it\n");
+ fprintf (fo, " under the terms of the GNU General Public License as published by the Free\n");
+ fprintf (fo, " Software Foundation; either version 3 of the License, or (at your option)\n");
+ fprintf (fo, " any later version.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " This program is distributed in the hope that it will be useful, but WITHOUT\n");
+ fprintf (fo, " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n");
+ fprintf (fo, " FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n");
+ fprintf (fo, " more details.\n");
+ fprintf (fo, "\n");
+ fprintf (fo, " You should have received a copy of the GNU General Public License along\n");
+ fprintf (fo, " with this program. If not, see . */\n");
+ fprintf (fo, "\n");
+ fprintf (fo, "/* This program is commented throughout in a fashion suitable for processing\n");
+ fprintf (fo, " with Doxygen. */\n");
+ fprintf (fo, "\n");
+
+ fprintf (fo, "/* This file was automatically generated by generate (see\n");
+ fprintf (fo, " cpu/or32/generate.c) */\n\n");
+ fprintf (fo, "#include \n\n");
+ fprintf (fo, "#include \n\n");
+ fprintf (fo, "typedef union {\n\tfloat fval;\n\tuint32_t hval;\n} FLOAT;\n\n");
+ fprintf (fo, "static void decode_execute (struct iqueue_entry *current)\n{\n");
+ fprintf (fo, " uint32_t insn = current->insn;\n");
+ out_lines = 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.
+
+ JPB: Added code to generate an illegal instruction exception for invalid
+ instructions. */
+static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
+{
+ unsigned long shift = *a;
+ unsigned long mask;
+ int i;
+ int prev_inv = 0;
+
+ if (!(*a & LEAF_FLAG)) {
+ shift = *a++;
+ mask = *a++;
+ shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift,
+ mask);
+ for (i = 0; i <= mask; i++, a++) {
+ if (!*a) {
+ shift_fprintf (level, fo, "case 0x%x:\n", i);
+ prev_inv = 1;
+ } else {
+ if(prev_inv) {
+ shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
+ shift_fprintf (level--, fo, "break;\n");
+ }
+ shift_fprintf (level, fo, "case 0x%x:\n", i);
+ generate_body (fo, automata + *a, cur_mask | (mask << shift), ++level);
+ shift_fprintf (level--, fo, "break;\n");
+ prev_inv = 0;
+ }
+ }
+ if (prev_inv) {
+ shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
+ shift_fprintf (level, fo,
+ "except_handle (EXCEPT_ILLEGAL, cpu_state.pc);\n");
+ shift_fprintf (level--, fo, "break;\n");
+ }
+ shift_fprintf (level, fo, "}\n");
+ } else {
+ i = *a & ~LEAF_FLAG;
+
+ /* Final check - do we have direct match?
+ (based on 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:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: rec-i386.h
===================================================================
--- rec-i386.h (nonexistent)
+++ rec-i386.h (revision 135)
@@ -0,0 +1,28 @@
+/* rec-i386.h -- i386 specific parts of the recompile engine
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Gets the current stack pointer */
+static void *get_sp(void)
+{
+ void *stack;
+ asm("movl %%esp, %0" : "=rm" (stack));
+ return stack;
+}
+
rec-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-2t.h
===================================================================
--- op-2t.h (nonexistent)
+++ op-2t.h (revision 135)
@@ -0,0 +1,62 @@
+/* op-2t.h -- Instantiation of operatations that work on only 2 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define OP_2T
+#define T glue(glue(glue(_, T0), _), T1)
+
+#if NUM_T_REGS == 3
+# define T0 t0
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+# define T0 t1
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+# define T0 t2
+# define T1 t0
+# include OP_FILE
+# undef T1
+# define T1 t1
+# include OP_FILE
+# undef T1
+# define T1 t2
+# include OP_FILE
+# undef T1
+# undef T0
+#else
+#error Update op_2t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_2T
op-2t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-mftspr-op.h
===================================================================
--- op-mftspr-op.h (nonexistent)
+++ op-mftspr-op.h (revision 135)
@@ -0,0 +1,78 @@
+/* op-mftspr-op.h -- Micro operations template for the m{f,t}spr operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifdef OP_2T
+__or_dynop void glue (op_mfspr, T) (void)
+{
+ /* FIXME: NPC/PPC Handling is br0ke */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ T0 = mfspr (T1 + OP_PARAM1);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (op_mfspr_imm, T) (void)
+{
+ /* FIXME: NPC/PPC Handling is br0ke */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ T0 = mfspr (OP_PARAM1);
+}
+#endif
+
+#ifdef OP_2T
+__or_dynop void glue (op_mtspr, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (T0 + OP_PARAM1, T1);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (op_mtspr_clear, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (T0 + OP_PARAM1, 0);
+}
+
+__or_dynop void glue (op_mtspr_imm, T) (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (OP_PARAM1, T0);
+}
+#endif
+
+#if !defined(OP_1T) && !defined(OP_2T)
+__or_dynop void
+op_mtspr_imm_clear (void)
+{
+ /* FIXME: NPC handling DOES NOT WORK like this */
+ if (env->sprs[SPR_SR] & SPR_SR_SM)
+ mtspr (OP_PARAM1, 0);
+}
+#endif
op-mftspr-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-i386.h
===================================================================
--- op-i386.h (nonexistent)
+++ op-i386.h (revision 135)
@@ -0,0 +1,46 @@
+/* op-i386.h -- i386 specific support routines for micro operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef OP_I386__H
+#define OP_I386__H
+
+#define OP_JUMP(x) asm("jmp *%0" : : "rm" (x))
+
+#define FORCE_RET asm volatile ("")
+
+/* Does a function call (with no arguments) makeing sure that gcc doesn't peddle
+ * the stack. (FIXME: Is this safe??) */
+#define SPEEDY_CALL(func) asm("call "#func"\n")
+
+/* Return out of the recompiled code */
+asm (" .align 2\n"
+ " .p2align 4,,15\n"
+ ".globl op_do_jump\n"
+ " .type op_do_jump,@function\n"
+ "op_do_jump:\n"
+ " ret\n" " ret\n" "1:\n" " .size op_do_jump,1b-op_do_jump\n");
+
+#endif /* OP_I386__H */
op-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op.c
===================================================================
--- op.c (nonexistent)
+++ op.c (revision 135)
@@ -0,0 +1,971 @@
+/* op.c -- Micro operations for the recompiler
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "spr-defs.h"
+#include "opcode/or32.h"
+#include "sim-config.h"
+#include "except.h"
+#include "abstract.h"
+#include "execute.h"
+#include "sprs.h"
+#include "sched.h"
+#include "immu.h"
+
+#include "op-support.h"
+
+#include "i386-regs.h"
+
+#include "dyn-rec.h"
+
+register struct cpu_state *env asm(CPU_STATE_REG);
+
+#include "op-i386.h"
+
+/*
+ * WARNING: Before going of and wildly editing everything in this file remember
+ * the following about its contents:
+ * 1) The `functions' don't EVER return. In otherwords haveing return state-
+ * ments _anywere_ in this file is likely not to work. This is because
+ * dyngen just strips away the ret from the end of the function and just uses
+ * the function `body'. If a ret statement is executed _anyware_ inside the
+ * dynamicly generated code, then it is undefined were we shall jump to.
+ * 2) Because of 1), try not to have overly complicated functions. In too
+ * complicated functions, gcc may decide to generate premature `exits'. This
+ * is what passing the -fno-reorder-blocks command line switch to gcc helps
+ * with. This is ofcourse not desired and is rather flaky as we don't (and
+ * can't) control the kind of code that gcc generates: It may work for one
+ * and break for another. The less branches there are the less likely it is
+ * that a premature return shall occur.
+ * 3) If gcc decides that it is going to be a basterd then it will optimise a
+ * very simple condition (if/switch) with a premature exit. But gcc can't
+ * fuck ME over! Just stick a FORCE_RET; at the END of the offending
+ * function.
+ * 4) All operations must start with `op_'. dyngen ignores all other functions.
+ * 5) Local variables are depriciated: They hinder performance.
+ * 6) Function calls are expensive as the stack has to be shifted (twice).
+ */
+
+/*#define __or_dynop __attribute__((noreturn))*/
+#define __or_dynop
+
+/* Temporaries to hold the (simulated) registers in */
+register uint32_t t0 asm(T0_REG);
+register uint32_t t1 asm(T1_REG);
+register uint32_t t2 asm(T2_REG);
+
+#define OP_PARAM1 ((uorreg_t)(&__op_param1))
+#define OP_PARAM2 ((uorreg_t)(&__op_param2))
+#define OP_PARAM3 ((uorreg_t)(&__op_param3))
+
+extern uorreg_t __op_param1;
+extern uorreg_t __op_param2;
+extern uorreg_t __op_param3;
+
+
+static inline void save_t_bound(oraddr_t pc)
+{
+ int reg;
+
+ pc = (pc & immu_state->page_offset_mask) / 4;
+ reg = env->curr_page->ts_bound[pc];
+
+ if(reg & 0x1f)
+ env->reg[reg & 0x1f] = t0;
+
+ if((reg >> 5) & 0x1f)
+ env->reg[(reg >> 5) & 0x1f] = t1;
+
+ if((reg >> 10) & 0x1f)
+ env->reg[(reg >> 10) & 0x1f] = t2;
+}
+
+void do_sched_wrap(void)
+{
+ env->pc += 4;
+ //runtime.cpu.instructions++;
+ runtime.sim.cycles -= env->cycles_dec;
+ scheduler.job_queue->time += env->cycles_dec;
+ if(scheduler.job_queue->time <= 0) {
+ save_t_bound(env->pc - 4);
+ do_scheduler();
+ }
+}
+
+/* do_scheduler wrapper for instructions that are in the delay slot */
+void do_sched_wrap_delay(void)
+{
+ /* FIXME: Can't this be eliminated? */
+ env->pc += 4;
+ //runtime.cpu.instructions++;
+ runtime.sim.cycles -= env->cycles_dec;
+ scheduler.job_queue->time += env->cycles_dec;
+ if(scheduler.job_queue->time <= 0)
+ do_scheduler();
+}
+
+void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
+{
+ uint16_t reg = 0;
+ uint32_t t0_reg = t0, t1_reg = t1, t2_reg = t2;
+ struct cpu_state *cpu_reg = env;
+
+ addr &= immu_state->page_offset_mask;
+ addr >>= 2;
+
+ if(addr)
+ reg = dp->ts_bound[addr - 1];
+
+ t0 = cpu_state.reg[reg & 0x1f];
+ t1 = cpu_state.reg[(reg >> 5) & 0x1f];
+
+ /* Don't we all love gcc? For some heavenly reason gcc 3.2 _knows_ that if I
+ * don't put a condition around the assignment of t2, _all_ the assignments to
+ * t{0,1,2} are useless and not needed. I'm pleasently happy that gcc is so
+ * bright, but on the other hand, t{0,1,2} are globals (!) how can you assume
+ * that the value of a global won't be used in a function further up or
+ * further down the stack?? */
+ if(addr)
+ t2 = cpu_state.reg[(reg >> 10) & 0x1f];
+
+ env = &cpu_state;
+
+ ((gen_code_ent *)dp->locs)[addr]();
+ t0 = t0_reg;
+ t1 = t1_reg;
+ t2 = t2_reg;
+ env = (struct cpu_state *)cpu_reg;
+}
+
+__or_dynop void op_set_pc_pc_delay(void)
+{
+ env->sprs[SPR_PPC] = env->pc;
+ /* pc_delay is pulled back 4 since imediatly after this is run, the scheduler
+ * runs which also increments it by 4 */
+ env->pc = env->pc_delay - 4;
+}
+
+__or_dynop void op_set_pc_delay_imm(void)
+{
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_set_pc_delay_pc(void)
+{
+ env->pc_delay = env->pc;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_clear_pc_delay(void)
+{
+ env->pc_delay = 0;
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_do_jump_delay(void)
+{
+ env->pc = env->pc_delay;
+}
+
+__or_dynop void op_clear_delay_insn(void)
+{
+ env->delay_insn = 0;
+}
+
+__or_dynop void op_set_delay_insn(void)
+{
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_check_delay_slot(void)
+{
+ if(!env->delay_insn)
+ OP_JUMP(OP_PARAM1);
+}
+
+__or_dynop void op_jmp_imm(void)
+{
+ OP_JUMP(OP_PARAM1);
+}
+
+__or_dynop void op_set_flag(void)
+{
+ env->sprs[SPR_SR] |= SPR_SR_F;
+}
+
+__or_dynop void op_clear_flag(void)
+{
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+}
+
+/* Used for the l.bf instruction. Therefore if the flag is not set, jump over
+ * all the jumping stuff */
+__or_dynop void op_check_flag(void)
+{
+ if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
+ SPEEDY_CALL(do_sched_wrap);
+ OP_JUMP(OP_PARAM1);
+ }
+}
+
+/* Used for l.bf if the delay slot instruction is on another page */
+__or_dynop void op_check_flag_delay(void)
+{
+ if(env->sprs[SPR_SR] & SPR_SR_F) {
+ env->delay_insn = 1;
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ }
+}
+
+/* Used for the l.bnf instruction. Therefore if the flag is set, jump over all
+ * the jumping stuff */
+__or_dynop void op_check_not_flag(void)
+{
+ if(env->sprs[SPR_SR] & SPR_SR_F) {
+ SPEEDY_CALL(do_sched_wrap);
+ OP_JUMP(OP_PARAM1);
+ }
+}
+
+/* Used for l.bnf if the delay slot instruction is on another page */
+__or_dynop void op_check_not_flag_delay(void)
+{
+ if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
+ env->delay_insn = 1;
+ env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
+ }
+}
+
+__or_dynop void op_add_pc(void)
+{
+ env->pc += OP_PARAM1;
+}
+
+__or_dynop void op_nop_exit(void)
+{
+ op_support_nop_exit();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_reset(void)
+{
+ op_support_nop_reset();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_printf(void)
+{
+ op_support_nop_printf();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_report(void)
+{
+ op_support_nop_report();
+ FORCE_RET;
+}
+
+__or_dynop void op_nop_report_imm(void)
+{
+ op_support_nop_report_imm(OP_PARAM1);
+}
+
+/* FIXME: Create another 2 sched functions that to the actual analysis call
+ * instead of bloating the recompiled code with this */
+__or_dynop void op_analysis(void)
+{
+ SPEEDY_CALL(op_support_analysis);
+}
+
+__or_dynop void op_move_gpr1_pc_delay(void)
+{
+ env->pc_delay = env->reg[1];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr2_pc_delay(void)
+{
+ env->pc_delay = env->reg[2];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr3_pc_delay(void)
+{
+ env->pc_delay = env->reg[3];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr4_pc_delay(void)
+{
+ env->pc_delay = env->reg[4];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr5_pc_delay(void)
+{
+ env->pc_delay = env->reg[5];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr6_pc_delay(void)
+{
+ env->pc_delay = env->reg[6];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr7_pc_delay(void)
+{
+ env->pc_delay = env->reg[7];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr8_pc_delay(void)
+{
+ env->pc_delay = env->reg[8];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr9_pc_delay(void)
+{
+ env->pc_delay = env->reg[9];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr10_pc_delay(void)
+{
+ env->pc_delay = env->reg[10];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr11_pc_delay(void)
+{
+ env->pc_delay = env->reg[11];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr12_pc_delay(void)
+{
+ env->pc_delay = env->reg[12];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr13_pc_delay(void)
+{
+ env->pc_delay = env->reg[13];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr14_pc_delay(void)
+{
+ env->pc_delay = env->reg[14];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr15_pc_delay(void)
+{
+ env->pc_delay = env->reg[15];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr16_pc_delay(void)
+{
+ env->pc_delay = env->reg[16];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr17_pc_delay(void)
+{
+ env->pc_delay = env->reg[17];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr18_pc_delay(void)
+{
+ env->pc_delay = env->reg[18];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr19_pc_delay(void)
+{
+ env->pc_delay = env->reg[19];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr20_pc_delay(void)
+{
+ env->pc_delay = env->reg[20];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr21_pc_delay(void)
+{
+ env->pc_delay = env->reg[21];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr22_pc_delay(void)
+{
+ env->pc_delay = env->reg[22];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr23_pc_delay(void)
+{
+ env->pc_delay = env->reg[23];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr24_pc_delay(void)
+{
+ env->pc_delay = env->reg[24];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr25_pc_delay(void)
+{
+ env->pc_delay = env->reg[25];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr26_pc_delay(void)
+{
+ env->pc_delay = env->reg[26];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr27_pc_delay(void)
+{
+ env->pc_delay = env->reg[27];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr28_pc_delay(void)
+{
+ env->pc_delay = env->reg[28];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr29_pc_delay(void)
+{
+ env->pc_delay = env->reg[29];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr30_pc_delay(void)
+{
+ env->pc_delay = env->reg[30];
+ env->delay_insn = 1;
+}
+
+__or_dynop void op_move_gpr31_pc_delay(void)
+{
+ env->pc_delay = env->reg[31];
+ env->delay_insn = 1;
+}
+
+#define OP_FILE "op-1t-op.h"
+#include "op-1t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-2t-op.h"
+#include "op-2t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-3t-op.h"
+#include "op-3t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-arith-op.h"
+#define OP_EXTRA
+
+#define OP /
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME div
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP /
+#define OP_CAST(x) (x)
+#define OP_NAME divu
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP *
+#define OP_CAST(x) (x)
+#define OP_NAME mulu
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP -
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME sub
+#include "op-3t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+
+#define OP_EXTRA + ((env->sprs[SPR_SR] & SPR_SR_CY) >> 10)
+#define OP +
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME addc
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+#define OP_EXTRA
+
+#define OP +
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME add
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP &
+#define OP_CAST(x) (x)
+#define OP_NAME and
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP *
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME mul
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP |
+#define OP_CAST(x) (x)
+#define OP_NAME or
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP <<
+#define OP_CAST(x) (x)
+#define OP_NAME sll
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP >>
+#define OP_CAST(x) (orreg_t)(x)
+#define OP_NAME sra
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP >>
+#define OP_CAST(x) (x)
+#define OP_NAME srl
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#define OP ^
+#define OP_CAST(x) (x)
+#define OP_NAME xor
+#include "op-3t.h"
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP_CAST
+#undef OP
+
+#undef OP_EXTRA
+#undef OP_FILE
+
+#define OP_FILE "op-extend-op.h"
+
+#define EXT_NAME extbs
+#define EXT_TYPE int8_t
+#define EXT_CAST (orreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME extbz
+#define EXT_TYPE uint8_t
+#define EXT_CAST (uorreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME exths
+#define EXT_TYPE int16_t
+#define EXT_CAST (orreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#define EXT_NAME exthz
+#define EXT_TYPE uint16_t
+#define EXT_CAST (uorreg_t)
+#include "op-2t.h"
+#undef EXT_CAST
+#undef EXT_TYPE
+#undef EXT_NAME
+
+#undef OP_FILE
+
+#define OP_FILE "op-comp-op.h"
+
+#define COMP ==
+#define COMP_NAME sfeq
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP !=
+#define COMP_NAME sfne
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >
+#define COMP_NAME sfgtu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >=
+#define COMP_NAME sfgeu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <
+#define COMP_NAME sfltu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <=
+#define COMP_NAME sfleu
+#define COMP_CAST(x) (x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >
+#define COMP_NAME sfgts
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP >=
+#define COMP_NAME sfges
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <
+#define COMP_NAME sflts
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#define COMP <=
+#define COMP_NAME sfles
+#define COMP_CAST(x) (orreg_t)(x)
+#include "op-2t.h"
+#include "op-1t.h"
+#undef COMP_CAST
+#undef COMP_NAME
+#undef COMP
+
+#undef OP_FILE
+
+#define OP_FILE "op-t-reg-mov-op.h"
+#include "op-1t.h"
+#undef OP_FILE
+
+#define OP_FILE "op-mftspr-op.h"
+#include "op-1t.h"
+#include "op-2t.h"
+#undef OP_FILE
+#include "op-mftspr-op.h"
+
+#define OP_FILE "op-mac-op.h"
+
+#define OP +=
+#define OP_NAME mac
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP
+
+#define OP -=
+#define OP_NAME msb
+#include "op-2t.h"
+#undef OP_NAME
+#undef OP
+
+#undef OP_FILE
+
+#define OP_FILE "op-lwhb-op.h"
+
+#define LS_OP_NAME lbz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem8
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lbs
+#define LS_OP_CAST (int8_t)
+#define LS_OP_FUNC eval_mem8
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lhz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem16
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lhs
+#define LS_OP_CAST (int16_t)
+#define LS_OP_FUNC eval_mem16
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lwz
+#define LS_OP_CAST
+#define LS_OP_FUNC eval_mem32
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#define LS_OP_NAME lws
+#define LS_OP_CAST (int32_t)
+#define LS_OP_FUNC eval_mem32
+#include "op-2t.h"
+#include "op-1t.h"
+#undef LS_OP_FUNC
+#undef LS_OP_CAST
+#undef LS_OP_NAME
+
+#undef OP_FILE
+
+#define OP_FILE "op-swhb-op.h"
+
+#define S_OP_NAME sb
+#define S_FUNC set_mem8
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+#define S_OP_NAME sh
+#define S_FUNC set_mem16
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+#define S_OP_NAME sw
+#define S_FUNC set_mem32
+#include "op-swhb-op.h"
+#include "op-2t.h"
+#include "op-1t.h"
+#undef S_FUNC
+#undef S_OP_NAME
+
+__or_dynop void op_join_mem_cycles(void)
+{
+ runtime.sim.cycles += runtime.sim.mem_cycles;
+ scheduler.job_queue->time -= runtime.sim.mem_cycles;
+ runtime.sim.mem_cycles = 0;
+}
+
+__or_dynop void op_store_link_addr_gpr(void)
+{
+ env->reg[LINK_REGNO] = env->pc + 8;
+}
+
+__or_dynop void op_prep_rfe(void)
+{
+ env->sprs[SPR_SR] = env->sprs[SPR_ESR_BASE] | SPR_SR_FO;
+ env->sprs[SPR_PPC] = env->pc;
+ env->pc = env->sprs[SPR_EPCR_BASE] - 4;
+}
+
+static inline void prep_except(oraddr_t epcr_base)
+{
+ env->sprs[SPR_EPCR_BASE] = epcr_base;
+
+ env->sprs[SPR_ESR_BASE] = env->sprs[SPR_SR];
+
+ /* Address translation is always disabled when starting exception. */
+ env->sprs[SPR_SR] &= ~SPR_SR_DME;
+ env->sprs[SPR_SR] &= ~SPR_SR_IME;
+
+ env->sprs[SPR_SR] &= ~SPR_SR_OVE; /* Disable overflow flag exception. */
+
+ env->sprs[SPR_SR] |= SPR_SR_SM; /* SUPV mode */
+ env->sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */
+}
+
+/* Before the code in op_{sys,trap}{,_delay} gets run, the scheduler runs.
+ * Therefore the pc will point to the instruction after the l.sys or l.trap
+ * instruction */
+__or_dynop void op_prep_sys_delay(void)
+{
+ env->delay_insn = 0;
+ prep_except(env->pc - 4);
+ env->pc = EXCEPT_SYSCALL - 4;
+}
+
+__or_dynop void op_prep_sys(void)
+{
+ prep_except(env->pc + 4);
+ env->pc = EXCEPT_SYSCALL - 4;
+}
+
+__or_dynop void op_prep_trap_delay(void)
+{
+ env->delay_insn = 0;
+ prep_except(env->pc - 4);
+ env->pc = EXCEPT_TRAP - 4;
+}
+
+__or_dynop void op_prep_trap(void)
+{
+ prep_except(env->pc);
+ env->pc = EXCEPT_TRAP - 4;
+}
+
+/* FIXME: This `instruction' should be split up like the l.trap and l.sys
+ * instructions are done */
+__or_dynop void op_illegal_delay(void)
+{
+ env->delay_insn = 0;
+ env->sprs[SPR_EEAR_BASE] = env->pc - 4;
+ env->pc = EXCEPT_ILLEGAL - 4;
+}
+
+__or_dynop void op_illegal(void)
+{
+ env->sprs[SPR_EEAR_BASE] = env->pc;
+ env->pc = EXCEPT_ILLEGAL;
+}
+
+__or_dynop void op_do_sched(void)
+{
+ SPEEDY_CALL(do_sched_wrap);
+}
+
+__or_dynop void op_do_sched_delay(void)
+{
+ SPEEDY_CALL(do_sched_wrap_delay);
+}
+
+__or_dynop void op_macc(void)
+{
+ env->sprs[SPR_MACLO] = 0;
+ env->sprs[SPR_MACHI] = 0;
+}
+
+__or_dynop void op_store_insn_ea(void)
+{
+ env->insn_ea = OP_PARAM1;
+}
+
op.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: sched-i386.h
===================================================================
--- sched-i386.h (nonexistent)
+++ sched-i386.h (revision 135)
@@ -0,0 +1,40 @@
+/* sched-i386.h -- i386 specific support routines for the scheduler
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Sets the cycle counter to a specific value */
+static void set_sched_cycle(int32_t job_time)
+{
+ union {
+ uint64_t val64;
+ union {
+ uint32_t low32;
+ uint32_t high32;
+ } val3232;
+ } time_pc;
+
+ asm("movq %%mm0, %0\n"
+ "\tmovl %2, %1\n"
+ "\tmovq %3, %%mm0\n"
+ : "=m" (time_pc.val64),
+ "=m" (time_pc.val3232.low32)
+ : "r" (job_time),
+ "m" (time_pc.val64));
+}
+
sched-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn32-defs.h
===================================================================
--- dyn32-defs.h (nonexistent)
+++ dyn32-defs.h (revision 135)
@@ -0,0 +1,139 @@
+/* dyn32-defs.h -- Definitions for the dynamic execution model
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef DYN32_DEFS__H
+#define DYN32_DEFS__H
+
+
+/* Package includes */
+#include "arch.h"
+
+
+struct op_queue {
+ unsigned int num_ops;
+ unsigned int ops_len;
+ unsigned int *ops;
+ unsigned int num_ops_param;
+ unsigned int ops_param_len;
+ unsigned int *ops_param;
+ unsigned int jump_local; /* Parameter index that holds the location of the jump */
+ oraddr_t jump_local_loc; /* Location to jump to (relative to start of page */
+ unsigned int not_jump_loc; /* Location to jump if not jumping (l.bf/l.bnf) */
+ int xref; /* Is this location cross referenced? */
+ oraddr_t insn_addr; /* Physical address of the instruction */
+ unsigned int reg_t[3]; /* Which registers are in the temporaries (after the instruction)? */
+ unsigned int tflags[3];
+
+ int insn_index;
+ unsigned int param_type[5]; /* opd->type */
+ orreg_t param[5]; /* Value of operand */
+ unsigned int param_num; /* Number of operands */
+ uint32_t insn; /* Instruction word */
+
+ struct op_queue *prev;
+ struct op_queue *next;
+};
+
+void gen_l_add PARAMS((struct op_queue *, int *, int));
+void gen_l_addc PARAMS((struct op_queue *, int *, int));
+void gen_l_and PARAMS((struct op_queue *, int *, int));
+void gen_l_bf PARAMS((struct op_queue *, int *, int));
+void gen_l_bnf PARAMS((struct op_queue *, int *, int));
+void gen_l_cmov PARAMS((struct op_queue *, int *, int));
+void gen_l_cust1 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust2 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust3 PARAMS((struct op_queue *, int *, int));
+void gen_l_cust4 PARAMS((struct op_queue *, int *, int));
+void gen_l_div PARAMS((struct op_queue *, int *, int));
+void gen_l_divu PARAMS((struct op_queue *, int *, int));
+void gen_l_extbs PARAMS((struct op_queue *, int *, int));
+void gen_l_extbz PARAMS((struct op_queue *, int *, int));
+void gen_l_exths PARAMS((struct op_queue *, int *, int));
+void gen_l_exthz PARAMS((struct op_queue *, int *, int));
+void gen_l_extws PARAMS((struct op_queue *, int *, int));
+void gen_l_extwz PARAMS((struct op_queue *, int *, int));
+void gen_l_ff1 PARAMS((struct op_queue *, int *, int));
+void gen_l_j PARAMS((struct op_queue *, int *, int));
+void gen_l_jal PARAMS((struct op_queue *, int *, int));
+void gen_l_jr PARAMS((struct op_queue *, int *, int));
+void gen_l_jalr PARAMS((struct op_queue *, int *, int));
+void gen_l_lbs PARAMS((struct op_queue *, int *, int));
+void gen_l_lbz PARAMS((struct op_queue *, int *, int));
+void gen_l_lhs PARAMS((struct op_queue *, int *, int));
+void gen_l_lhz PARAMS((struct op_queue *, int *, int));
+void gen_l_lws PARAMS((struct op_queue *, int *, int));
+void gen_l_lwz PARAMS((struct op_queue *, int *, int));
+void gen_l_mac PARAMS((struct op_queue *, int *, int));
+void gen_l_macrc PARAMS((struct op_queue *, int *, int));
+void gen_l_mfspr PARAMS((struct op_queue *, int *, int));
+void gen_l_movhi PARAMS((struct op_queue *, int *, int));
+void gen_l_msb PARAMS((struct op_queue *, int *, int));
+void gen_l_mtspr PARAMS((struct op_queue *, int *, int));
+void gen_l_mul PARAMS((struct op_queue *, int *, int));
+void gen_l_mulu PARAMS((struct op_queue *, int *, int));
+void gen_l_nop PARAMS((struct op_queue *, int *, int));
+void gen_l_or PARAMS((struct op_queue *, int *, int));
+void gen_l_rfe PARAMS((struct op_queue *, int *, int));
+void gen_l_sb PARAMS((struct op_queue *, int *, int));
+void gen_l_sh PARAMS((struct op_queue *, int *, int));
+void gen_l_sw PARAMS((struct op_queue *, int *, int));
+void gen_l_sfeq PARAMS((struct op_queue *, int *, int));
+void gen_l_sfges PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgeu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgts PARAMS((struct op_queue *, int *, int));
+void gen_l_sfgtu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfles PARAMS((struct op_queue *, int *, int));
+void gen_l_sfleu PARAMS((struct op_queue *, int *, int));
+void gen_l_sflts PARAMS((struct op_queue *, int *, int));
+void gen_l_sfltu PARAMS((struct op_queue *, int *, int));
+void gen_l_sfne PARAMS((struct op_queue *, int *, int));
+void gen_l_sll PARAMS((struct op_queue *, int *, int));
+void gen_l_sra PARAMS((struct op_queue *, int *, int));
+void gen_l_srl PARAMS((struct op_queue *, int *, int));
+void gen_l_sub PARAMS((struct op_queue *, int *, int));
+void gen_l_sys PARAMS((struct op_queue *, int *, int));
+void gen_l_trap PARAMS((struct op_queue *, int *, int));
+void gen_l_xor PARAMS((struct op_queue *, int *, int));
+void gen_l_invalid PARAMS((struct op_queue *, int *, int));
+
+void gen_lf_add_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_div_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_ftoi_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_itof_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_madd_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_mul_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_rem_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfeq_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfge_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfgt_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfle_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sflt_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sfne_s PARAMS((struct op_queue *, int *, int));
+void gen_lf_sub_s PARAMS((struct op_queue *, int *, int));
+void l_none(struct op_queue *opq, int *param_t, int delay_slot);
+
+#endif /* DYN32_DEFS__H */
+
dyn32-defs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-support.c
===================================================================
--- op-support.c (nonexistent)
+++ op-support.c (revision 135)
@@ -0,0 +1,114 @@
+/* op-support.c -- Support routines for micro operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "opcode/or32.h"
+#include "sim-config.h"
+#include "spr-defs.h"
+#include "except.h"
+#include "immu.h"
+#include "abstract.h"
+#include "execute.h"
+#include "sched.h"
+#include "i386-regs.h"
+#include "dyn-rec.h"
+#include "op-support.h"
+#include "simprintf.h"
+
+
+/* Stuff that is really a `micro' operation but is rather big (or for some other
+ * reason like calling exit()) */
+
+void op_support_nop_exit(void)
+{
+ PRINTF("exit(%"PRIdREG")\n", cpu_state.reg[3]);
+ fprintf(stderr, "@reset : cycles %lld, insn #%lld\n",
+ runtime.sim.reset_cycles, runtime.cpu.reset_instructions);
+ fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles,
+ runtime.cpu.instructions);
+ fprintf(stderr, " diff : cycles %lld, insn #%lld\n",
+ runtime.sim.cycles - runtime.sim.reset_cycles,
+ runtime.cpu.instructions - runtime.cpu.reset_instructions);
+ /* FIXME: Implement emulation of a stalled cpu
+ if (config.debug.gdb_enabled)
+ set_stall_state (1);
+ else {
+ handle_sim_command();
+ sim_done();
+ }
+ */
+ exit(0);
+}
+
+void op_support_nop_reset(void)
+{
+ PRINTF("****************** counters reset ******************\n");
+ PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
+ PRINTF("****************** counters reset ******************\n");
+ runtime.sim.reset_cycles = runtime.sim.cycles;
+ runtime.cpu.reset_instructions = runtime.cpu.instructions;
+}
+
+void op_support_nop_printf(void)
+{
+ simprintf(cpu_state.reg[4], cpu_state.reg[3]);
+}
+
+void op_support_nop_report(void)
+{
+ PRINTF("report(0x%"PRIxREG");\n", cpu_state.reg[3]);
+}
+
+void op_support_nop_report_imm(int imm)
+{
+ PRINTF("report %i (0x%"PRIxREG");\n", imm, cpu_state.reg[3]);
+}
+
+/* Handles a jump */
+/* addr is a VIRTUAL address */
+/* NOTE: We can't use env since this code is compiled like the rest of the
+ * simulator (most likely without -fomit-frame-pointer) and thus env will point
+ * to some bogus value. */
+void do_jump(oraddr_t addr)
+{
+ cpu_state.pc = addr;
+ longjmp(cpu_state.excpt_loc, 0);
+}
+
+/* Wrapper around analysis() that contains all the recompiler specific stuff */
+void op_support_analysis(void)
+{
+ oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
+ runtime.cpu.instructions++;
+ cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
+ cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
+ cpu_state.iqueue.insn_addr = cpu_state.pc;
+ analysis(&cpu_state.iqueue);
+}
+
op-support.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-lwhb-op.h
===================================================================
--- op-lwhb-op.h (nonexistent)
+++ op-lwhb-op.h (revision 135)
@@ -0,0 +1,38 @@
+/* op-lwhb-op.h -- Micro operations template for load operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* FIXME: Do something if a breakpoint is hit */
+
+#ifdef OP_2T
+__or_dynop void glue(glue(op_, LS_OP_NAME), T)(void)
+{
+ int breakpoint;
+ T0 = LS_OP_CAST LS_OP_FUNC(T1 + OP_PARAM1, &breakpoint);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue(glue(glue(op_, LS_OP_NAME), _imm), T)(void)
+{
+ int breakpoint;
+ T0 = LS_OP_CAST LS_OP_FUNC(OP_PARAM1, &breakpoint);
+}
+#endif
+
op-lwhb-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-comp-op.h
===================================================================
--- op-comp-op.h (nonexistent)
+++ op-comp-op.h (revision 135)
@@ -0,0 +1,50 @@
+/* op-comp-op.h -- Micro operations template for comparison operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef OP_2T
+__or_dynop void glue(glue(op_, COMP_NAME), T)(void)
+{
+ if(COMP_CAST(T0) COMP COMP_CAST(T1))
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue(glue(glue(op_, COMP_NAME), _imm), T)(void)
+{
+ if(COMP_CAST(T0) COMP COMP_CAST(OP_PARAM1))
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+
+__or_dynop void glue(glue(glue(op_, COMP_NAME), _null), T)(void)
+{
+ if(COMP_CAST(T0) COMP 0)
+ env->sprs[SPR_SR] |= SPR_SR_F;
+ else
+ env->sprs[SPR_SR] &= ~SPR_SR_F;
+ FORCE_RET;
+}
+#endif
+
op-comp-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: .cvsignore
===================================================================
--- .cvsignore (nonexistent)
+++ .cvsignore (revision 135)
@@ -0,0 +1,3 @@
+Makefile
+.deps
+generate
Index: op-support.h
===================================================================
--- op-support.h (nonexistent)
+++ op-support.h (revision 135)
@@ -0,0 +1,28 @@
+/* op-support.h -- Definitions of support routines for operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+void op_support_nop_exit(void);
+void op_support_nop_reset(void);
+void op_support_nop_printf(void);
+void op_support_nop_report(void);
+void op_support_nop_report_imm(int imm);
+void op_support_analysis(void);
+void do_jump(oraddr_t addr);
+
+void upd_reg_from_t(oraddr_t pc, int bound);
op-support.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-swhb-op.h
===================================================================
--- op-swhb-op.h (nonexistent)
+++ op-swhb-op.h (revision 135)
@@ -0,0 +1,57 @@
+/* op-swhb-op.h -- Micro operations template for store operations
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+/* FIXME: Do something with breakpoint */
+
+
+#ifdef OP_2T
+__or_dynop void glue (glue (op_, S_OP_NAME), T) (void)
+{
+ int breakpoint;
+ S_FUNC (T0 + OP_PARAM1, T1, &breakpoint);
+}
+#endif
+
+#ifdef OP_1T
+__or_dynop void glue (glue (glue (op_, S_OP_NAME), _imm), T) (void)
+{
+ int breakpoint;
+ S_FUNC (OP_PARAM1, T0, &breakpoint);
+}
+
+__or_dynop void glue (glue (glue (op_, S_OP_NAME), _clear), T) (void)
+{
+ int breakpoint;
+ S_FUNC (T0 + OP_PARAM1, 0, &breakpoint);
+}
+#endif
+
+#if !defined(OP_1T) && !defined(OP_2T)
+__or_dynop void glue (glue (op_, S_OP_NAME), _clear_imm) (void)
+{
+ int breakpoint;
+ S_FUNC (OP_PARAM1, 0, &breakpoint);
+}
+#endif
op-swhb-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn-rec.c
===================================================================
--- dyn-rec.c (nonexistent)
+++ dyn-rec.c (revision 135)
@@ -0,0 +1,2451 @@
+/* dyn-rec.c -- Dynamic recompiler implementation for or32
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "immu.h"
+#include "abstract.h"
+#include "opcode/or32.h"
+#include "spr-defs.h"
+#include "execute.h"
+#include "except.h"
+#include "spr-defs.h"
+#include "sim-config.h"
+#include "sched.h"
+#include "i386-regs.h"
+#include "def-op-t.h"
+#include "dyn-rec.h"
+#include "gen-ops.h"
+#include "op-support.h"
+#include "toplevel-support.h"
+
+
+/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
+
+/* FIXME: Optimise sorted list adding */
+
+typedef void (*generic_gen_op)(struct op_queue *opq, int end);
+typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
+
+void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot);
+
+/* ttg->temporary to gpr */
+DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr);
+/* gtt->gpr to temporary */
+DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr);
+
+DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea);
+
+/* Linker stubs. This will allow the linker to link in op.o. The relocations
+ * that the linker does for these will be irrelevent anyway, since we patch the
+ * relocations during recompilation. */
+uorreg_t __op_param1;
+uorreg_t __op_param2;
+uorreg_t __op_param3;
+
+/* The number of bytes that a dynamicly recompiled page should be enlarged by */
+#define RECED_PAGE_ENLARGE_BY 51200
+
+/* The number of entries that the micro operations array in op_queue should be
+ * enlarged by */
+#define OPS_ENLARGE_BY 5
+
+#define T_NONE (-1)
+
+/* Temporary is used as a source operand */
+#define TFLAG_SRC 1
+/* Temporary is used as a destination operand */
+#define TFLAG_DST 2
+/* Temporary has been saved to permanent storage */
+#define TFLAG_SAVED 4
+/* Temporary contains the value of the register before the instruction execution
+ * occurs (either by an explicit reg->t move or implicitly being left over from
+ * a previous instruction) */
+#define TFLAG_SOURCED 8
+
+/* FIXME: Put this into some header */
+extern int do_stats;
+
+static int sigsegv_state = 0;
+static void *sigsegv_addr = NULL;
+
+void dyn_ret_stack_prot(void);
+
+void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
+{
+ struct dyn_page *dp;
+ FILE *f;
+ char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
+ int i;
+ struct sigcontext *sigc = dat;
+
+ if(!sigsegv_state) {
+ sigsegv_addr = siginf->si_addr;
+ } else {
+ fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n");
+ sigsegv_state++;
+ }
+
+ /* First dump all the data that does not need dereferenceing to get */
+ switch(sigsegv_state) {
+ case 0:
+ fflush(stderr);
+ fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n",
+ sigsegv_addr, sigc->eip, cpu_state.pc);
+ sigsegv_state++;
+ case 1:
+ /* Run through the recompiled pages, dumping them to disk as we go */
+ for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) {
+ dp = cpu_state.dyn_pages[i];
+ if(!dp)
+ continue;
+ fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
+ dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
+ dp->host_len);
+ fflush(stdout);
+
+ sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
+ if(!(f = fopen(filen, "w"))) {
+ fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
+ filen, strerror(errno));
+ continue;
+ }
+ if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
+ fprintf(stderr, "Unable to write recompiled data to file: %s\n",
+ strerror(errno));
+
+ fclose(f);
+ }
+ sigsegv_state++;
+ case 2:
+ sim_done();
+ }
+}
+
+struct dyn_page *new_dp(oraddr_t page)
+{
+ struct dyn_page *dp = malloc(sizeof(struct dyn_page));
+ dp->or_page = IADDR_PAGE(page);
+
+ dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4));
+
+ dp->host_len = 0;
+ dp->host_page = NULL;
+ dp->dirty = 1;
+
+ if(do_stats) {
+ dp->insns = malloc(immu_state->pagesize);
+ dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4));
+ }
+
+ cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp;
+ return dp;
+}
+
+void dyn_main(void)
+{
+ struct dyn_page *target_dp;
+ oraddr_t phys_page;
+
+ setjmp(cpu_state.excpt_loc);
+ for(;;) {
+ phys_page = immu_translate(cpu_state.pc);
+
+/*
+ printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
+ phys_page, cpu_state.sprs[SPR_PPC] - 4);
+*/
+
+ /* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
+ * it to the cycles when the instruction is executed so if we don't reset it
+ * now it will produce wrong results */
+ runtime.sim.mem_cycles = 0;
+
+ target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2];
+
+ if(!target_dp)
+ target_dp = new_dp(phys_page);
+
+ /* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
+ * 0x0 page if the jump is to that location */
+ if(phys_page < 0x100)
+ target_dp->dirty = 1;
+
+ if(target_dp->dirty)
+ recompile_page(target_dp);
+
+ cpu_state.curr_page = target_dp;
+
+ /* FIXME: If the page is backed by more than one type of memory, this will
+ * produce wrong results */
+ cpu_state.cycles_dec = target_dp->delayr;
+ if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
+ /* Add the mmu hit delay to the cycle counter */
+ cpu_state.cycles_dec -= immu_state->hitdelay;
+
+ /* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
+ * calls but the recompiled code trashes them... */
+ enter_dyn_code(phys_page, target_dp);
+ }
+}
+
+static void immu_retranslate(void *dat)
+{
+ int got_en_dis = (int)dat;
+ immu_translate(cpu_state.pc);
+ runtime.sim.mem_cycles = 0;
+
+ /* Only update the cycle decrementer if the mmu got enabled or disabled */
+ if(got_en_dis == IMMU_GOT_ENABLED)
+ /* Add the mmu hit delay to the cycle counter */
+ cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay;
+ else if(got_en_dis == IMMU_GOT_DISABLED)
+ cpu_state.cycles_dec = cpu_state.curr_page->delayr;
+}
+
+/* This is called whenever the immu is either enabled/disabled or reconfigured
+ * while enabled. This checks if an itlb miss would occour and updates the immu
+ * hit delay counter */
+void recheck_immu(int got_en_dis)
+{
+ oraddr_t addr;
+
+ if(cpu_state.delay_insn)
+ addr = cpu_state.pc_delay;
+ else
+ addr = cpu_state.pc + 4;
+
+ if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr))
+ /* Schedule a job to do immu_translate() */
+ SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0);
+}
+
+/* Runs the scheduler. Called from except_handler (and dirtyfy_page below) */
+void run_sched_out_of_line(void)
+{
+ oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
+
+ if(do_stats) {
+ cpu_state.iqueue.insn_addr = cpu_state.pc;
+ cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
+ cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
+ runtime.cpu.instructions++;
+ analysis(&cpu_state.iqueue);
+ }
+
+ /* Run the scheduler */
+ scheduler.job_queue->time += cpu_state.cycles_dec;
+ runtime.sim.cycles -= cpu_state.cycles_dec;
+
+ op_join_mem_cycles();
+ if(scheduler.job_queue->time <= 0)
+ do_scheduler();
+}
+
+/* Signals a page as dirty */
+static void dirtyfy_page(struct dyn_page *dp)
+{
+ oraddr_t check;
+
+ printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
+
+ dp->dirty = 1;
+
+ /* If the execution is currently in the page that was touched then recompile
+ * it now and jump back to the point of execution */
+ check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4;
+ if(IADDR_PAGE(check) == dp->or_page) {
+ run_sched_out_of_line();
+ recompile_page(dp);
+
+ cpu_state.delay_insn = 0;
+
+ /* Jump out to the next instruction */
+ do_jump(check);
+ }
+}
+
+/* Checks to see if a write happened to a recompiled page. If so marks it as
+ * dirty */
+void dyn_checkwrite(oraddr_t addr)
+{
+ /* FIXME: Do this with mprotect() */
+ struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2];
+
+ /* Since the locations 0x0-0xff are nearly always written to in an exception
+ * handler, ignore any writes to these locations. If code ends up jumping
+ * out there, we'll recompile when the jump actually happens. */
+ if((addr > 0x100) && dp && !dp->dirty)
+ dirtyfy_page(dp);
+}
+
+/* Moves the temprary t to its permanent storage if it has been used as a
+ * destination register */
+static void ship_t_out(struct op_queue *opq, unsigned int t)
+{
+ unsigned int gpr = opq->reg_t[t];
+
+ for(; opq; opq = opq->prev) {
+ if(opq->reg_t[t] != gpr)
+ return;
+ if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) {
+ opq->tflags[t] |= TFLAG_SAVED;
+
+ /* FIXME: Check if this is still neccesary */
+ /* Before takeing the temporaries out, temporarily remove the op_do_sched
+ * operation such that dyn_page->ts_bound shall be correct before the
+ * scheduler runs */
+ if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
+ opq->num_ops--;
+ gen_op_move_gpr_t[t][gpr](opq, 1);
+ gen_op_do_sched(opq, 1);
+ return;
+ }
+
+ gen_op_move_gpr_t[t][gpr](opq, 1);
+
+ return;
+ }
+ }
+}
+
+static void ship_gprs_out_t(struct op_queue *opq)
+{
+ int i;
+
+ if(!opq)
+ return;
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] < 32)
+ /* Ship temporaries out in the last opq that actually touched it */
+ ship_t_out(opq, i);
+ }
+}
+
+/* FIXME: Look at the following instructions to make a better guess at which
+ * temporary to return */
+static int find_t(struct op_queue *opq, unsigned int reg)
+{
+ int i, j, t = -1;
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == reg)
+ return i;
+
+ /* Ok, we have found an as-yet unused temporary, check if it is needed
+ * later in this instruction */
+ for(j = 0; j < opq->param_num; j++) {
+ if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i]))
+ break;
+ }
+
+ if(j != opq->param_num)
+ continue;
+
+ /* We have found the temporary (temporarily:) fit for use */
+ if((t == -1) || (opq->reg_t[i] == 32))
+ t = i;
+ }
+
+ return t;
+}
+
+/* Checks if there is enough space in dp->host_page, if not grow it */
+void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
+ unsigned int amount)
+{
+ unsigned int used = cur - dp->host_page;
+
+ /* The array is long enough */
+ if((used + amount) <= *len)
+ return cur;
+
+ /* Reallocate */
+ *len += RECED_PAGE_ENLARGE_BY;
+
+ if(!(dp->host_page = realloc(dp->host_page, *len))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+
+ return dp->host_page + used;
+}
+
+/* Adds an operation to the opq */
+void add_to_opq(struct op_queue *opq, int end, int op)
+{
+ if(opq->num_ops == opq->ops_len) {
+ opq->ops_len += OPS_ENLARGE_BY;
+ if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ }
+
+ if(end)
+ opq->ops[opq->num_ops] = op;
+ else {
+ /* Shift everything over by one */
+ memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
+ opq->ops[0] = op;
+ }
+
+ opq->num_ops++;
+}
+
+static void gen_op_mark_loc(struct op_queue *opq, int end)
+{
+ add_to_opq(opq, end, op_mark_loc_indx);
+}
+
+/* Adds a parameter to the opq */
+void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
+{
+ if(opq->num_ops_param == opq->ops_param_len) {
+ opq->ops_param_len += OPS_ENLARGE_BY;
+ if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ }
+
+ if(end)
+ opq->ops_param[opq->num_ops_param] = param;
+ else {
+ /* Shift everything over by one */
+ memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
+ opq->ops_param[0] = param;
+ }
+
+ opq->num_ops_param++;
+}
+
+/* Initialises the recompiler */
+void init_dyn_recomp(void)
+{
+ struct sigaction sigact;
+ struct op_queue *opq = NULL;
+ unsigned int i;
+
+ cpu_state.opqs = NULL;
+
+ /* Allocate the operation queue list (+1 for the page chaining) */
+ for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) {
+ if(!(opq = malloc(sizeof(struct op_queue)))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+
+ /* initialise some fields */
+ opq->ops_len = 0;
+ opq->ops = NULL;
+ opq->ops_param_len = 0;
+ opq->ops_param = NULL;
+ opq->xref = 0;
+
+ if(cpu_state.opqs)
+ cpu_state.opqs->prev = opq;
+
+ opq->next = cpu_state.opqs;
+ cpu_state.opqs = opq;
+ }
+
+ opq->prev = NULL;
+
+ cpu_state.curr_page = NULL;
+ if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
+ immu_state->pagesize_log2))))) {
+ fprintf(stderr, "OOM\n");
+ exit(1);
+ }
+ memset(cpu_state.dyn_pages, 0,
+ sizeof(void *) * (2 << (32 - immu_state->pagesize_log2)));
+
+ /* Register our segmentation fault handler */
+ sigact.sa_sigaction = dyn_sigsegv_debug;
+ memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
+ sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
+ if(sigaction(SIGSEGV, &sigact, NULL))
+ printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
+
+ /* FIXME: Find a better place for this */
+ { /* Needed by execution */
+ extern int do_stats;
+ do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
+ || config.sim.history || config.sim.exe_log;
+ }
+
+ printf("Recompile engine up and running\n");
+}
+
+/* Parses instructions and their operands and populates opq with them */
+static void eval_insn_ops(struct op_queue *opq, oraddr_t addr)
+{
+ int breakp;
+ struct insn_op_struct *opd;
+
+ for(; opq->next; opq = opq->next, addr += 4) {
+ opq->param_num = 0;
+ breakp = 0;
+ opq->insn = eval_insn(addr, &breakp);
+
+ /* FIXME: If a breakpoint is set at this location, insert exception code */
+ if(breakp) {
+ fprintf(stderr, "FIXME: Insert breakpoint code\n");
+ }
+
+ opq->insn_index = insn_decode(opq->insn);
+
+ if(opq->insn_index == -1)
+ continue;
+
+ opd = op_start[opq->insn_index];
+
+ do {
+ opq->param[opq->param_num] = eval_operand_val(opq->insn, opd);
+ opq->param_type[opq->param_num] = opd->type;
+
+ opq->param_num++;
+ while(!(opd->type & OPTYPE_OP)) opd++;
+ } while(!(opd++->type & OPTYPE_LAST));
+ }
+}
+
+/* Adds code to the opq for the instruction pointed to by addr */
+static void recompile_insn(struct op_queue *opq, int delay_insn)
+{
+ int j, k;
+ int param_t[5]; /* Which temporary the parameters reside in */
+
+ /* Check if we have an illegal instruction */
+ if(opq->insn_index == -1) {
+ gen_l_invalid(opq, NULL, delay_insn);
+ return;
+ }
+
+ /* If we are recompileing an instruction that has a delay slot and is in the
+ * delay slot, ignore it. This is undefined behavour. */
+ if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY))
+ return;
+
+ param_t[0] = T_NONE;
+ param_t[1] = T_NONE;
+ param_t[2] = T_NONE;
+ param_t[3] = T_NONE;
+ param_t[4] = T_NONE;
+
+ /* Jump instructions are special since they have a delay slot and thus they
+ * need to control the exact operation sequence. Special case these here to
+ * avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */
+ if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) {
+ /* Jump instructions don't have a disposition */
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+
+ /* Analysis is done by the individual jump instructions */
+ /* Jump instructions don't touch runtime.sim.mem_cycles */
+ /* Jump instructions run their own scheduler */
+ return;
+ }
+
+ /* Before an exception takes place, all registers must be stored. */
+ if((or32_opcodes[opq->insn_index].func_unit == it_exception)) {
+ ship_gprs_out_t(opq);
+
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+ return;
+ }
+
+ for(j = 0; j < opq->param_num; j++) {
+ if(!(opq->param_type[j] & OPTYPE_REG))
+ continue;
+
+ /* Never, ever, move r0 into a temporary */
+ if(!opq->param[j])
+ continue;
+
+ k = find_t(opq, opq->param[j]);
+
+ param_t[j] = k;
+
+ if(opq->reg_t[k] == opq->param[j]) {
+ if(!(opq->param_type[j] & OPTYPE_DST) &&
+ !(opq->tflags[k] & TFLAG_SOURCED)) {
+ gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
+ opq->tflags[k] |= TFLAG_SOURCED;
+ }
+
+ if(opq->param_type[j] & OPTYPE_DST)
+ opq->tflags[k] |= TFLAG_DST;
+ else
+ opq->tflags[k] |= TFLAG_SRC;
+
+ continue;
+ }
+
+ if(opq->reg_t[k] < 32) {
+ /* Only ship the temporary out if it has been used as a destination
+ * register */
+ ship_t_out(opq, k);
+ }
+
+ if(opq->param_type[j] & OPTYPE_DST)
+ opq->tflags[k] = TFLAG_DST;
+ else
+ opq->tflags[k] = TFLAG_SRC;
+
+ opq->reg_t[k] = opq->param[j];
+
+ /* Only generate code to move the register into a temporary if it is used as
+ * a source operand */
+ if(!(opq->param_type[j] & OPTYPE_DST)) {
+ gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
+ opq->tflags[k] |= TFLAG_SOURCED;
+ }
+ }
+
+ /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
+ * effective address needs to be calculated before the instruction is
+ * simulated */
+ if(do_stats) {
+ for(j = 0; j < opq->param_num; j++) {
+ if(!(opq->param_type[j] & OPTYPE_DIS))
+ continue;
+
+ if(!opq->param[j + 1])
+ gen_op_store_insn_ea(opq, 1, opq->param[j]);
+ else
+ calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]);
+ }
+ }
+
+ or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
+
+ if(do_stats) {
+ ship_gprs_out_t(opq);
+ gen_op_analysis(opq, 1);
+ }
+
+ /* The call to join_mem_cycles() could be put into the individual operations
+ * that emulate the load/store instructions, but then it would be added to
+ * the cycle counter before analysis() is called, which is not how the complex
+ * execution model does it. */
+ if((or32_opcodes[opq->insn_index].func_unit == it_load) ||
+ (or32_opcodes[opq->insn_index].func_unit == it_store))
+ gen_op_join_mem_cycles(opq, 1);
+
+ /* Delay slot instructions get a special scheduler, thus don't generate it
+ * here */
+ if(!delay_insn)
+ gen_op_do_sched(opq, 1);
+}
+
+/* Recompiles the page associated with *dyn */
+void recompile_page(struct dyn_page *dyn)
+{
+ unsigned int j;
+ struct op_queue *opq = cpu_state.opqs;
+ oraddr_t rec_addr = dyn->or_page;
+ oraddr_t rec_page = dyn->or_page;
+ void **loc;
+
+ /* The start of the next page */
+ rec_page += immu_state->pagesize;
+
+ printf("Recompileing page %"PRIxADDR"\n", rec_addr);
+ fflush(stdout);
+
+ /* Mark all temporaries as not containing a register */
+ for(j = 0; j < NUM_T_REGS; j++) {
+ opq->reg_t[j] = 32; /* Out-of-range registers */
+ opq->tflags[j] = 0;
+ }
+
+ dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr;
+
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+
+ eval_insn_ops(opq, rec_addr);
+
+ /* Insert code to check if the first instruction is exeucted in a delay slot*/
+ gen_op_check_delay_slot(opq, 1, 0);
+ recompile_insn(opq, 1);
+ ship_gprs_out_t(opq);
+ gen_op_do_sched_delay(opq, 1);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_jump_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+ gen_op_mark_loc(opq, 1);
+
+ for(j = 0; j < NUM_T_REGS; j++)
+ opq->reg_t[j] = 32; /* Out-of-range registers */
+
+ for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
+ if(opq->prev) {
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+ }
+ opq->jump_local = -1;
+ opq->not_jump_loc = -1;
+
+ opq->insn_addr = rec_addr;
+
+ for(j = 0; j < NUM_T_REGS; j++)
+ opq->tflags[j] = TFLAG_SOURCED;
+
+ /* Check if this location is cross referenced */
+ if(opq->xref) {
+ /* If the current address is cross-referenced, the temporaries shall be
+ * in an undefined state, so we must assume that no registers reside in
+ * them */
+ /* Ship out the current set of registers from the temporaries */
+ if(opq->prev) {
+ ship_gprs_out_t(opq->prev);
+ for(j = 0; j < NUM_T_REGS; j++) {
+ opq->reg_t[j] = 32;
+ opq->prev->reg_t[j] = 32;
+ }
+ }
+ }
+
+ recompile_insn(opq, 0);
+
+ /* Store the state of the temporaries */
+ memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
+ }
+
+ dyn->dirty = 0;
+
+ /* Ship temporaries out to the corrisponding registers */
+ ship_gprs_out_t(opq->prev);
+
+ opq->num_ops = 0;
+ opq->num_ops_param = 0;
+ opq->not_jump_loc = -1;
+ opq->jump_local = -1;
+
+ /* Insert code to jump to the next page */
+ gen_op_do_jump(opq, 1);
+
+ /* Generate the code */
+ gen_code(cpu_state.opqs, dyn);
+
+ /* Fix up the locations */
+ for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++)
+ *loc += (unsigned int)dyn->host_page;
+
+ cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
+
+ /* Search for page-local jumps */
+ opq = cpu_state.opqs;
+ for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) {
+ if(opq->jump_local != -1)
+ opq->ops_param[opq->jump_local] =
+ (unsigned int)dyn->locs[opq->jump_local_loc >> 2];
+
+ if(opq->not_jump_loc != -1)
+ opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
+
+ /* Store the state of the temporaries into dyn->ts_bound */
+ dyn->ts_bound[j] = 0;
+ if(opq->reg_t[0] < 32)
+ dyn->ts_bound[j] = opq->reg_t[0];
+ if(opq->reg_t[1] < 32)
+ dyn->ts_bound[j] |= opq->reg_t[1] << 5;
+ if(opq->reg_t[2] < 32)
+ dyn->ts_bound[j] |= opq->reg_t[2] << 10;
+
+ /* Reset for the next page to be recompiled */
+ opq->xref = 0;
+ }
+
+ /* Patch the relocations */
+ patch_relocs(cpu_state.opqs, dyn->host_page);
+
+ if(do_stats) {
+ opq = cpu_state.opqs;
+ for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) {
+ dyn->insns[j] = opq->insn;
+ dyn->insn_indexs[j] = opq->insn_index;
+ }
+ }
+
+ /* FIXME: Fix the issue below in a more elegent way */
+ /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
+ * updated but the recompiler expectes it to start a 0, so reset it */
+ runtime.sim.mem_cycles = 0;
+}
+
+/* Recompiles a delay-slot instruction (opq is the opq of the instruction
+ * haveing the delay-slot) */
+static void recompile_delay_insn(struct op_queue *opq)
+{
+ struct op_queue delay_opq;
+ int i;
+
+ /* Setup a fake opq that looks very much like the delay slot instruction */
+ memcpy(&delay_opq, opq, sizeof(struct op_queue));
+ /* `Fix' a couple of bits */
+ for(i = 0; i < NUM_T_REGS; i++)
+ delay_opq.tflags[i] = TFLAG_SOURCED;
+ delay_opq.insn_index = opq->next->insn_index;
+ memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type));
+ memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param));
+ delay_opq.param_num = opq->next->param_num;
+ delay_opq.insn = opq->next->insn;
+
+ delay_opq.xref = 0;
+ delay_opq.insn_addr = opq->insn_addr + 4;
+ delay_opq.prev = opq->prev;
+ delay_opq.next = NULL;
+
+ /* Generate the delay slot instruction */
+ recompile_insn(&delay_opq, 1);
+
+ ship_gprs_out_t(&delay_opq);
+
+ opq->num_ops = delay_opq.num_ops;
+ opq->ops_len = delay_opq.ops_len;
+ opq->ops = delay_opq.ops;
+ opq->num_ops_param = delay_opq.num_ops_param;
+ opq->ops_param_len = delay_opq.ops_param_len;
+ opq->ops_param = delay_opq.ops_param;
+
+ for(i = 0; i < NUM_T_REGS; i++)
+ opq->reg_t[i] = 32;
+}
+
+/* Returns non-zero if the jump is into this page, 0 otherwise */
+static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
+{
+ int i;
+
+ /* Mark the jump as non page local if the delay slot instruction is on the
+ * next page to the jump instruction. This should not be needed */
+ if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr))
+ /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
+ * VIRTUAL offset and the next physical page may not be the next VIRTUAL
+ * page */
+ return 0;
+
+ /* The jump is into the page currently undergoing dynamic recompilation */
+
+ /* If we haven't got to the location of the jump, everything is ok */
+ if(j_ea > opq->insn_addr) {
+ /* Find the corissponding opq and mark it as cross referenced */
+ for(i = (j_ea - opq->insn_addr) / 4; i; i--)
+ opq = opq->next;
+ opq->xref = 1;
+ return 1;
+ }
+
+ /* Insert temporary -> register code before the jump ea and register ->
+ * temporary at the x-ref address */
+ for(i = (opq->insn_addr - j_ea) / 4; i; i--)
+ opq = opq->prev;
+
+ if(!opq->prev)
+ /* We're at the begining of a page, no need to do anything */
+ return 1;
+
+ /* Found location, insert code */
+
+ ship_gprs_out_t(opq->prev);
+
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->prev->reg_t[i] < 32)
+ /* FIXME: Ship temporaries in the begining of the opq that needs it */
+ gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0);
+ }
+
+ opq->xref = 1;
+
+ return 1;
+}
+
+static void gen_j_imm(struct op_queue *opq, oraddr_t off)
+{
+ int jump_local;
+
+ off <<= 2;
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_set_pc_delay_imm(opq, 1, off);
+ gen_op_do_sched(opq, 1);
+ return;
+ }
+
+ jump_local = find_jump_loc(opq->insn_addr + off, opq);
+
+ gen_op_set_delay_insn(opq, 1);
+ gen_op_do_sched(opq, 1);
+
+ recompile_delay_insn(opq);
+
+ gen_op_add_pc(opq, 1, (orreg_t)off - 8);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_sched_delay(opq, 1);
+
+ if(jump_local) {
+ gen_op_jmp_imm(opq, 1, 0);
+ opq->jump_local = opq->num_ops_param - 1;
+ opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask;
+ } else
+ gen_op_do_jump(opq, 1);
+}
+
+static const generic_gen_op set_pc_delay_gpr[32] = {
+ NULL,
+ gen_op_move_gpr1_pc_delay,
+ gen_op_move_gpr2_pc_delay,
+ gen_op_move_gpr3_pc_delay,
+ gen_op_move_gpr4_pc_delay,
+ gen_op_move_gpr5_pc_delay,
+ gen_op_move_gpr6_pc_delay,
+ gen_op_move_gpr7_pc_delay,
+ gen_op_move_gpr8_pc_delay,
+ gen_op_move_gpr9_pc_delay,
+ gen_op_move_gpr10_pc_delay,
+ gen_op_move_gpr11_pc_delay,
+ gen_op_move_gpr12_pc_delay,
+ gen_op_move_gpr13_pc_delay,
+ gen_op_move_gpr14_pc_delay,
+ gen_op_move_gpr15_pc_delay,
+ gen_op_move_gpr16_pc_delay,
+ gen_op_move_gpr17_pc_delay,
+ gen_op_move_gpr18_pc_delay,
+ gen_op_move_gpr19_pc_delay,
+ gen_op_move_gpr20_pc_delay,
+ gen_op_move_gpr21_pc_delay,
+ gen_op_move_gpr22_pc_delay,
+ gen_op_move_gpr23_pc_delay,
+ gen_op_move_gpr24_pc_delay,
+ gen_op_move_gpr25_pc_delay,
+ gen_op_move_gpr26_pc_delay,
+ gen_op_move_gpr27_pc_delay,
+ gen_op_move_gpr28_pc_delay,
+ gen_op_move_gpr29_pc_delay,
+ gen_op_move_gpr30_pc_delay,
+ gen_op_move_gpr31_pc_delay };
+
+static void gen_j_reg(struct op_queue *opq, unsigned int gpr)
+{
+ int i;
+
+ /* Ship the jump-to register out (if it exists). It requires special
+ * handleing */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == opq->param[0])
+ /* Ship temporary out in the last opq that used it */
+ ship_t_out(opq, i);
+ }
+
+ if(do_stats)
+ gen_op_analysis(opq, 1);
+
+ if(!gpr)
+ gen_op_clear_pc_delay(opq, 1);
+ else
+ set_pc_delay_gpr[gpr](opq, 1);
+
+ gen_op_do_sched(opq, 1);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4))
+ return;
+
+ recompile_delay_insn(opq);
+
+ gen_op_set_pc_pc_delay(opq, 1);
+ gen_op_clear_delay_insn(opq, 1);
+ gen_op_do_sched_delay(opq, 1);
+
+ gen_op_do_jump_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/*------------------------------[ Operation generation for an instruction ]---*/
+/* FIXME: Flag setting is not done in any instruction */
+/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
+
+DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear);
+DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move);
+DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm);
+
+DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm);
+DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add);
+
+void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ /* Just clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if(opq->param[0] != opq->param[1])
+ /* This just moves a register */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Check if we are moveing an immediate */
+ if(param_t[2] == T_NONE) {
+ /* Yep, an immediate */
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ /* Just another move */
+ if(opq->param[0] != opq->param[2])
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ /* Ok, This _IS_ an add... */
+ if(param_t[2] == T_NONE)
+ /* immediate */
+ l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc);
+
+void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ /* FIXME: More optimisations !! (...and immediate...) */
+ l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm);
+DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and);
+
+void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ /* Screw this, the operation shall do nothing */
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ /* Just clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if((opq->param[0] == opq->param[1]) &&
+ (opq->param[0] == opq->param[2]) &&
+ (param_t[2] != T_NONE))
+ return;
+
+ if(param_t[2] == T_NONE)
+ l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ /* The temporaries are expected to be shiped out after the execution of the
+ * branch instruction wether it branched or not */
+ ship_gprs_out_t(opq->prev);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_check_flag_delay(opq, 1, opq->param[0] << 2);
+ gen_op_do_sched(opq, 1);
+ opq->not_jump_loc = -1;
+ return;
+ }
+
+ gen_op_check_flag(opq, 1, 0);
+ opq->not_jump_loc = opq->num_ops_param - 1;
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ /* The temporaries are expected to be shiped out after the execution of the
+ * branch instruction wether it branched or not */
+ ship_gprs_out_t(opq->prev);
+
+ if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
+ gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2);
+ gen_op_do_sched(opq, 1);
+ opq->not_jump_loc = -1;
+ return;
+ }
+
+ gen_op_check_not_flag(opq, 1, 0);
+ opq->not_jump_loc = opq->num_ops_param - 1;
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov);
+
+/* FIXME: Check if either opperand 1 or 2 is r0 */
+void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1]))
+ return;
+
+ if(opq->param[1] == opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+}
+
+/* FIXME: All registers need to be stored before the div instructions as they
+ * have the potenticial to cause an exception */
+
+DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except);
+DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay);
+DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div);
+
+void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[2]) {
+ /* There is no option. This _will_ cause an illeagal exception */
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+ return;
+ }
+
+ if(!delay_slot)
+ check_null_excpt[param_t[2]](opq, 1);
+ else
+ check_null_excpt_delay[param_t[2]](opq, 1);
+
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ /* Clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu);
+
+void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[2]) {
+ /* There is no option. This _will_ cause an illeagal exception */
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+ return;
+ }
+
+ if(!delay_slot)
+ check_null_excpt[param_t[2]](opq, 1);
+ else
+ check_null_excpt_delay[param_t[2]](opq, 1);
+
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ /* Clear param_t[0] */
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs);
+
+void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz);
+
+void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths);
+
+void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz);
+
+void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(opq->param[0] == opq->param[1])
+ return;
+
+ /* In the 32-bit architechture this instruction reduces to a move */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(opq->param[0] == opq->param[1])
+ return;
+
+ /* In the 32-bit architechture this instruction reduces to a move */
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1);
+
+void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ int i;
+
+ /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
+ * a temporary. The problem is that the l.jal(r) instruction stores the
+ * `return address' in LINK_REGNO. The temporaries are shiped out only
+ * after the delay slot instruction has executed and so it overwrittes the
+ * `return address'. */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == LINK_REGNO) {
+ /* Don't bother storeing the register, it is going to get clobered in this
+ * instruction anyway */
+ opq->reg_t[i] = 32;
+ break;
+ }
+ }
+
+ /* Store the return address */
+ gen_op_store_link_addr_gpr(opq, 1);
+
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_j_imm(opq, opq->param[0]);
+}
+
+void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_j_reg(opq, opq->param[0]);
+}
+
+void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ int i;
+
+ /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
+ * a temporary. The problem is that the l.jal(r) instruction stores the
+ * `return address' in LINK_REGNO. The temporaries are shiped out only
+ * after the delay slot instruction has executed and so it overwrittes the
+ * `return address'. */
+ for(i = 0; i < NUM_T_REGS; i++) {
+ if(opq->reg_t[i] == LINK_REGNO) {
+ /* Don't bother storeing the register, it is going to get clobered in this
+ * instruction anyway */
+ opq->reg_t[i] = 32;
+ break;
+ }
+ }
+
+ /* Store the return address */
+ gen_op_store_link_addr_gpr(opq, 1);
+
+ gen_j_reg(opq, opq->param[0]);
+}
+
+/* FIXME: Optimise all load instruction when the disposition == 0 */
+
+DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm);
+DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs);
+
+void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm);
+DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz);
+
+void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm);
+DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs);
+
+void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm);
+DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz);
+
+void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm);
+DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws);
+
+void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm);
+DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz);
+
+void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ /* FIXME: This will work, but the statistics need to be updated... */
+ return;
+ }
+
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ /* Load the data from the immediate */
+ l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ return;
+ }
+
+ l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
+}
+
+DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm);
+DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac);
+
+void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] || !opq->param[1])
+ return;
+
+ if(param_t[1] == T_NONE)
+ l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc);
+
+void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0]) {
+ gen_op_macc(opq, 1);
+ return;
+ }
+
+ l_macrc_t_table[param_t[0]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm);
+DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr);
+
+void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+}
+
+void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16);
+}
+
+DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb);
+
+void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] || !opq->param[1])
+ return;
+
+ l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear);
+DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm);
+DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr);
+
+void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[0]) {
+ if(!opq->param[1]) {
+ /* Clear the immediate SPR */
+ gen_op_mtspr_imm_clear(opq, 1, opq->param[2]);
+ return;
+ }
+ l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+
+ l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+}
+
+DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm);
+DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul);
+
+void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu);
+
+void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1] || !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Do parameter switch now */
+ switch(opq->param[0]) {
+ case NOP_NOP:
+ break;
+ case NOP_EXIT:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_exit(opq, 1);
+ break;
+ case NOP_CNT_RESET:
+ gen_op_nop_reset(opq, 1);
+ break;
+ case NOP_PRINTF:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_printf(opq, 1);
+ break;
+ case NOP_REPORT:
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_report(opq, 1);
+ break;
+ default:
+ if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) {
+ ship_gprs_out_t(opq->prev);
+ gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST);
+ }
+ break;
+ }
+}
+
+DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm);
+DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or);
+
+void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((opq->param[0] == opq->param[1]) &&
+ (opq->param[0] == opq->param[2]) &&
+ (param_t[2] != T_NONE))
+ return;
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
+ return;
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Check if we are moveing an immediate */
+ if(param_t[2] == T_NONE) {
+ /* Yep, an immediate */
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ /* Just another move */
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ gen_op_prep_rfe(opq, 1);
+ /* FIXME: rename op_do_sched_delay */
+ gen_op_do_sched_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/* FIXME: All store instructions should be optimised when the disposition = 0 */
+
+DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear);
+DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm);
+DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb);
+
+void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sb_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear);
+DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm);
+DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh);
+
+void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sh_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear);
+DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm);
+DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw);
+
+void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ /* Just in case an exception happens */
+ ship_gprs_out_t(opq->prev);
+
+ if(!opq->param[2]) {
+ if(!opq->param[1]) {
+ gen_op_sw_clear_imm(opq, 1, opq->param[0]);
+ return;
+ }
+ l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ /* Store the data to the immediate */
+ l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
+ return;
+ }
+
+ l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null);
+DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm);
+DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq);
+
+void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ if(param_t[1] == T_NONE) {
+ if(!opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfeq_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfeq_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null);
+DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null);
+DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm);
+DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges);
+
+void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfles IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 >= (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfles_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfges_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null);
+DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null);
+DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm);
+DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu);
+
+void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfleu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 >= opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfleu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgeu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+ if(param_t[1] == T_NONE)
+ l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null);
+DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null);
+DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm);
+DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts);
+
+void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sflts IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 > (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sflts_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgts_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null);
+DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null);
+DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm);
+DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu);
+
+void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfltu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 > opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfltu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfgtu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm);
+DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles);
+
+void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfges IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 <= (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfges_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfles_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm);
+DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu);
+
+void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfleu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 <= opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgeu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfleu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm);
+DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts);
+
+void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfgts IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 < (orreg_t)opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgts_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sflts_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm);
+DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu);
+
+void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_clear_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ /* sfgtu IS correct */
+ if(param_t[1] == T_NONE) {
+ if(0 < opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ } else
+ l_sfgtu_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfltu_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null);
+DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm);
+DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne);
+
+void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0] && !opq->param[1]) {
+ gen_op_set_flag(opq, 1);
+ return;
+ }
+
+ if(!opq->param[0]) {
+ if(param_t[1] == T_NONE)
+ if(opq->param[1])
+ gen_op_set_flag(opq, 1);
+ else
+ gen_op_clear_flag(opq, 1);
+ else
+ l_sfne_null_t_table[param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ l_sfne_null_t_table[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(param_t[1] == T_NONE)
+ l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
+ else
+ l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm);
+DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll);
+
+void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm);
+DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra);
+
+void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm);
+DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl);
+
+void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if(!opq->param[1]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg);
+DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub);
+
+void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1] && !opq->param[2]) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ if(param_t[2] == T_NONE)
+ mov_t_imm[param_t[0]](opq, 1, -opq->param[2]);
+ else
+ l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+/* FIXME: This will not work if the l.sys is in a delay slot */
+void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ if(!delay_slot)
+ gen_op_prep_sys(opq, 1);
+ else
+ gen_op_prep_sys_delay(opq, 1);
+
+ gen_op_do_sched(opq, 1);
+ gen_op_do_jump(opq, 1);
+}
+
+/* FIXME: This will not work if the l.trap is in a delay slot */
+void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(do_stats)
+ /* All gprs are current since this insn doesn't touch any reg */
+ gen_op_analysis(opq, 1);
+
+ if(!delay_slot)
+ gen_op_prep_trap(opq, 1);
+ else
+ gen_op_prep_trap_delay(opq, 1);
+}
+
+DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm);
+/* FIXME: Make unused elements NULL */
+DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor);
+
+void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!opq->param[0])
+ return;
+
+ if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
+ clear_t[param_t[0]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[2]) {
+ if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
+ return;
+ move_t_t[param_t[0]][param_t[1]](opq, 1);
+ return;
+ }
+
+ if(!opq->param[1]) {
+ if(param_t[2] == T_NONE) {
+ mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
+ return;
+ }
+ move_t_t[param_t[0]][param_t[2]](opq, 1);
+ return;
+ }
+
+ if(param_t[2] == T_NONE)
+ l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
+ else
+ l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
+}
+
+void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ if(!delay_slot) {
+ gen_op_illegal(opq, 1);
+ gen_op_do_jump(opq, 1);
+ } else {
+ gen_op_illegal_delay(opq, 1);
+ gen_op_do_jump(opq, 1);
+ }
+}
+
+/*----------------------------------[ Floating point instructions (stubs) ]---*/
+void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
+void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot)
+{
+ gen_l_invalid(opq, param_t, delay_slot);
+}
+
dyn-rec.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-arith-op.h
===================================================================
--- op-arith-op.h (nonexistent)
+++ op-arith-op.h (revision 135)
@@ -0,0 +1,33 @@
+/* op-arith-op.h -- Micro operations template for arithmetic operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef OP_3T
+__or_dynop void glue(glue(op_, OP_NAME), T)(void)
+{
+ T0 = OP_CAST(T1) OP OP_CAST(T2) OP_EXTRA;
+}
+#endif
+
+#ifdef OP_2T
+__or_dynop void glue(glue(glue(op_, OP_NAME), _imm), T)(void)
+{
+ T0 = OP_CAST(T1) OP OP_CAST(OP_PARAM1) OP_EXTRA;
+}
+#endif
+
op-arith-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-1t.h
===================================================================
--- op-1t.h (nonexistent)
+++ op-1t.h (revision 135)
@@ -0,0 +1,38 @@
+/* op-1t.h -- Instantiation of operatations that work on only 1 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define OP_1T
+#define T glue(_, T0)
+
+#if NUM_T_REGS == 3
+#define T0 t0
+#include OP_FILE
+#undef T0
+#define T0 t1
+#include OP_FILE
+#undef T0
+#define T0 t2
+#include OP_FILE
+#undef T0
+#else
+#error Update op_1t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_1T
op-1t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyn-rec.h
===================================================================
--- dyn-rec.h (nonexistent)
+++ dyn-rec.h (revision 135)
@@ -0,0 +1,70 @@
+/* dyn-rec.h -- Recompiler specific definitions
+
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributor Jeremy Bennett
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef DYN_REC__H
+#define DYN_REC__H
+
+typedef void (*gen_code_ent)(void);
+
+/* Each dynamically recompiled page has one of these */
+struct dyn_page {
+ oraddr_t or_page;
+ void *host_page;
+ unsigned int host_len;
+ int dirty; /* Is recompiled page invalid? */
+ int delayr; /* delayr of memory backing this page */
+ uint16_t ts_bound[2049]; /* What registers the temporaries back (on the
+ * begining boundry of the instruction) */
+ void **locs; /* Openrisc locations in the recompiled code */
+ uint32_t *insns; /* Copy of instructions on this page */
+ unsigned int *insn_indexs; /* Decoded instructions on this page */
+};
+
+/* Function prototypes for external use */
+extern void recompile_page(struct dyn_page *dyn);
+extern struct dyn_page *new_dp(oraddr_t page);
+extern void add_to_opq(struct op_queue *opq, int end, int op);
+extern void add_to_op_params(struct op_queue *opq, int end, unsigned long param);
+extern void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
+ unsigned int amount);
+extern void init_dyn_recomp(void);
+extern void run_sched_out_of_line(void);
+extern void recheck_immu(int got_en_dis);
+extern void enter_dyn_code(oraddr_t addr, struct dyn_page *dp);
+extern void dyn_checkwrite(oraddr_t addr);
+extern void dyn_main(void);
+
+/* Global variables for external use */
+extern void *rec_stack_base;
+
+#define IMMU_GOT_ENABLED 1
+#define IMMU_GOT_DISABLED 2
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+
+#endif /* DYN_REC__H */
+
dyn-rec.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-3t.h
===================================================================
--- op-3t.h (nonexistent)
+++ op-3t.h (revision 135)
@@ -0,0 +1,135 @@
+/* op-3t.h -- Instantiation of operatations that work on only 3 temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define OP_3T
+#define T glue(glue(glue(glue(glue(_, T0), _), T1), _), T2)
+
+#if NUM_T_REGS == 3
+# define T0 t0
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+# define T0 t1
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+# define T0 t2
+# define T1 t0
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t1
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# define T1 t2
+# define T2 t0
+# include OP_FILE
+# undef T2
+# define T2 t1
+# include OP_FILE
+# undef T2
+# define T2 t2
+# include OP_FILE
+# undef T2
+# undef T1
+# undef T0
+#else
+#error Update op_3t.h for NUM_T_REGS temporaries
+#endif
+
+#undef T
+#undef OP_3T
op-3t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-ff1-op.h
===================================================================
--- op-ff1-op.h (nonexistent)
+++ op-ff1-op.h (revision 135)
@@ -0,0 +1,35 @@
+/* op-ff1-op.h -- Micro operations template for the ff1 instruction
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(glue(glue(op_ff1_, DST_T), _), SRC_T)(void)
+{
+ int i;
+
+ for(i = 0; i < 32; i++, SRC_T >>= 1) {
+ if(SRC_T & 1) {
+ DST_T = i;
+ break;
+ }
+ }
+
+ FORCE_RET;
+}
+
+
op-ff1-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-t-reg-mov-op.h
===================================================================
--- op-t-reg-mov-op.h (nonexistent)
+++ op-t-reg-mov-op.h (revision 135)
@@ -0,0 +1,330 @@
+/* op-t-reg-mov-op.h -- Micro operations template for reg<->temporary operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(op_gtt_gpr1, T)(void)
+{
+ T0 = env->reg[1];
+}
+
+__or_dynop void glue(op_gtt_gpr2, T)(void)
+{
+ T0 = env->reg[2];
+}
+
+__or_dynop void glue(op_gtt_gpr3, T)(void)
+{
+ T0 = env->reg[3];
+}
+
+__or_dynop void glue(op_gtt_gpr4, T)(void)
+{
+ T0 = env->reg[4];
+}
+
+__or_dynop void glue(op_gtt_gpr5, T)(void)
+{
+ T0 = env->reg[5];
+}
+
+__or_dynop void glue(op_gtt_gpr6, T)(void)
+{
+ T0 = env->reg[6];
+}
+
+__or_dynop void glue(op_gtt_gpr7, T)(void)
+{
+ T0 = env->reg[7];
+}
+
+__or_dynop void glue(op_gtt_gpr8, T)(void)
+{
+ T0 = env->reg[8];
+}
+
+__or_dynop void glue(op_gtt_gpr9, T)(void)
+{
+ T0 = env->reg[9];
+}
+
+__or_dynop void glue(op_gtt_gpr10, T)(void)
+{
+ T0 = env->reg[10];
+}
+
+__or_dynop void glue(op_gtt_gpr11, T)(void)
+{
+ T0 = env->reg[11];
+}
+
+__or_dynop void glue(op_gtt_gpr12, T)(void)
+{
+ T0 = env->reg[12];
+}
+
+__or_dynop void glue(op_gtt_gpr13, T)(void)
+{
+ T0 = env->reg[13];
+}
+
+__or_dynop void glue(op_gtt_gpr14, T)(void)
+{
+ T0 = env->reg[14];
+}
+
+__or_dynop void glue(op_gtt_gpr15, T)(void)
+{
+ T0 = env->reg[15];
+}
+
+__or_dynop void glue(op_gtt_gpr16, T)(void)
+{
+ T0 = env->reg[16];
+}
+
+__or_dynop void glue(op_gtt_gpr17, T)(void)
+{
+ T0 = env->reg[17];
+}
+
+__or_dynop void glue(op_gtt_gpr18, T)(void)
+{
+ T0 = env->reg[18];
+}
+
+__or_dynop void glue(op_gtt_gpr19, T)(void)
+{
+ T0 = env->reg[19];
+}
+
+__or_dynop void glue(op_gtt_gpr20, T)(void)
+{
+ T0 = env->reg[20];
+}
+
+__or_dynop void glue(op_gtt_gpr21, T)(void)
+{
+ T0 = env->reg[21];
+}
+
+__or_dynop void glue(op_gtt_gpr22, T)(void)
+{
+ T0 = env->reg[22];
+}
+
+__or_dynop void glue(op_gtt_gpr23, T)(void)
+{
+ T0 = env->reg[23];
+}
+
+__or_dynop void glue(op_gtt_gpr24, T)(void)
+{
+ T0 = env->reg[24];
+}
+
+__or_dynop void glue(op_gtt_gpr25, T)(void)
+{
+ T0 = env->reg[25];
+}
+
+__or_dynop void glue(op_gtt_gpr26, T)(void)
+{
+ T0 = env->reg[26];
+}
+
+__or_dynop void glue(op_gtt_gpr27, T)(void)
+{
+ T0 = env->reg[27];
+}
+
+__or_dynop void glue(op_gtt_gpr28, T)(void)
+{
+ T0 = env->reg[28];
+}
+
+__or_dynop void glue(op_gtt_gpr29, T)(void)
+{
+ T0 = env->reg[29];
+}
+
+__or_dynop void glue(op_gtt_gpr30, T)(void)
+{
+ T0 = env->reg[30];
+}
+
+__or_dynop void glue(op_gtt_gpr31, T)(void)
+{
+ T0 = env->reg[31];
+}
+
+__or_dynop void glue(op_ttg_gpr1, T)(void)
+{
+ env->reg[1] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr2, T)(void)
+{
+ env->reg[2] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr3, T)(void)
+{
+ env->reg[3] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr4, T)(void)
+{
+ env->reg[4] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr5, T)(void)
+{
+ env->reg[5] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr6, T)(void)
+{
+ env->reg[6] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr7, T)(void)
+{
+ env->reg[7] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr8, T)(void)
+{
+ env->reg[8] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr9, T)(void)
+{
+ env->reg[9] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr10, T)(void)
+{
+ env->reg[10] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr11, T)(void)
+{
+ env->reg[11] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr12, T)(void)
+{
+ env->reg[12] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr13, T)(void)
+{
+ env->reg[13] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr14, T)(void)
+{
+ env->reg[14] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr15, T)(void)
+{
+ env->reg[15] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr16, T)(void)
+{
+ env->reg[16] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr17, T)(void)
+{
+ env->reg[17] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr18, T)(void)
+{
+ env->reg[18] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr19, T)(void)
+{
+ env->reg[19] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr20, T)(void)
+{
+ env->reg[20] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr21, T)(void)
+{
+ env->reg[21] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr22, T)(void)
+{
+ env->reg[22] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr23, T)(void)
+{
+ env->reg[23] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr24, T)(void)
+{
+ env->reg[24] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr25, T)(void)
+{
+ env->reg[25] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr26, T)(void)
+{
+ env->reg[26] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr27, T)(void)
+{
+ env->reg[27] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr28, T)(void)
+{
+ env->reg[28] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr29, T)(void)
+{
+ env->reg[29] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr30, T)(void)
+{
+ env->reg[30] = T0;
+}
+
+__or_dynop void glue(op_ttg_gpr31, T)(void)
+{
+ env->reg[31] = T0;
+}
+
op-t-reg-mov-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen-i386.c
===================================================================
--- dyngen-i386.c (nonexistent)
+++ dyngen-i386.c (revision 135)
@@ -0,0 +1,75 @@
+/* dyngen-i386.c -- i386 parts of dyngen
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include
+
+#include "dyngen.h"
+
+#define RET_OPCODE 0xc3
+
+unsigned int i386_get_real_func_len(void *f_start, unsigned int f_len, char *name)
+{
+ if(((uint8_t *)f_start)[f_len - 1] != RET_OPCODE) {
+ fprintf(stderr, "`%s' does not have a ret at the end!\n", name);
+ exit(1);
+ }
+
+ return f_len - 1;
+}
+
+void i386_gen_reloc(FILE *f, struct reloc *reloc, unsigned int param)
+{
+ switch(reloc->type) {
+ case R_386_32:
+ fprintf(f, " *(uint32_t *)(host_page + %d) = *(ops_param + %u) + %d;\n",
+ reloc->func_offset, param - 1, reloc->addend);
+ break;
+ default:
+ fprintf(stderr, "Unknown i386 relocation: %i (%s)\n", reloc->type,
+ reloc->name);
+ }
+}
+
+void i386_gen_func_reloc(FILE *f, struct reloc *reloc)
+{
+ switch(reloc->type) {
+ case R_386_32:
+ /* This relocation is absolute. There is nothing to relocate (The linker
+ * handles this fine). */
+ break;
+ case R_386_PC32:
+ fprintf(f, " *(uint32_t *)(host_page + %d) = (uint32_t)((%s + %d) - (unsigned int)(host_page + %d));\n",
+ reloc->func_offset, reloc->name, reloc->addend, reloc->func_offset);
+ break;
+ default:
+ fprintf(stderr, "Unknown i386 relocation: %i (symbol: %s)\n", reloc->type,
+ reloc->name);
+ }
+}
+
+const struct archf archfs = {
+ i386_get_real_func_len,
+ i386_gen_reloc,
+ i386_gen_func_reloc
+};
dyngen-i386.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: simpl32-defs.h
===================================================================
--- simpl32-defs.h (nonexistent)
+++ simpl32-defs.h (revision 135)
@@ -0,0 +1,112 @@
+/* simpl32-defs.h -- Definitions for the simple execution model
+
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+ Copyright (C) 2008 Embecosm Limited
+
+ Contributed by Damjan Lampret (lampret@opencores.org).
+ Contributor Jeremy Bennett
+
+ This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
+ This file is also part of or1k_gen_isa, GDB and GAS.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see . */
+
+/* This program is commented throughout in a fashion suitable for processing
+ with Doxygen. */
+
+
+#ifndef SIMPLE32_DEFS__H
+#define SIMPLE32_DEFS__H
+
+/* Package includes */
+#include "abstract.h"
+
+
+extern void l_invalid PARAMS((struct iqueue_entry *));
+extern void l_sfne PARAMS((struct iqueue_entry *));
+extern void l_bf PARAMS((struct iqueue_entry *));
+extern void l_add PARAMS((struct iqueue_entry *));
+extern void l_addc PARAMS((struct iqueue_entry *));
+extern void l_sw PARAMS((struct iqueue_entry *));
+extern void l_sb PARAMS((struct iqueue_entry *));
+extern void l_sh PARAMS((struct iqueue_entry *));
+extern void l_lwz PARAMS((struct iqueue_entry *));
+extern void l_lbs PARAMS((struct iqueue_entry *));
+extern void l_lbz PARAMS((struct iqueue_entry *));
+extern void l_lhs PARAMS((struct iqueue_entry *));
+extern void l_lhz PARAMS((struct iqueue_entry *));
+extern void l_movhi PARAMS((struct iqueue_entry *));
+extern void l_and PARAMS((struct iqueue_entry *));
+extern void l_or PARAMS((struct iqueue_entry *));
+extern void l_xor PARAMS((struct iqueue_entry *));
+extern void l_sub PARAMS((struct iqueue_entry *));
+extern void l_mul PARAMS((struct iqueue_entry *));
+extern void l_div PARAMS((struct iqueue_entry *));
+extern void l_divu PARAMS((struct iqueue_entry *));
+extern void l_sll PARAMS((struct iqueue_entry *));
+extern void l_sra PARAMS((struct iqueue_entry *));
+extern void l_srl PARAMS((struct iqueue_entry *));
+extern void l_j PARAMS((struct iqueue_entry *));
+extern void l_jal PARAMS((struct iqueue_entry *));
+extern void l_jalr PARAMS((struct iqueue_entry *));
+extern void l_jr PARAMS((struct iqueue_entry *));
+extern void l_rfe PARAMS((struct iqueue_entry *));
+extern void l_nop PARAMS((struct iqueue_entry *));
+extern void l_bnf PARAMS((struct iqueue_entry *));
+extern void l_sfeq PARAMS((struct iqueue_entry *));
+extern void l_sfgts PARAMS((struct iqueue_entry *));
+extern void l_sfges PARAMS((struct iqueue_entry *));
+extern void l_sflts PARAMS((struct iqueue_entry *));
+extern void l_sfles PARAMS((struct iqueue_entry *));
+extern void l_sfgtu PARAMS((struct iqueue_entry *));
+extern void l_sfgeu PARAMS()(struct iqueue_entry *);
+extern void l_sfltu PARAMS((struct iqueue_entry *));
+extern void l_sfleu PARAMS((struct iqueue_entry *));
+extern void l_extbs PARAMS((struct iqueue_entry *));
+extern void l_extbz PARAMS((struct iqueue_entry *));
+extern void l_exths PARAMS((struct iqueue_entry *));
+extern void l_exthz PARAMS((struct iqueue_entry *));
+extern void l_extws PARAMS((struct iqueue_entry *));
+extern void l_extwz PARAMS((struct iqueue_entry *));
+extern void l_mtspr PARAMS((struct iqueue_entry *));
+extern void l_mfspr PARAMS((struct iqueue_entry *));
+extern void l_sys PARAMS((struct iqueue_entry *));
+extern void l_trap PARAMS((struct iqueue_entry *)); /* CZ 21/06/01 */
+extern void l_macrc PARAMS((struct iqueue_entry *));
+extern void l_mac PARAMS((struct iqueue_entry *));
+extern void l_msb PARAMS((struct iqueue_entry *));
+extern void l_invalid PARAMS((struct iqueue_entry *));
+extern void l_cmov PARAMS ((struct iqueue_entry *));
+extern void l_ff1 PARAMS ((struct iqueue_entry *));
+extern void l_cust1 PARAMS ((struct iqueue_entry *));
+extern void l_cust2 PARAMS ((struct iqueue_entry *));
+extern void l_cust3 PARAMS ((struct iqueue_entry *));
+extern void l_cust4 PARAMS ((struct iqueue_entry *));
+extern void lf_add_s PARAMS ((struct iqueue_entry *));
+extern void lf_div_s PARAMS ((struct iqueue_entry *));
+extern void lf_ftoi_s PARAMS ((struct iqueue_entry *));
+extern void lf_itof_s PARAMS ((struct iqueue_entry *));
+extern void lf_madd_s PARAMS ((struct iqueue_entry *));
+extern void lf_mul_s PARAMS ((struct iqueue_entry *));
+extern void lf_rem_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfeq_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfge_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfgt_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfle_s PARAMS ((struct iqueue_entry *));
+extern void lf_sflt_s PARAMS ((struct iqueue_entry *));
+extern void lf_sfne_s PARAMS ((struct iqueue_entry *));
+extern void lf_sub_s PARAMS((struct iqueue_entry *));
+extern void l_none PARAMS((struct iqueue_entry *));
+
+#endif /* SIMPLE32_DEFS__H */
simpl32-defs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: def-op-t.h
===================================================================
--- def-op-t.h (nonexistent)
+++ def-op-t.h (revision 135)
@@ -0,0 +1,138 @@
+/* def_op_t.h -- Operation-generation strucutre definitions helpers
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define GPR_T(op_name, temp) \
+ { NULL, \
+ glue(glue(op_name, 1), temp), \
+ glue(glue(op_name, 2), temp), \
+ glue(glue(op_name, 3), temp), \
+ glue(glue(op_name, 4), temp), \
+ glue(glue(op_name, 5), temp), \
+ glue(glue(op_name, 6), temp), \
+ glue(glue(op_name, 7), temp), \
+ glue(glue(op_name, 8), temp), \
+ glue(glue(op_name, 9), temp), \
+ glue(glue(op_name, 10), temp), \
+ glue(glue(op_name, 11), temp), \
+ glue(glue(op_name, 12), temp), \
+ glue(glue(op_name, 13), temp), \
+ glue(glue(op_name, 14), temp), \
+ glue(glue(op_name, 15), temp), \
+ glue(glue(op_name, 16), temp), \
+ glue(glue(op_name, 17), temp), \
+ glue(glue(op_name, 18), temp), \
+ glue(glue(op_name, 19), temp), \
+ glue(glue(op_name, 20), temp), \
+ glue(glue(op_name, 21), temp), \
+ glue(glue(op_name, 22), temp), \
+ glue(glue(op_name, 23), temp), \
+ glue(glue(op_name, 24), temp), \
+ glue(glue(op_name, 25), temp), \
+ glue(glue(op_name, 26), temp), \
+ glue(glue(op_name, 27), temp), \
+ glue(glue(op_name, 28), temp), \
+ glue(glue(op_name, 29), temp), \
+ glue(glue(op_name, 30), temp), \
+ glue(glue(op_name, 31), temp) }
+
+#if NUM_T_REGS == 3
+
+#define OP_ROW(op_name) \
+ { glue(op_name, _t0), glue(op_name, _t1), glue(op_name, _t2) }
+
+#define OP_ROW_NEQ0(op_name) \
+ { NULL, glue(op_name, _t1), glue(op_name, _t2) }
+
+#define OP_ROW_NEQ1(op_name) \
+ { glue(op_name, _t0), NULL, glue(op_name, _t2) }
+
+#define OP_ROW_NEQ2(op_name) \
+ { glue(op_name, _t0), glue(op_name, _t1), NULL }
+
+#define OP_ROW_COL(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)), }
+
+/* In 3D space: row, column, ??? */
+#define OP_ROW_COL_3D(op_name) { \
+ OP_ROW_COL(glue(op_name, _t0)), \
+ OP_ROW_COL(glue(op_name, _t1)), \
+ OP_ROW_COL(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ(op_name) { \
+ OP_ROW_NEQ0(glue(op_name, _t0)), \
+ OP_ROW_NEQ1(glue(op_name, _t1)), \
+ OP_ROW_NEQ2(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ0(op_name) { \
+ OP_ROW_NEQ0(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ1(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW_NEQ1(glue(op_name, _t1)), \
+ OP_ROW(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_NEQ2(op_name) { \
+ OP_ROW(glue(op_name, _t0)), \
+ OP_ROW(glue(op_name, _t1)), \
+ OP_ROW_NEQ2(glue(op_name, _t2)) }
+
+#define OP_ROW_COL_3D_NEQ(op_name) { \
+ OP_ROW_COL_NEQ0(glue(op_name, _t0)), \
+ OP_ROW_COL_NEQ1(glue(op_name, _t1)), \
+ OP_ROW_COL_NEQ2(glue(op_name, _t2)) }
+
+#define GPR_ROW_COL(op_name) { \
+ GPR_T(op_name, _t0), \
+ GPR_T(op_name, _t1), \
+ GPR_T(op_name, _t2) }
+
+#else
+#error Update def_op_t.h for NUM_T_REGS temporaries
+#endif
+
+#define DEF_1T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS] = \
+ OP_ROW(op_name)
+
+#define DEF_2T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL(op_name)
+
+#define DEF_3T_OP(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_3D(op_name)
+
+/* Same as above but put NULL in places where T0 == T1 */
+#define DEF_2T_OP_NEQ(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_NEQ(op_name)
+
+/* Same as above but put NULL in places where T0 == T1 == T2 */
+#define DEF_3T_OP_NEQ(type, name, op_name) \
+ static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \
+ OP_ROW_COL_3D_NEQ(op_name)
+
+#define DEF_GPR_OP(type, name, op_name) \
+ static const generic_gen_op name[NUM_T_REGS][32] = \
+ GPR_ROW_COL(op_name)
+
def-op-t.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-1t-op.h
===================================================================
--- op-1t-op.h (nonexistent)
+++ op-1t-op.h (revision 135)
@@ -0,0 +1,75 @@
+/* op-1t-op.h -- Micro operations useing only one temporary
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+__or_dynop void glue(op_imm, T)(void)
+{
+ T0 = OP_PARAM1;
+}
+
+__or_dynop void glue(op_clear, T)(void)
+{
+ T0 = 0;
+}
+
+__or_dynop void glue(op_check_null_except_delay, T)(void)
+{
+ if(!T0) {
+ /* Do exception */
+ env->sprs[SPR_EEAR_BASE] = env->pc - 4;
+ env->delay_insn = 0;
+ do_jump(EXCEPT_ILLEGAL);
+ }
+}
+
+__or_dynop void glue(op_check_null_except, T)(void)
+{
+ if(!T0) {
+ /* Do exception */
+ env->sprs[SPR_EEAR_BASE] = env->pc;
+ do_jump(EXCEPT_ILLEGAL);
+ }
+}
+
+__or_dynop void glue(op_calc_insn_ea, T)(void)
+{
+ env->insn_ea = T0 + OP_PARAM1;
+}
+
+__or_dynop void glue(op_macrc, T)(void)
+{
+ /* FIXME: How is this supposed to work? The architechture manual says that
+ * the low 32-bits shall be saved into rD. I have just copied this code from
+ * insnset.c to make testbench/mul pass */
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ T0 = (orreg_t)(temp >> 28);
+ env->sprs[SPR_MACLO] = 0;
+ env->sprs[SPR_MACHI] = 0;
+}
+
+__or_dynop void glue(op_mac_imm, T)(void)
+{
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ temp += (int64_t)T0 * (int64_t)OP_PARAM1;
+
+ env->sprs[SPR_MACLO] = temp & 0xffffffff;
+ env->sprs[SPR_MACHI] = temp >> 32;
+}
+
op-1t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-2t-op.h
===================================================================
--- op-2t-op.h (nonexistent)
+++ op-2t-op.h (revision 135)
@@ -0,0 +1,44 @@
+/* op-1t-op.h -- Micro operations useing two temporaries
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+__or_dynop void glue(op_move, T)(void)
+{
+ T0 = T1;
+}
+
+__or_dynop void glue(op_ff1, T)(void)
+{
+ int i;
+
+ for(i = 0; i < 32; i++, T0 >>= 1) {
+ if(T0 & 1) {
+ T1 = i;
+ break;
+ }
+ }
+
+ FORCE_RET;
+}
+
+
+__or_dynop void glue(op_neg, T)(void)
+{
+ T0 = -T1;
+}
+
op-2t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-3t-op.h
===================================================================
--- op-3t-op.h (nonexistent)
+++ op-3t-op.h (revision 135)
@@ -0,0 +1,25 @@
+/* op-3t-op.h -- Micro operations useing three temporaries
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(op_cmov, T)(void)
+{
+ T0 = env->sprs[SPR_SR] & SPR_SR_F ? T1 : T2;
+}
+
op-3t-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen.c
===================================================================
--- dyngen.c (nonexistent)
+++ dyngen.c (revision 135)
@@ -0,0 +1,289 @@
+/* dyngen.c -- Generates micro operation generating functions
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+
+#include "dyngen.h"
+
+#define OP_FUNC_PREFIX "op_"
+#define OP_FUNC_PARAM_PREFIX "__op_param"
+/* Have to add to to make sure that the param[] is 0 */
+#define MAX_PARAMS (3 + 1)
+
+static const char *c_file_head =
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"abstract.h\"\n"
+"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"%s\"\n"
+"\n";
+
+static const char *gen_code_proto =
+"void gen_code(struct op_queue *opq, struct dyn_page *dp);\n"
+"void patch_relocs(struct op_queue *opq, void *host_page);\n"
+"\n";
+
+static const char *c_sw_file_head =
+"#include \n"
+"#include \n"
+"\n"
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"abstract.h\"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"%s\"\n"
+"\n"
+"void gen_code(struct op_queue *opq, struct dyn_page *dp)\n"
+"{\n"
+" unsigned int *ops, i;\n"
+" unsigned int host_len = dp->host_len;\n"
+" void *host_cur = dp->host_page;\n"
+" oraddr_t pc = dp->or_page;\n"
+" void **loc = dp->locs;\n"
+"\n"
+" while(opq) {\n"
+" if(opq->next)\n"
+" *loc++ = (void *)(host_cur - dp->host_page);"
+"\n"
+" for(i = 0, ops = opq->ops; i < opq->num_ops; i++, ops++) {\n"
+" switch(*ops) {\n"
+" case op_mark_loc_indx:\n"
+" opq->ops_param[0] = host_cur - dp->host_page;\n"
+" break;\n";
+
+static const char *c_sw_file_tail =
+" }\n"
+" }\n"
+" opq = opq->next;\n"
+" pc += 4;\n"
+" }\n"
+"\n"
+" dp->host_len = host_cur - dp->host_page;\n"
+" dp->host_page = realloc(dp->host_page, dp->host_len);\n"
+"}\n";
+
+static const char *c_rel_file_head =
+"#include /* To get printf... */\n"
+"#include \n"
+"\n"
+"#include \"config.h\"\n"
+"\n"
+"#include \n"
+"\n"
+"#include \"arch.h\"\n"
+"#include \"spr-defs.h\"\n"
+"#include \"i386-regs.h\"\n"
+"#include \"opcode/or32.h\"\n"
+"#include \"abstract.h\"\n"
+"#include \"tick.h\"\n"
+"#include \"execute.h\"\n"
+"#include \"sprs.h\"\n"
+"#include \"dyn-rec.h\"\n"
+"#include \"op-support.h\"\n"
+"#include \"%s\"\n"
+"\n"
+"void do_scheduler(void); /* FIXME: Remove */\n"
+"void do_sched_wrap(void); /* FIXME: Remove */\n"
+"void do_sched_wrap_delay(void); /* FIXME: Remove */\n"
+"void simprintf(oraddr_t stackaddr, unsigned long regparam); /* FIXME: Remove */\n"
+"\n"
+"void patch_relocs(struct op_queue *opq, void *host_page)\n"
+"{\n"
+" unsigned int *ops, *ops_param, i;\n"
+"\n"
+" while(opq) {\n"
+" for(i = 0, ops = opq->ops, ops_param = opq->ops_param; i < opq->num_ops; i++, ops++) {\n"
+" switch(*ops) {\n";
+
+static const char *c_rel_file_tail =
+" }\n"
+" }\n"
+" opq = opq->next;\n"
+" }\n"
+"}\n";
+
+static void gen_func_proto(FILE *f, const char *name, int *params)
+{
+ int i;
+
+ fprintf(f, "void gen_%s(struct op_queue *opq, int end", name);
+ for(i = 0; (i < MAX_PARAMS) && params[i]; i++) {
+ fprintf(f, ", uorreg_t param%i", i + 1);
+ }
+ fprintf(f, ")");
+}
+
+int main(int argc, char **argv)
+{
+ void *obj;
+ int i, j;
+ unsigned int len;
+ char *name;
+ int params[MAX_PARAMS];
+ struct reloc reloc;
+
+ FILE *c_file;
+ FILE *h_file;
+ FILE *c_sw_file;
+ FILE *c_rel_file;
+
+ if(argc != 6) {
+ fprintf(stderr, "Usage: %s
dyngen.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: common-i386.h
===================================================================
--- common-i386.h (nonexistent)
+++ common-i386.h (revision 135)
@@ -0,0 +1,63 @@
+/* common-i386.h -- Assembler routines used in rec_i386.h and op_i386.h
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This is needed because we can't move an mmx register to a general purpose
+ * register. */
+static union {
+ struct {
+ uint32_t low32;
+ uint32_t high32;
+ } val3232;
+ uint64_t val64;
+} useless_x86;
+
+/* Sets the PC with a specified value */
+static void set_pc(oraddr_t pc)
+{
+ /* I could just use pc as a memory argument, but if I do that then gcc may put
+ * the value of pc onto the stack, in which case gcc would also shift the
+ * stack twice, which would result in two add 4, %esp instructions and a
+ * mov %eax, *%esp, which would not only be slow but it would take up more
+ * space. */
+ asm("movq %%mm0, %0\n"
+ "\tmovl %2, %1\n"
+ "\tmovq %3, %%mm0"
+ : "=m" (useless_x86.val64),
+ "=m" (useless_x86.val3232.high32)
+ : "r" (pc),
+ "m" (useless_x86.val64));
+}
+
+/* Returns the current value of the pc */
+static oraddr_t get_pc(void)
+{
+ asm("movq %%mm0, %0" : "=m" (useless_x86.val64));
+ return useless_x86.val3232.high32;
+}
+
+/* Updates the runtime.sim.cycles counter */
+static void upd_sim_cycles(void)
+{
+ asm volatile ("movq %%mm0, %0\n" : "=m" (useless_x86.val64));
+ runtime.sim.cycles += scheduler.job_queue->time - useless_x86.val3232.low32;
+ scheduler.job_queue->time = useless_x86.val3232.low32;
+ cpu_state.pc = useless_x86.val3232.high32;
+}
+
common-i386.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-extend-op.h
===================================================================
--- op-extend-op.h (nonexistent)
+++ op-extend-op.h (revision 135)
@@ -0,0 +1,27 @@
+/* op-extend-op.h -- Micro operations template for sign extention operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+void glue(glue(op_, EXT_NAME), T)(void)
+{
+ register EXT_TYPE x;
+ x = T1;
+ T0 = EXT_CAST x;
+}
+
op-extend-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 135)
@@ -0,0 +1,196 @@
+# Makefile -- Makefile for OR32 dependent simulation
+#
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+# Copyright (C) 2008 Embecosm Limited
+#
+# Contributor Jeremy Bennett
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+
+
+if DYNAMIC_EXECUTION
+
+noinst_LTLIBRARIES = libarch.la
+
+noinst_PROGRAMS = dyngen
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ op.c \
+ dyn-rec.c \
+ op-support.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+nodist_libarch_la_SOURCES = gen-ops.h \
+ gen-ops.c \
+ gen-ops-gen.c \
+ gen-ops-rel.c
+
+BUILT_SOURCES = gen-ops.h \
+ gen-ops.c \
+ gen-ops-gen.c \
+ gen-ops-rel.c
+
+dyngen_SOURCES = dyngen.c \
+ dyngen-i386.c \
+ dyngen-elf.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+dyngen_CFLAGS = $(AM_CFLAGS)
+
+gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o
+ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h
+
+OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2
+
+op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \
+ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \
+ op-swhb-op.h
+ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $<
+else
+
+noinst_LTLIBRARIES = libarch.la
+
+if GENERATE_NEEDED
+
+EXTRA_DIST = insnset.c
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+BUILT_SOURCES = execgen.c
+
+noinst_PROGRAMS = generate$(EXEEXT)
+
+generate_SOURCES = or32.c \
+ generate.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+generate_CFLAGS = $(AM_CFLAGS)
+
+execgen.c: generate$(EXEEXT) insnset.c
+ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c
+
+else
+
+libarch_la_SOURCES = execute.c \
+ or32.c \
+ common-i386.h \
+ dyn32-defs.h \
+ dyngen.h \
+ dyn-rec.h \
+ i386-regs.h \
+ op-arith-op.h \
+ op-comp-op.h \
+ op-extend-op.h \
+ op-ff1-op.h \
+ op-i386.h \
+ op-lwhb-op.h \
+ op-mac-op.h \
+ op-mftspr-op.h \
+ op-support.h \
+ op-swhb-op.h \
+ op-t-reg-mov-op.h \
+ rec-i386.h \
+ sched-i386.h \
+ simpl32-defs.h
+
+dist_EXTRA_libarch_la_SOURCES = insnset.c
+
+endif
+endif
+
+# If the simulator was first built without --enable-simple and then with it,
+# then also remove these two files
+
+CLEANFILES = execgen.c \
+ generate \
+ gen-ops.c \
+ gen-ops.h \
+ gen-ops-rel.c \
+ gen-ops-gen.c
Makefile.am
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen-elf.c
===================================================================
--- dyngen-elf.c (nonexistent)
+++ dyngen-elf.c (revision 135)
@@ -0,0 +1,359 @@
+/* dyngen-elf.c -- Elf parser for dyngen
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "dyngen.h"
+
+struct elf_obj {
+ Elf32_Ehdr e_hdr;
+ Elf32_Shdr *e_shdrs;
+ void **e_sections;
+ Elf32_Sym *e_syms; /* The symbol table in the elf file */
+ unsigned int e_sym_num; /* The number of symbols */
+ unsigned int e_sym_str_tab; /* The string-table associated with symbols */
+ Elf32_Rel *e_rels;
+ unsigned int e_rel_num; /* The number of relocations (in e_rel) */
+ unsigned int e_rel_sym;
+ unsigned int e_rel_sec; /* The section to modify */
+ Elf32_Rela *e_relas;
+ unsigned int e_rela_num; /* The number of relocations (in e_rela) */
+ unsigned int e_rela_sym;
+ unsigned int e_rela_sec; /* The section to modify */
+};
+
+void *elf_open_obj(const char *file)
+{
+ struct elf_obj *obj;
+ FILE *f;
+ int i;
+
+ if(!(obj = malloc(sizeof(struct elf_obj)))) {
+ fprintf(stderr, "OOM\n");
+ return NULL;
+ }
+
+ if(!(f = fopen(file, "r"))) {
+ free(obj);
+ return NULL;
+ }
+
+ fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f);
+
+ /* Do some sanity checks */
+ if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) ||
+ (obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) ||
+ (obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) ||
+ (obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) {
+ fprintf(stderr, "%s is not an elf file!\n", file);
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) {
+ fprintf(stderr, "Invalid class in ELF header\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) {
+ fprintf(stderr, "Invalid data format in ELF header\n");
+ goto error_load;
+ }
+
+ /* FIXME: Swap data as necessary */
+
+ if((obj->e_hdr.e_ident[EI_VERSION] != 1) ||
+ (obj->e_hdr.e_version != 1)) {
+ fprintf(stderr, "Unexpected elf version found: %i (%li)\n",
+ obj->e_hdr.e_ident[EI_VERSION], (long int)obj->e_hdr.e_version);
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_type != ET_REL) {
+ fprintf(stderr, "Appears that we did not receive a object file\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_phoff) {
+ fprintf(stderr, "What am I supposed to do with a program header??\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+ fprintf(stderr, "Unknown size of elf header\n");
+ goto error_load;
+ }
+
+ if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) {
+ fprintf(stderr, "The elf file contains no sections!\n");
+ goto error_load;
+ }
+
+ if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) {
+ fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize);
+ goto error_load;
+ }
+
+ /* Load the section headers */
+ if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){
+ fprintf(stderr, "OOM\n");
+ goto error_load;
+ }
+
+ fseek(f, obj->e_hdr.e_shoff, SEEK_SET);
+ fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f);
+
+ /* FIXME: swap data */
+
+ /* Load the sections */
+ if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) {
+ fprintf(stderr, "OOM\n");
+ free(obj->e_shdrs);
+ goto error_load;
+ }
+
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_shdrs[i].sh_type == SHT_NOBITS)
+ continue;
+ if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) {
+ fprintf(stderr, "OOM\n");
+ goto post_sec_error_load;
+ }
+ fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET);
+ fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f);
+ }
+
+ obj->e_rels = NULL;
+ obj->e_syms = NULL;
+ obj->e_relas = NULL;
+
+ /* Find the symbol table and relocation table(s) */
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ switch(obj->e_shdrs[i].sh_type) {
+ case SHT_SYMTAB:
+ if(obj->e_syms) {
+ fprintf(stderr, "ELF file has more than one symbol table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) {
+ fprintf(stderr, "ELF symbol table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n");
+ goto post_sec_error_load;
+ }
+ obj->e_syms = obj->e_sections[i];
+ obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ obj->e_sym_str_tab = obj->e_shdrs[i].sh_link;
+ break;
+ case SHT_REL:
+ if(obj->e_rels) {
+ fprintf(stderr, "ELF file has more than one relocation table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) {
+ fprintf(stderr, "ELF relocation table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n");
+ goto post_sec_error_load;
+ }
+ obj->e_rels = obj->e_sections[i];
+ obj->e_rel_sec = obj->e_shdrs[i].sh_info;
+ obj->e_rel_sym = obj->e_shdrs[i].sh_link;
+ obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ break;
+ case SHT_RELA:
+ if(obj->e_relas) {
+ fprintf(stderr, "ELF file has more than one a-relocation table\n");
+ goto post_sec_error_load;
+ }
+ if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) {
+ fprintf(stderr, "ELF a-relocation table entry size is unknown\n");
+ goto post_sec_error_load;
+ }
+ if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
+ fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n");
+ goto post_sec_error_load;
+ }
+ obj->e_relas = obj->e_sections[i];
+ obj->e_rela_sec = obj->e_shdrs[i].sh_info;
+ obj->e_rela_sym = obj->e_shdrs[i].sh_link;
+ obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
+ break;
+ }
+ }
+
+ fclose(f);
+ return obj;
+
+post_sec_error_load:
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_sections[i])
+ free(obj->e_sections[i]);
+ }
+ free(obj->e_sections);
+ free(obj->e_shdrs);
+error_load:
+ free(obj);
+ fclose(f);
+ return NULL;
+}
+
+void elf_close_obj(void *e_obj)
+{
+ struct elf_obj *obj = e_obj;
+ int i;
+
+ for(i = 0; i < obj->e_hdr.e_shnum; i++) {
+ if(obj->e_sections[i])
+ free(obj->e_sections[i]);
+ }
+ free(obj->e_sections);
+ free(obj->e_shdrs);
+ free(obj);
+}
+
+static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func)
+{
+ int i, j;
+ Elf32_Sym *cur;
+
+ for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) {
+ if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL)
+ continue;
+ if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC)
+ continue;
+ if(j == func)
+ return cur;
+ j++;
+ }
+ return NULL;
+}
+
+char *elf_get_func_name(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(func_sym)
+ return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name;
+
+ return NULL;
+}
+
+unsigned int elf_get_func_len(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(func_sym)
+ return func_sym->st_size;
+ return 0;
+}
+
+void *elf_get_func_start(void *e_obj, unsigned int func)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+
+ if(!func_sym)
+ return NULL;
+
+ if(func_sym->st_shndx == SHN_COMMON) {
+ fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n");
+ return NULL;
+ }
+
+ return obj->e_sections[func_sym->st_shndx] + func_sym->st_value;
+}
+
+static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym)
+{
+ char *name;
+
+ name = obj->e_sections[obj->e_sym_str_tab];
+ name += obj->e_syms[sym].st_name;
+
+ return name;
+}
+
+int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn,
+ struct reloc *reloc)
+{
+ struct elf_obj *obj = e_obj;
+ Elf32_Sym *func_sym = elf_find_func(obj, func);
+ Elf32_Rel *cur;
+ Elf32_Rela *cura;
+ int i, j;
+
+/*
+ if(obj->e_rel_sec != func_sym->st_shndx) {
+ fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n");
+ return 0;
+ }
+*/
+
+ for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) {
+ if((cur->r_offset - func_sym->st_value) > func_sym->st_size)
+ continue;
+ if(relocn == j) {
+ reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
+ reloc->func_offset = cur->r_offset - func_sym->st_value;
+ reloc->type = ELF32_R_TYPE(cur->r_info);
+ /* FIXME: Byte-swap */
+ reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset);
+ return 1;
+ }
+ j++;
+ }
+
+ if(!obj->e_relas)
+ return 0;
+
+ for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) {
+ if((cura->r_offset - func_sym->st_value) > func_sym->st_size)
+ continue;
+ if(relocn == j) {
+ reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
+ reloc->func_offset = cura->r_offset - func_sym->st_value;
+ reloc->type = ELF32_R_TYPE(cur->r_info);
+ reloc->addend = cura->r_addend;
+ return 1;
+ }
+ j++;
+ }
+
+ return 0;
+}
+
+const struct bff bffs = {
+ elf_open_obj,
+ elf_close_obj,
+ elf_get_func_name,
+ elf_get_func_start,
+ elf_get_func_len,
+ elf_get_func_reloc };
dyngen-elf.c
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: dyngen.h
===================================================================
--- dyngen.h (nonexistent)
+++ dyngen.h (revision 135)
@@ -0,0 +1,45 @@
+/* dyngen.h -- Definitions for dyngen.c
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+struct reloc {
+ unsigned int func_offset;
+ unsigned int addend;
+ int type;
+ const char *name;
+};
+
+struct bff {
+ void *(*open_obj)(const char *object); /* Open the object file */
+ void (*close_obj)(void *);
+ char *(*get_func_name)(void *, unsigned int func); /* Gets the name of func */
+ void *(*get_func_start)(void *, unsigned int func);
+ unsigned int (*get_func_len)(void *, unsigned int func);
+ int (*get_func_reloc)(void *, unsigned int func, unsigned int relocn, struct reloc *reloc);
+};
+
+extern const struct bff bffs;
+
+struct archf {
+ unsigned int (*get_real_func_len)(void *func, unsigned int len, char *name);
+ void (*gen_reloc)(FILE *f, struct reloc *reloc, unsigned int param);
+ void (*gen_func_reloc)(FILE *f, struct reloc *reloc);
+};
+
+extern const struct archf archfs;
dyngen.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: i386-regs.h
===================================================================
--- i386-regs.h (nonexistent)
+++ i386-regs.h (revision 135)
@@ -0,0 +1,26 @@
+/* i386_regs.h -- Register definitions for i386
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define CPU_STATE_REG "ebp"
+#define T0_REG "ebx"
+#define T1_REG "esi"
+#define T2_REG "edi"
+
+#define NUM_T_REGS 3
i386-regs.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: op-mac-op.h
===================================================================
--- op-mac-op.h (nonexistent)
+++ op-mac-op.h (revision 135)
@@ -0,0 +1,30 @@
+/* op-mac-op.h -- Micro operations template for mac operations
+ Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+__or_dynop void glue(glue(op_, OP_NAME), T)(void)
+{
+ int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
+
+ temp OP (int64_t)T0 * (int64_t)T1;
+
+ env->sprs[SPR_MACLO] = temp & 0xffffffff;
+ env->sprs[SPR_MACHI] = temp >> 32;
+}
+
op-mac-op.h
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property