X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=sim%2Fv850%2Fsimops.c;h=40d578e5d0ac87e17c5716c05cae787167668af9;hb=4f83758119ddf0f114477760d79bdde7bbc76835;hp=31fa244f779d30f9e6727a10cfc84be44075bcf0;hpb=968519095a3386323bb7ef7f88583e6ed902e691;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/v850/simops.c b/sim/v850/simops.c index 31fa244f77..40d578e5d0 100644 --- a/sim/v850/simops.c +++ b/sim/v850/simops.c @@ -1,938 +1,596 @@ -#include +#include "sim-main.h" #include "v850_sim.h" #include "simops.h" -#include "sys/syscall.h" -#include "bfd.h" -#include -enum op_types { - OP_UNKNOWN, - OP_NONE, - OP_TRAP, - OP_REG, - OP_REG_REG, - OP_REG_REG_CMP, - OP_REG_REG_MOVE, - OP_IMM_REG, - OP_IMM_REG_CMP, - OP_IMM_REG_MOVE, - OP_COND_BR, - OP_LOAD16, - OP_STORE16, - OP_LOAD32, - OP_STORE32, - OP_JUMP, - OP_IMM_REG_REG, - OP_UIMM_REG_REG, - OP_BIT, - OP_EX1, - OP_EX2, - OP_LDSR, - OP_STSR -}; +#include -#ifdef DEBUG -static void trace_input PARAMS ((char *name, enum op_types type, int size)); -static void trace_output PARAMS ((enum op_types result)); -static int init_text_p = 0; -static asection *text; -static bfd_vma text_start; -static bfd_vma text_end; -extern bfd *exec_bfd; +#ifdef HAVE_UTIME_H +#include +#endif -#ifndef SIZE_INSTRUCTION -#define SIZE_INSTRUCTION 6 +#ifdef HAVE_TIME_H +#include #endif -#ifndef SIZE_OPERANDS -#define SIZE_OPERANDS 16 +#ifdef HAVE_UNISTD_H +#include #endif -#ifndef SIZE_VALUES -#define SIZE_VALUES 11 +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif #endif -#ifndef SIZE_LOCATION -#define SIZE_LOCATION 40 +#include "targ-vals.h" + +#include "libiberty.h" + +#include +#if !defined(__GO32__) && !defined(_WIN32) +#include +#include +#include #endif -static void -trace_input (name, type, size) - char *name; - enum op_types type; - int size; -{ - char buf[1024]; - char *p; - uint32 values[3]; - int num_values, i; - char *cond; - asection *s; - const char *filename; - const char *functionname; - unsigned int linenumber; - - if ((v850_debug & DEBUG_TRACE) == 0) - return; +/* This is an array of the bit positions of registers r20 .. r31 in + that order in a prepare/dispose instruction. */ +int type1_regs[12] = { 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 0, 21 }; +/* This is an array of the bit positions of registers r16 .. r31 in + that order in a push/pop instruction. */ +int type2_regs[16] = { 3, 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21}; +/* This is an array of the bit positions of registers r1 .. r15 in + that order in a push/pop instruction. */ +int type3_regs[15] = { 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21}; - buf[0] = '\0'; - if (!init_text_p) - { - init_text_p = 1; - for (s = exec_bfd->sections; s; s = s->next) - if (strcmp (bfd_get_section_name (exec_bfd, s), ".text") == 0) - { - text = s; - text_start = bfd_get_section_vma (exec_bfd, s); - text_end = text_start + bfd_section_size (exec_bfd, s); - break; - } - } +#ifdef DEBUG +#ifndef SIZE_INSTRUCTION +#define SIZE_INSTRUCTION 18 +#endif - if (text && PC >= text_start && PC < text_end) - { - filename = (const char *)0; - functionname = (const char *)0; - linenumber = 0; - if (bfd_find_nearest_line (exec_bfd, text, (struct symbol_cache_entry **)0, PC - text_start, - &filename, &functionname, &linenumber)) - { - p = buf; - if (linenumber) - { - sprintf (p, "Line %5d ", linenumber); - p += strlen (p); - } +#ifndef SIZE_VALUES +#define SIZE_VALUES 11 +#endif - if (functionname) - { - sprintf (p, "Func %s ", functionname); - p += strlen (p); - } - else if (filename) - { - char *q = (char *) strrchr (filename, '/'); - sprintf (p, "File %s ", (q) ? q+1 : filename); - p += strlen (p); - } - if (*p == ' ') - *p = '\0'; - } - } +unsigned32 trace_values[3]; +int trace_num_values; +unsigned32 trace_pc; +const char * trace_name; +int trace_module; + + +void +trace_input (char *name, enum op_types type, int size) +{ + if (!TRACE_ALU_P (STATE_CPU (simulator, 0))) + return; - (*v850_callback->printf_filtered) (v850_callback, "0x%.8x: %-*.*s %-*s", - (unsigned)PC, - SIZE_LOCATION, SIZE_LOCATION, buf, - SIZE_INSTRUCTION, name); + trace_pc = PC; + trace_name = name; + trace_module = TRACE_ALU_IDX; switch (type) { default: case OP_UNKNOWN: case OP_NONE: - strcpy (buf, "unknown"); - break; - case OP_TRAP: - sprintf (buf, "%d", OP[0]); + trace_num_values = 0; break; - + case OP_REG: - sprintf (buf, "r%d", OP[0]); + case OP_REG_REG_MOVE: + trace_values[0] = State.regs[OP[0]]; + trace_num_values = 1; break; - + + case OP_BIT_CHANGE: case OP_REG_REG: case OP_REG_REG_CMP: - case OP_REG_REG_MOVE: - sprintf (buf, "r%d,r%d", OP[0], OP[1]); + trace_values[0] = State.regs[OP[1]]; + trace_values[1] = State.regs[OP[0]]; + trace_num_values = 2; break; - + case OP_IMM_REG: case OP_IMM_REG_CMP: + trace_values[0] = SEXT5 (OP[0]); + trace_values[1] = OP[1]; + trace_num_values = 2; + break; + case OP_IMM_REG_MOVE: - sprintf (buf, "%d,r%d", OP[0], OP[1]); + trace_values[0] = SEXT5 (OP[0]); + trace_num_values = 1; break; - + case OP_COND_BR: - sprintf (buf, "%d", SEXT9 (OP[0])); + trace_values[0] = State.pc; + trace_values[1] = SEXT9 (OP[0]); + trace_values[2] = PSW; + trace_num_values = 3; break; - + case OP_LOAD16: - sprintf (buf, "%d[r30],r%d", SEXT7 (OP[1]) * size, OP[0]); + trace_values[0] = OP[1] * size; + trace_values[1] = State.regs[30]; + trace_num_values = 2; break; - + case OP_STORE16: - sprintf (buf, "r%d,%d[r30]", OP[0], SEXT7 (OP[1]) * size); + trace_values[0] = State.regs[OP[0]]; + trace_values[1] = OP[1] * size; + trace_values[2] = State.regs[30]; + trace_num_values = 3; break; - + case OP_LOAD32: - sprintf (buf, "%d[r%d],r%d", SEXT16 (OP[2]) & ~0x1, OP[0], OP[1]); + trace_values[0] = EXTEND16 (OP[2]); + trace_values[1] = State.regs[OP[0]]; + trace_num_values = 2; break; - + case OP_STORE32: - sprintf (buf, "r%d,%d[r%d]", OP[1], SEXT16 (OP[2] & ~0x1), OP[0]); + trace_values[0] = State.regs[OP[1]]; + trace_values[1] = EXTEND16 (OP[2]); + trace_values[2] = State.regs[OP[0]]; + trace_num_values = 3; break; - + case OP_JUMP: - sprintf (buf, "%d,r%d", SEXT22 (OP[0]), OP[1]); + trace_values[0] = SEXT22 (OP[0]); + trace_values[1] = State.pc; + trace_num_values = 2; break; - + case OP_IMM_REG_REG: - sprintf (buf, "%d,r%d,r%d", SEXT16 (OP[0]), OP[1], OP[2]); + trace_values[0] = EXTEND16 (OP[0]) << size; + trace_values[1] = State.regs[OP[1]]; + trace_num_values = 2; break; - + + case OP_IMM16_REG_REG: + trace_values[0] = EXTEND16 (OP[2]) << size; + trace_values[1] = State.regs[OP[1]]; + trace_num_values = 2; + break; + case OP_UIMM_REG_REG: - sprintf (buf, "%d,r%d,r%d", OP[0] & 0xffff, OP[1], OP[2]); + trace_values[0] = (OP[0] & 0xffff) << size; + trace_values[1] = State.regs[OP[1]]; + trace_num_values = 2; break; - + + case OP_UIMM16_REG_REG: + trace_values[0] = (OP[2]) << size; + trace_values[1] = State.regs[OP[1]]; + trace_num_values = 2; + break; + case OP_BIT: - sprintf (buf, "%d,%d[r%d]", OP[1] & 0x7, SEXT16 (OP[2]), OP[0]); + trace_num_values = 0; break; - + case OP_EX1: - switch (OP[0] & 0xf) - { - default: cond = "?"; break; - case 0x0: cond = "v"; break; - case 0x1: cond = "c"; break; - case 0x2: cond = "z"; break; - case 0x3: cond = "nh"; break; - case 0x4: cond = "s"; break; - case 0x5: cond = "t"; break; - case 0x6: cond = "lt"; break; - case 0x7: cond = "le"; break; - case 0x8: cond = "nv"; break; - case 0x9: cond = "nc"; break; - case 0xa: cond = "nz"; break; - case 0xb: cond = "h"; break; - case 0xc: cond = "ns"; break; - case 0xd: cond = "sa"; break; - case 0xe: cond = "ge"; break; - case 0xf: cond = "gt"; break; - } - - sprintf (buf, "%s,r%d", cond, OP[1]); + trace_values[0] = PSW; + trace_num_values = 1; break; - + case OP_EX2: - strcpy (buf, "EX2"); + trace_num_values = 0; break; - + case OP_LDSR: - case OP_STSR: - sprintf (buf, "r%d,s%d", OP[0], OP[1]); + trace_values[0] = State.regs[OP[0]]; + trace_num_values = 1; break; + + case OP_STSR: + trace_values[0] = State.sregs[OP[1]]; + trace_num_values = 1; } + +} - if ((v850_debug & DEBUG_VALUES) == 0) - { - (*v850_callback->printf_filtered) (v850_callback, "%s\n", buf); - } - else - { - (*v850_callback->printf_filtered) (v850_callback, "%-*s", SIZE_OPERANDS, buf); - switch (type) - { - default: - case OP_UNKNOWN: - case OP_NONE: - case OP_TRAP: - num_values = 0; - break; - - case OP_REG: - case OP_REG_REG_MOVE: - values[0] = State.regs[OP[0]]; - num_values = 1; - break; - - case OP_REG_REG: - case OP_REG_REG_CMP: - values[0] = State.regs[OP[1]]; - values[1] = State.regs[OP[0]]; - num_values = 2; - break; - - case OP_IMM_REG: - case OP_IMM_REG_CMP: - values[0] = SEXT5 (OP[0]); - values[1] = OP[1]; - num_values = 2; - break; - - case OP_IMM_REG_MOVE: - values[0] = SEXT5 (OP[0]); - num_values = 1; - break; - - case OP_COND_BR: - values[0] = State.pc; - values[1] = SEXT9 (OP[0]); - values[2] = State.sregs[5]; - num_values = 3; - break; - - case OP_LOAD16: - values[0] = SEXT7 (OP[1]) * size; - values[1] = State.regs[30]; - num_values = 2; - break; - - case OP_STORE16: - values[0] = State.regs[OP[0]]; - values[1] = SEXT7 (OP[1]) * size; - values[2] = State.regs[30]; - num_values = 3; - break; - - case OP_LOAD32: - values[0] = SEXT16 (OP[2]); - values[1] = State.regs[OP[0]]; - num_values = 2; - break; - - case OP_STORE32: - values[0] = State.regs[OP[1]]; - values[1] = SEXT16 (OP[2]); - values[2] = State.regs[OP[0]]; - num_values = 3; - break; - - case OP_JUMP: - values[0] = SEXT22 (OP[0]); - values[1] = State.pc; - num_values = 2; - break; - - case OP_IMM_REG_REG: - values[0] = SEXT16 (OP[0]) << size; - values[1] = State.regs[OP[1]]; - num_values = 2; - break; - - case OP_UIMM_REG_REG: - values[0] = (OP[0] & 0xffff) << size; - values[1] = State.regs[OP[1]]; - num_values = 2; - break; - - case OP_BIT: - num_values = 0; - break; - - case OP_EX1: - values[0] = State.sregs[5]; - num_values = 1; - break; - - case OP_EX2: - num_values = 0; - break; - - case OP_LDSR: - values[0] = State.regs[OP[0]]; - num_values = 1; - break; +void +trace_result (int has_result, unsigned32 result) +{ + char buf[1000]; + char *chp; - case OP_STSR: - values[0] = State.sregs[OP[1]]; - num_values = 1; - } + buf[0] = '\0'; + chp = buf; + + /* write out the values saved during the trace_input call */ + { + int i; + for (i = 0; i < trace_num_values; i++) + { + sprintf (chp, "%*s0x%.8lx", SIZE_VALUES - 10, "", + (long) trace_values[i]); + chp = strchr (chp, '\0'); + } + while (i++ < 3) + { + sprintf (chp, "%*s", SIZE_VALUES, ""); + chp = strchr (chp, '\0'); + } + } + + /* append any result to the end of the buffer */ + if (has_result) + sprintf (chp, " :: 0x%.8lx", (unsigned long) result); + + trace_generic (simulator, STATE_CPU (simulator, 0), trace_module, "%s", buf); +} - for (i = 0; i < num_values; i++) - (*v850_callback->printf_filtered) (v850_callback, "%*s0x%.8lx", SIZE_VALUES - 10, "", values[i]); +void +trace_output (enum op_types result) +{ + if (!TRACE_ALU_P (STATE_CPU (simulator, 0))) + return; - while (i++ < 3) - (*v850_callback->printf_filtered) (v850_callback, "%*s", SIZE_VALUES, ""); + switch (result) + { + default: + case OP_UNKNOWN: + case OP_NONE: + case OP_TRAP: + case OP_REG: + case OP_REG_REG_CMP: + case OP_IMM_REG_CMP: + case OP_COND_BR: + case OP_STORE16: + case OP_STORE32: + case OP_BIT: + case OP_EX2: + trace_result (0, 0); + break; + + case OP_LOAD16: + case OP_STSR: + trace_result (1, State.regs[OP[0]]); + break; + + case OP_REG_REG: + case OP_REG_REG_MOVE: + case OP_IMM_REG: + case OP_IMM_REG_MOVE: + case OP_LOAD32: + case OP_EX1: + trace_result (1, State.regs[OP[1]]); + break; + + case OP_IMM_REG_REG: + case OP_UIMM_REG_REG: + case OP_IMM16_REG_REG: + case OP_UIMM16_REG_REG: + trace_result (1, State.regs[OP[1]]); + break; + + case OP_JUMP: + if (OP[1] != 0) + trace_result (1, State.regs[OP[1]]); + else + trace_result (0, 0); + break; + + case OP_LDSR: + trace_result (1, State.sregs[OP[1]]); + break; } } +#endif -static void -trace_output (result) - enum op_types result; + +/* Returns 1 if the specific condition is met, returns 0 otherwise. */ +int +condition_met (unsigned code) { - if ((v850_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + unsigned int psw = PSW; + + switch (code & 0xf) { - switch (result) - { - default: - case OP_UNKNOWN: - case OP_NONE: - case OP_TRAP: - case OP_REG: - case OP_REG_REG_CMP: - case OP_IMM_REG_CMP: - case OP_COND_BR: - case OP_STORE16: - case OP_STORE32: - case OP_BIT: - case OP_EX2: - break; + case 0x0: return ((psw & PSW_OV) != 0); + case 0x1: return ((psw & PSW_CY) != 0); + case 0x2: return ((psw & PSW_Z) != 0); + case 0x3: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) != 0); + case 0x4: return ((psw & PSW_S) != 0); + /*case 0x5: return 1;*/ + case 0x6: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) != 0); + case 0x7: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) != 0); + case 0x8: return ((psw & PSW_OV) == 0); + case 0x9: return ((psw & PSW_CY) == 0); + case 0xa: return ((psw & PSW_Z) == 0); + case 0xb: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) == 0); + case 0xc: return ((psw & PSW_S) == 0); + case 0xd: return ((psw & PSW_SAT) != 0); + case 0xe: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) == 0); + case 0xf: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) == 0); + } + + return 1; +} - case OP_LOAD16: - case OP_STSR: - (*v850_callback->printf_filtered) (v850_callback, " :: 0x%.8lx", - (unsigned long)State.regs[OP[0]]); - break; +unsigned long +Add32 (unsigned long a1, unsigned long a2, int * carry) +{ + unsigned long result = (a1 + a2); - case OP_REG_REG: - case OP_REG_REG_MOVE: - case OP_IMM_REG: - case OP_IMM_REG_MOVE: - case OP_LOAD32: - case OP_EX1: - (*v850_callback->printf_filtered) (v850_callback, " :: 0x%.8lx", - (unsigned long)State.regs[OP[1]]); - break; + * carry = (result < a1); - case OP_IMM_REG_REG: - case OP_UIMM_REG_REG: - (*v850_callback->printf_filtered) (v850_callback, " :: 0x%.8lx", - (unsigned long)State.regs[OP[2]]); - break; + return result; +} - case OP_JUMP: - if (OP[1] != 0) - (*v850_callback->printf_filtered) (v850_callback, " :: 0x%.8lx", - (unsigned long)State.regs[OP[1]]); - break; +static void +Multiply64 (int sign, unsigned long op0) +{ + unsigned long op1; + unsigned long lo; + unsigned long mid1; + unsigned long mid2; + unsigned long hi; + unsigned long RdLo; + unsigned long RdHi; + int carry; + + op1 = State.regs[ OP[1] ]; - case OP_LDSR: - (*v850_callback->printf_filtered) (v850_callback, " :: 0x%.8lx", - (unsigned long)State.sregs[OP[1]]); - break; + if (sign) + { + /* Compute sign of result and adjust operands if necessary. */ + + sign = (op0 ^ op1) & 0x80000000; + + if (((signed long) op0) < 0) + op0 = - op0; + + if (((signed long) op1) < 0) + op1 = - op1; + } + + /* We can split the 32x32 into four 16x16 operations. This ensures + that we do not lose precision on 32bit only hosts: */ + lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF)); + mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); + mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF)); + hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); + + /* We now need to add all of these results together, taking care + to propogate the carries from the additions: */ + RdLo = Add32 (lo, (mid1 << 16), & carry); + RdHi = carry; + RdLo = Add32 (RdLo, (mid2 << 16), & carry); + RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); + + if (sign) + { + /* Negate result if necessary. */ + + RdLo = ~ RdLo; + RdHi = ~ RdHi; + if (RdLo == 0xFFFFFFFF) + { + RdLo = 0; + RdHi += 1; } - - (*v850_callback->printf_filtered) (v850_callback, "\n"); + else + RdLo += 1; } -} + + /* Don't store into register 0. */ + if (OP[1]) + State.regs[ OP[1] ] = RdLo; + if (OP[2] >> 11) + State.regs[ OP[2] >> 11 ] = RdHi; -#else -#define trace_input(NAME, IN1, IN2) -#define trace_output(RESULT) -#endif + return; +} -/* sld.b */ -void -OP_300 () +/* Read a null terminated string from memory, return in a buffer. */ + +static char * +fetch_str (SIM_DESC sd, address_word addr) { - unsigned int op2; - int result, temp; + char *buf; + int nr = 0; - trace_input ("sld.b", OP_LOAD16, 1); - temp = OP[1]; - temp = SEXT7 (temp); - op2 = temp; - result = load_mem (State.regs[30] + op2, 1); - State.regs[OP[0]] = SEXT8 (result); - trace_output (OP_LOAD16); -} + while (sim_core_read_1 (STATE_CPU (sd, 0), + PC, read_map, addr + nr) != 0) + nr++; -/* sld.h */ -void -OP_400 () -{ - unsigned int op2; - int result, temp; + buf = NZALLOC (char, nr + 1); + sim_read (simulator, addr, (unsigned char *) buf, nr); - trace_input ("sld.h", OP_LOAD16, 2); - temp = OP[1]; - temp = SEXT7 (temp); - op2 = temp << 1; - result = load_mem (State.regs[30] + op2, 2); - State.regs[OP[0]] = SEXT16 (result); - trace_output (OP_LOAD16); + return buf; } -/* sld.w */ -void -OP_500 () +/* Read a null terminated argument vector from memory, return in a + buffer. */ + +static char ** +fetch_argv (SIM_DESC sd, address_word addr) { - unsigned int op2; - int result, temp; + int max_nr = 64; + int nr = 0; + char **buf = xmalloc (max_nr * sizeof (char*)); - trace_input ("sld.w", OP_LOAD16, 4); - temp = OP[1]; - temp = SEXT7 (temp); - op2 = temp << 2; - result = load_mem (State.regs[30] + op2, 4); - State.regs[OP[0]] = result; - trace_output (OP_LOAD16); + while (1) + { + unsigned32 a = sim_core_read_4 (STATE_CPU (sd, 0), + PC, read_map, addr + nr * 4); + if (a == 0) break; + buf[nr] = fetch_str (sd, a); + nr ++; + if (nr == max_nr - 1) + { + max_nr += 50; + buf = xrealloc (buf, max_nr * sizeof (char*)); + } + } + buf[nr] = 0; + return buf; } + /* sst.b */ -void -OP_380 () +int +OP_380 (void) { - unsigned int op0, op1; - int temp; - trace_input ("sst.b", OP_STORE16, 1); - op0 = State.regs[OP[0]]; - temp = OP[1]; - temp = SEXT7 (temp); - op1 = temp; - store_mem (State.regs[30] + op1, 1, op0); + + store_mem (State.regs[30] + (OP[3] & 0x7f), 1, State.regs[ OP[1] ]); + trace_output (OP_STORE16); + + return 2; } /* sst.h */ -void -OP_480 () +int +OP_480 (void) { - unsigned int op0, op1; - int temp; - trace_input ("sst.h", OP_STORE16, 2); - op0 = State.regs[OP[0]]; - temp = OP[1]; - temp = SEXT7 (temp); - op1 = temp << 1; - store_mem (State.regs[30] + op1, 2, op0); + + store_mem (State.regs[30] + ((OP[3] & 0x7f) << 1), 2, State.regs[ OP[1] ]); + trace_output (OP_STORE16); + + return 2; } /* sst.w */ -void -OP_501 () +int +OP_501 (void) { - unsigned int op0, op1; - int temp; - trace_input ("sst.w", OP_STORE16, 4); - op0 = State.regs[OP[0]]; - temp = OP[1]; - temp = SEXT7 (temp); - op1 = temp << 2; - store_mem (State.regs[30] + op1, 4, op0); + + store_mem (State.regs[30] + ((OP[3] & 0x7e) << 1), 4, State.regs[ OP[1] ]); + trace_output (OP_STORE16); + + return 2; } /* ld.b */ -void -OP_700 () +int +OP_700 (void) { - unsigned int op0, op2; - int result, temp; + int adr; trace_input ("ld.b", OP_LOAD32, 1); - op0 = State.regs[OP[0]]; - temp = SEXT16 (OP[2]); - op2 = temp; - result = load_mem (op0 + op2, 1); - State.regs[OP[1]] = SEXT8 (result); + + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); + + State.regs[ OP[1] ] = EXTEND8 (load_mem (adr, 1)); + trace_output (OP_LOAD32); + + return 4; } /* ld.h */ -void -OP_720 () +int +OP_720 (void) { - unsigned int op0, op2; - int result, temp; + int adr; trace_input ("ld.h", OP_LOAD32, 2); - op0 = State.regs[OP[0]]; - temp = SEXT16 (OP[2]); - temp &= ~0x1; - op2 = temp; - result = load_mem (op0 + op2, 2); - State.regs[OP[1]] = SEXT16 (result); + + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); + adr &= ~0x1; + + State.regs[ OP[1] ] = EXTEND16 (load_mem (adr, 2)); + trace_output (OP_LOAD32); + + return 4; } /* ld.w */ -void -OP_10720 () +int +OP_10720 (void) { - unsigned int op0, op2; - int result, temp; + int adr; trace_input ("ld.w", OP_LOAD32, 4); - op0 = State.regs[OP[0]]; - temp = SEXT16 (OP[2]); - temp &= ~0x1; - op2 = temp; - result = load_mem (op0 + op2, 4); - State.regs[OP[1]] = result; + + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1); + adr &= ~0x3; + + State.regs[ OP[1] ] = load_mem (adr, 4); + trace_output (OP_LOAD32); + + return 4; } /* st.b */ -void -OP_740 () +int +OP_740 (void) { - unsigned int op0, op1, op2; - int temp; - trace_input ("st.b", OP_STORE32, 1); - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; - temp = SEXT16 (OP[2]); - op2 = temp; - store_mem (op0 + op2, 1, op1); + + store_mem (State.regs[ OP[0] ] + EXTEND16 (OP[2]), 1, State.regs[ OP[1] ]); + trace_output (OP_STORE32); + + return 4; } /* st.h */ -void -OP_760 () +int +OP_760 (void) { - unsigned int op0, op1, op2; - int temp; - + int adr; + trace_input ("st.h", OP_STORE32, 2); - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; - temp = SEXT16 (OP[2] & ~0x1); - op2 = temp; - store_mem (op0 + op2, 2, op1); + + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); + adr &= ~1; + + store_mem (adr, 2, State.regs[ OP[1] ]); + trace_output (OP_STORE32); + + return 4; } /* st.w */ -void -OP_10760 () +int +OP_10760 (void) { - unsigned int op0, op1, op2; - int temp; - + int adr; + trace_input ("st.w", OP_STORE32, 4); - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; - temp = SEXT16 (OP[2] & ~0x1); - op2 = temp; - store_mem (op0 + op2, 4, op1); - trace_output (OP_STORE32); -} - -/* bv disp9 */ -void -OP_580 () -{ - unsigned int psw; - int op0; - - trace_input ("bv", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_OV) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bl disp9 */ -void -OP_581 () -{ - unsigned int psw; - int op0; - - trace_input ("bl", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_CY) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* be disp9 */ -void -OP_582 () -{ - unsigned int psw; - int op0; - - trace_input ("be", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_Z) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bnh disp 9*/ -void -OP_583 () -{ - unsigned int psw; - int op0; - - trace_input ("bnh", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bn disp9 */ -void -OP_584 () -{ - unsigned int psw; - int op0; - - trace_input ("bn", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_S) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* br disp9 */ -void -OP_585 () -{ - unsigned int psw; - int op0; - - trace_input ("br", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - State.pc += op0; - trace_output (OP_COND_BR); -} - -/* blt disp9 */ -void -OP_586 () -{ - unsigned int psw; - int op0; - - trace_input ("blt", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* ble disp9 */ -void -OP_587 () -{ - unsigned int psw; - int op0; - - trace_input ("ble", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((((psw & PSW_Z) != 0) - || (((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0))) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bnv disp9 */ -void -OP_588 () -{ - unsigned int psw; - int op0; - - trace_input ("bnv", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_OV) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bnl disp9 */ -void -OP_589 () -{ - unsigned int psw; - int op0; - - trace_input ("bnl", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_CY) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bne disp9 */ -void -OP_58A () -{ - unsigned int psw; - int op0; - - trace_input ("bne", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_Z) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bh disp9 */ -void -OP_58B () -{ - unsigned int psw; - int op0; - - trace_input ("bh", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bp disp9 */ -void -OP_58C () -{ - unsigned int psw; - int op0; - - trace_input ("bp", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_S) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bsa disp9 */ -void -OP_58D () -{ - unsigned int psw; - int op0; - - trace_input ("bsa", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; - - if ((psw & PSW_SAT) != 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bge disp9 */ -void -OP_58E () -{ - unsigned int psw; - int op0; - trace_input ("bge", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1); + adr &= ~3; - if ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* bgt disp9 */ -void -OP_58F () -{ - unsigned int psw; - int op0; - - trace_input ("bgt", OP_COND_BR, 0); - op0 = SEXT9 (OP[0]); - psw = State.sregs[5]; + store_mem (adr, 4, State.regs[ OP[1] ]); - if ((((psw & PSW_Z) != 0) - || (((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0))) == 0) - State.pc += op0; - else - State.pc += 2; - trace_output (OP_COND_BR); -} - -/* jmp [reg1] */ -void -OP_60 () -{ - /* interp.c will bump this by +2, so correct for it here. */ - trace_input ("jmp", OP_REG, 0); - State.pc = State.regs[OP[0]] - 2; - trace_output (OP_REG); -} - -/* jarl disp22, reg */ -void -OP_780 () -{ - unsigned int op0, opc; - int temp; - - trace_input ("jarl", OP_JUMP, 0); - temp = SEXT22 (OP[0]); - op0 = temp; - opc = State.pc; - - State.pc += temp; + trace_output (OP_STORE32); - /* Gross. jarl X,r0 is really jr and doesn't save its result. */ - if (OP[1] != 0) - State.regs[OP[1]] = opc + 4; - trace_output (OP_JUMP); + return 4; } /* add reg, reg */ -void -OP_1C0 () +int +OP_1C0 (void) { unsigned int op0, op1, result, z, s, cy, ov; trace_input ("add", OP_REG_REG, 0); + /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; + result = op0 + op1; /* Compute the condition codes. */ @@ -944,15 +602,17 @@ OP_1C0 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_REG_REG); + + return 2; } /* add sign_extend(imm5), reg */ -void -OP_240 () +int +OP_240 (void) { unsigned int op0, op1, result, z, s, cy, ov; int temp; @@ -974,25 +634,26 @@ OP_240 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_IMM_REG); + + return 2; } /* addi sign_extend(imm16), reg, reg */ -void -OP_600 () +int +OP_600 (void) { unsigned int op0, op1, result, z, s, cy, ov; - int temp; - trace_input ("addi", OP_IMM_REG_REG, 0); + trace_input ("addi", OP_IMM16_REG_REG, 0); /* Compute the result. */ - temp = SEXT16 (OP[0]); - op0 = temp; - op1 = State.regs[OP[1]]; + + op0 = EXTEND16 (OP[2]); + op1 = State.regs[ OP[0] ]; result = op0 + op1; /* Compute the condition codes. */ @@ -1003,23 +664,25 @@ OP_600 () && (op0 & 0x80000000) != (result & 0x80000000)); /* Store the result and condition codes. */ - State.regs[OP[2]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + State.regs[OP[1]] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); - trace_output (OP_IMM_REG_REG); + trace_output (OP_IMM16_REG_REG); + + return 4; } /* sub reg1, reg2 */ -void -OP_1A0 () +int +OP_1A0 (void) { unsigned int op0, op1, result, z, s, cy, ov; trace_input ("sub", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op1 - op0; /* Compute the condition codes. */ @@ -1031,22 +694,24 @@ OP_1A0 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_REG_REG); + + return 2; } /* subr reg1, reg2 */ -void -OP_180 () +int +OP_180 (void) { unsigned int op0, op1, result, z, s, cy, ov; trace_input ("subr", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 - op1; /* Compute the condition codes. */ @@ -1058,98 +723,63 @@ OP_180 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_REG_REG); + + return 2; } -/* mulh reg1, reg2 */ -void -OP_E0 () +/* sxh reg1 */ +int +OP_E0 (void) { trace_input ("mulh", OP_REG_REG, 0); - State.regs[OP[1]] = ((State.regs[OP[1]] & 0xffff) - * (State.regs[OP[0]] & 0xffff)); + + State.regs[ OP[1] ] = (EXTEND16 (State.regs[ OP[1] ]) * EXTEND16 (State.regs[ OP[0] ])); + trace_output (OP_REG_REG); -} -/* mulh sign_extend(imm5), reg2 + return 2; +} - Condition codes */ -void -OP_2E0 () +/* mulh sign_extend(imm5), reg2 */ +int +OP_2E0 (void) { - int value = SEXT5 (OP[0]); - trace_input ("mulh", OP_IMM_REG, 0); - State.regs[OP[1]] = (State.regs[OP[1]] & 0xffff) * value; + + State.regs[ OP[1] ] = EXTEND16 (State.regs[ OP[1] ]) * SEXT5 (OP[0]); + trace_output (OP_IMM_REG); -} -/* mulhi imm16, reg1, reg2 */ -void -OP_6E0 () -{ - int value = OP[0] & 0xffff; - - trace_input ("mulhi", OP_IMM_REG_REG, 0); - State.regs[OP[2]] = (State.regs[OP[1]] & 0xffff) * value; - trace_output (OP_IMM_REG_REG); + return 2; } -/* divh reg1, reg2 */ -void -OP_40 () +/* mulhi imm16, reg1, reg2 */ +int +OP_6E0 (void) { - unsigned int op0, op1, result, ov, s, z; - int temp; - - trace_input ("divh", OP_REG_REG, 0); - - /* Compute the result. */ - temp = SEXT16 (State.regs[OP[0]]); - op0 = temp; - op1 = State.regs[OP[1]]; - - if (op0 == 0xffffffff && op1 == 0x80000000) - { - result = 0x80000000; - ov = 1; - } - else if (op0 != 0) - { - result = op1 / op0; - ov = 0; - } - else - { - result = 0x0; - ov = 1; - } - - /* Compute the condition codes. */ - z = (result == 0); - s = (result & 0x80000000); - - /* Store the result and condition codes. */ - State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) - | (ov ? PSW_OV : 0)); - trace_output (OP_REG_REG); + trace_input ("mulhi", OP_IMM16_REG_REG, 0); + + State.regs[ OP[1] ] = EXTEND16 (State.regs[ OP[0] ]) * EXTEND16 (OP[2]); + + trace_output (OP_IMM16_REG_REG); + + return 4; } /* cmp reg, reg */ -void -OP_1E0 () +int +OP_1E0 (void) { unsigned int op0, op1, result, z, s, cy, ov; trace_input ("cmp", OP_REG_REG_CMP, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op1 - op0; /* Compute the condition codes. */ @@ -1160,15 +790,17 @@ OP_1E0 () && (op1 & 0x80000000) != (result & 0x80000000)); /* Set condition codes. */ - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_REG_REG_CMP); + + return 2; } /* cmp sign_extend(imm5), reg */ -void -OP_260 () +int +OP_260 (void) { unsigned int op0, op1, result, z, s, cy, ov; int temp; @@ -1188,94 +820,39 @@ OP_260 () && (op1 & 0x80000000) != (result & 0x80000000)); /* Set condition codes. */ - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_IMM_REG_CMP); + + return 2; } /* setf cccc,reg2 */ -void -OP_7E0 () +int +OP_7E0 (void) { - /* Hack alert. We turn off a bit in op0 since we really only - wanted 4 bits. */ - unsigned int op0, psw, result = 0; - trace_input ("setf", OP_EX1, 0); - op0 = OP[0] & 0xf; - psw = State.sregs[5]; - switch (op0) - { - case 0x0: - result = ((psw & PSW_OV) != 0); - break; - case 0x1: - result = ((psw & PSW_CY) != 0); - break; - case 0x2: - result = ((psw & PSW_Z) != 0); - break; - case 0x3: - result = ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) != 0); - break; - case 0x4: - result = ((psw & PSW_S) != 0); - break; - case 0x5: - result = 1; - break; - case 0x6: - result = ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) != 0); - break; - case 0x7: - result = (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) - || ((psw & PSW_Z) != 0)) != 0); - break; - case 0x8: - result = ((psw & PSW_OV) == 0); - break; - case 0x9: - result = ((psw & PSW_CY) == 0); - break; - case 0xa: - result = ((psw & PSW_Z) == 0); - break; - case 0xb: - result = ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) == 0); - break; - case 0xc: - result = ((psw & PSW_S) == 0); - break; - case 0xd: - result = ((psw & PSW_SAT) != 0); - break; - case 0xe: - result = ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) == 0); - break; - case 0xf: - result = (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) - || ((psw & PSW_Z) != 0)) == 0); - break; - } + State.regs[ OP[1] ] = condition_met (OP[0]); - State.regs[OP[1]] = result; trace_output (OP_EX1); + + return 4; } /* satadd reg,reg */ -void -OP_C0 () +int +OP_C0 (void) { unsigned int op0, op1, result, z, s, cy, ov, sat; - + trace_input ("satadd", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 + op1; - + /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); @@ -1283,25 +860,38 @@ OP_C0 () ov = ((op0 & 0x80000000) == (op1 & 0x80000000) && (op0 & 0x80000000) != (result & 0x80000000)); sat = ov; + + /* Handle saturated results. */ + if (sat && s) + { + /* An overflow that results in a negative result implies that we + became too positive. */ + result = 0x7fffffff; + s = 0; + } + else if (sat) + { + /* Any other overflow must have thus been too negative. */ + result = 0x80000000; + s = 1; + z = 0; + } /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) - | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) - | (sat ? PSW_SAT : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); - /* Handle saturated results. */ - if (sat && s) - State.regs[OP[1]] = 0x80000000; - else if (sat) - State.regs[OP[1]] = 0x7fffffff; trace_output (OP_REG_REG); + + return 2; } /* satadd sign_extend(imm5), reg */ -void -OP_220 () +int +OP_220 (void) { unsigned int op0, op1, result, z, s, cy, ov, sat; @@ -1323,34 +913,46 @@ OP_220 () && (op0 & 0x80000000) != (result & 0x80000000)); sat = ov; + /* Handle saturated results. */ + if (sat && s) + { + /* An overflow that results in a negative result implies that we + became too positive. */ + result = 0x7fffffff; + s = 0; + } + else if (sat) + { + /* Any other overflow must have thus been too negative. */ + result = 0x80000000; + s = 1; + z = 0; + } + /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) | (sat ? PSW_SAT : 0)); - - /* Handle saturated results. */ - if (sat && s) - State.regs[OP[1]] = 0x80000000; - else if (sat) - State.regs[OP[1]] = 0x7fffffff; trace_output (OP_IMM_REG); + + return 2; } /* satsub reg1, reg2 */ -void -OP_A0 () +int +OP_A0 (void) { unsigned int op0, op1, result, z, s, cy, ov, sat; - + trace_input ("satsub", OP_REG_REG, 0); - + /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op1 - op0; - + /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); @@ -1359,24 +961,36 @@ OP_A0 () && (op1 & 0x80000000) != (result & 0x80000000)); sat = ov; - /* Store the result and condition codes. */ - State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) - | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) - | (sat ? PSW_SAT : 0)); - /* Handle saturated results. */ if (sat && s) - State.regs[OP[1]] = 0x80000000; + { + /* An overflow that results in a negative result implies that we + became too positive. */ + result = 0x7fffffff; + s = 0; + } else if (sat) - State.regs[OP[1]] = 0x7fffffff; + { + /* Any other overflow must have thus been too negative. */ + result = 0x80000000; + s = 1; + z = 0; + } + + /* Store the result and condition codes. */ + State.regs[OP[1]] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + trace_output (OP_REG_REG); + return 2; } /* satsubi sign_extend(imm16), reg */ -void -OP_660 () +int +OP_660 (void) { unsigned int op0, op1, result, z, s, cy, ov, sat; int temp; @@ -1384,9 +998,9 @@ OP_660 () trace_input ("satsubi", OP_IMM_REG, 0); /* Compute the result. */ - temp = SEXT16 (OP[0]); + temp = EXTEND16 (OP[2]); op0 = temp; - op1 = State.regs[OP[1]]; + op1 = State.regs[ OP[0] ]; result = op1 - op0; /* Compute the condition codes. */ @@ -1397,68 +1011,94 @@ OP_660 () && (op1 & 0x80000000) != (result & 0x80000000)); sat = ov; - /* Store the result and condition codes. */ + /* Handle saturated results. */ + if (sat && s) + { + /* An overflow that results in a negative result implies that we + became too positive. */ + result = 0x7fffffff; + s = 0; + } + else if (sat) + { + /* Any other overflow must have thus been too negative. */ + result = 0x80000000; + s = 1; + z = 0; + } + + /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) | (sat ? PSW_SAT : 0)); - /* Handle saturated results. */ - if (sat && s) - State.regs[OP[1]] = 0x80000000; - else if (sat) - State.regs[OP[1]] = 0x7fffffff; trace_output (OP_IMM_REG); + + return 4; } /* satsubr reg,reg */ -void -OP_80 () +int +OP_80 (void) { unsigned int op0, op1, result, z, s, cy, ov, sat; - + trace_input ("satsubr", OP_REG_REG, 0); - + /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 - op1; - + /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (result < op0); - ov = ((op1 & 0x80000000) != (op0 & 0x80000000) - && (op1 & 0x80000000) != (result & 0x80000000)); + cy = (op0 < op1); + ov = ((op0 & 0x80000000) != (op1 & 0x80000000) + && (op0 & 0x80000000) != (result & 0x80000000)); sat = ov; - /* Store the result and condition codes. */ - State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) - | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) - | (sat ? PSW_SAT : 0)); - /* Handle saturated results. */ if (sat && s) - State.regs[OP[1]] = 0x80000000; + { + /* An overflow that results in a negative result implies that we + became too positive. */ + result = 0x7fffffff; + s = 0; + } else if (sat) - State.regs[OP[1]] = 0x7fffffff; + { + /* Any other overflow must have thus been too negative. */ + result = 0x80000000; + s = 1; + z = 0; + } + + /* Store the result and condition codes. */ + State.regs[OP[1]] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + trace_output (OP_REG_REG); + + return 2; } /* tst reg,reg */ -void -OP_160 () +int +OP_160 (void) { unsigned int op0, op1, result, z, s; trace_input ("tst", OP_REG_REG_CMP, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 & op1; /* Compute the condition codes. */ @@ -1466,209 +1106,209 @@ OP_160 () s = (result & 0x80000000); /* Store the condition codes. */ - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); trace_output (OP_REG_REG_CMP); -} -/* mov reg, reg */ -void -OP_0 () -{ - trace_input ("mov", OP_REG_REG_MOVE, 0); - State.regs[OP[1]] = State.regs[OP[0]]; - trace_output (OP_REG_REG_MOVE); + return 2; } /* mov sign_extend(imm5), reg */ -void -OP_200 () +int +OP_200 (void) { int value = SEXT5 (OP[0]); - + trace_input ("mov", OP_IMM_REG_MOVE, 0); - State.regs[OP[1]] = value; + + State.regs[ OP[1] ] = value; + trace_output (OP_IMM_REG_MOVE); -} - -/* movea sign_extend(imm16), reg, reg */ - -void -OP_620 () -{ - int value = SEXT16 (OP[0]); - - trace_input ("movea", OP_IMM_REG_REG, 0); - State.regs[OP[2]] = State.regs[OP[1]] + value; - trace_output (OP_IMM_REG_REG); + + return 2; } /* movhi imm16, reg, reg */ -void -OP_640 () +int +OP_640 (void) { - uint32 value = (OP[0] & 0xffff) << 16; + trace_input ("movhi", OP_UIMM16_REG_REG, 16); + + State.regs[ OP[1] ] = State.regs[ OP[0] ] + (OP[2] << 16); + + trace_output (OP_UIMM16_REG_REG); - trace_input ("movhi", OP_UIMM_REG_REG, 16); - State.regs[OP[2]] = State.regs[OP[1]] + value; - trace_output (OP_UIMM_REG_REG); + return 4; } /* sar zero_extend(imm5),reg1 */ -void -OP_2A0 () +int +OP_2A0 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("sar", OP_IMM_REG, 0); - op0 = OP[0] & 0x1f; - op1 = State.regs[OP[1]]; + op0 = OP[0]; + op1 = State.regs[ OP[1] ]; result = (signed)op1 >> op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (op0 - 1))); + cy = op0 ? (op1 & (1 << (op0 - 1))) : 0; /* Store the result and condition codes. */ - State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + State.regs[ OP[1] ] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_IMM_REG); + + return 2; } /* sar reg1, reg2 */ -void -OP_A007E0 () +int +OP_A007E0 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("sar", OP_REG_REG, 0); - op0 = State.regs[OP[0]] & 0x1f; - op1 = State.regs[OP[1]]; + + op0 = State.regs[ OP[0] ] & 0x1f; + op1 = State.regs[ OP[1] ]; result = (signed)op1 >> op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (op0 - 1))); + cy = op0 ? (op1 & (1 << (op0 - 1))) : 0; /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_REG_REG); + + return 4; } /* shl zero_extend(imm5),reg1 */ -void -OP_2C0 () +int +OP_2C0 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("shl", OP_IMM_REG, 0); - op0 = OP[0] & 0x1f; - op1 = State.regs[OP[1]]; + op0 = OP[0]; + op1 = State.regs[ OP[1] ]; result = op1 << op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (32 - op0))); + cy = op0 ? (op1 & (1 << (32 - op0))) : 0; /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_IMM_REG); + + return 2; } /* shl reg1, reg2 */ -void -OP_C007E0 () +int +OP_C007E0 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("shl", OP_REG_REG, 0); - op0 = State.regs[OP[0]] & 0x1f; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ] & 0x1f; + op1 = State.regs[ OP[1] ]; result = op1 << op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (32 - op0))); + cy = op0 ? (op1 & (1 << (32 - op0))) : 0; /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_REG_REG); + + return 4; } /* shr zero_extend(imm5),reg1 */ -void -OP_280 () +int +OP_280 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("shr", OP_IMM_REG, 0); - op0 = OP[0] & 0x1f; - op1 = State.regs[OP[1]]; + op0 = OP[0]; + op1 = State.regs[ OP[1] ]; result = op1 >> op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (op0 - 1))); + cy = op0 ? (op1 & (1 << (op0 - 1))) : 0; /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_IMM_REG); + + return 2; } /* shr reg1, reg2 */ -void -OP_8007E0 () +int +OP_8007E0 (void) { unsigned int op0, op1, result, z, s, cy; trace_input ("shr", OP_REG_REG, 0); - op0 = State.regs[OP[0]] & 0x1f; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ] & 0x1f; + op1 = State.regs[ OP[1] ]; result = op1 >> op0; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); - cy = (op1 & (1 << (op0 - 1))); + cy = op0 ? (op1 & (1 << (op0 - 1))) : 0; /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0)); trace_output (OP_REG_REG); + + return 4; } /* or reg, reg */ -void -OP_100 () +int +OP_100 (void) { unsigned int op0, op1, result, z, s; trace_input ("or", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 | op1; /* Compute the condition codes. */ @@ -1677,20 +1317,22 @@ OP_100 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); trace_output (OP_REG_REG); + + return 2; } /* ori zero_extend(imm16), reg, reg */ -void -OP_680 () +int +OP_680 (void) { unsigned int op0, op1, result, z, s; - trace_input ("ori", OP_UIMM_REG_REG, 0); - op0 = OP[0] & 0xffff; - op1 = State.regs[OP[1]]; + trace_input ("ori", OP_UIMM16_REG_REG, 0); + op0 = OP[2]; + op1 = State.regs[ OP[0] ]; result = op0 | op1; /* Compute the condition codes. */ @@ -1698,23 +1340,25 @@ OP_680 () s = (result & 0x80000000); /* Store the result and condition codes. */ - State.regs[OP[2]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); - trace_output (OP_UIMM_REG_REG); + State.regs[OP[1]] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + trace_output (OP_UIMM16_REG_REG); + + return 4; } /* and reg, reg */ -void -OP_140 () +int +OP_140 (void) { unsigned int op0, op1, result, z, s; trace_input ("and", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 & op1; /* Compute the condition codes. */ @@ -1723,43 +1367,48 @@ OP_140 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); trace_output (OP_REG_REG); + + return 2; } /* andi zero_extend(imm16), reg, reg */ -void -OP_6C0 () +int +OP_6C0 (void) { - unsigned int op0, op1, result, z; + unsigned int result, z; - trace_input ("andi", OP_UIMM_REG_REG, 0); - op0 = OP[0] & 0xffff; - op1 = State.regs[OP[1]]; - result = op0 & op1; + trace_input ("andi", OP_UIMM16_REG_REG, 0); + + result = OP[2] & State.regs[ OP[0] ]; /* Compute the condition codes. */ z = (result == 0); /* Store the result and condition codes. */ - State.regs[OP[2]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= (z ? PSW_Z : 0); - trace_output (OP_UIMM_REG_REG); + State.regs[ OP[1] ] = result; + + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= (z ? PSW_Z : 0); + + trace_output (OP_UIMM16_REG_REG); + + return 4; } /* xor reg, reg */ -void -OP_120 () +int +OP_120 (void) { unsigned int op0, op1, result, z, s; trace_input ("xor", OP_REG_REG, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; - op1 = State.regs[OP[1]]; + op0 = State.regs[ OP[0] ]; + op1 = State.regs[ OP[1] ]; result = op0 ^ op1; /* Compute the condition codes. */ @@ -1768,20 +1417,22 @@ OP_120 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); trace_output (OP_REG_REG); + + return 2; } /* xori zero_extend(imm16), reg, reg */ -void -OP_6A0 () +int +OP_6A0 (void) { unsigned int op0, op1, result, z, s; - trace_input ("xori", OP_UIMM_REG_REG, 0); - op0 = OP[0] & 0xffff; - op1 = State.regs[OP[1]]; + trace_input ("xori", OP_UIMM16_REG_REG, 0); + op0 = OP[2]; + op1 = State.regs[ OP[0] ]; result = op0 ^ op1; /* Compute the condition codes. */ @@ -1789,21 +1440,23 @@ OP_6A0 () s = (result & 0x80000000); /* Store the result and condition codes. */ - State.regs[OP[2]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); - trace_output (OP_UIMM_REG_REG); + State.regs[OP[1]] = result; + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + trace_output (OP_UIMM16_REG_REG); + + return 4; } /* not reg1, reg2 */ -void -OP_20 () +int +OP_20 (void) { unsigned int op0, result, z, s; trace_input ("not", OP_REG_REG_MOVE, 0); /* Compute the result. */ - op0 = State.regs[OP[0]]; + op0 = State.regs[ OP[0] ]; result = ~op0; /* Compute the condition codes. */ @@ -1812,153 +1465,141 @@ OP_20 () /* Store the result and condition codes. */ State.regs[OP[1]] = result; - State.sregs[5] &= ~(PSW_Z | PSW_S | PSW_OV); - State.sregs[5] |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)); trace_output (OP_REG_REG_MOVE); + + return 2; } /* set1 */ -void -OP_7C0 () +int +OP_7C0 (void) { unsigned int op0, op1, op2; int temp; trace_input ("set1", OP_BIT, 0); - op0 = State.regs[OP[0]]; + op0 = State.regs[ OP[0] ]; op1 = OP[1] & 0x7; - temp = SEXT16 (OP[2]); + temp = EXTEND16 (OP[2]); op2 = temp; temp = load_mem (op0 + op2, 1); - State.sregs[5] &= ~PSW_Z; + PSW &= ~PSW_Z; if ((temp & (1 << op1)) == 0) - State.sregs[5] |= PSW_Z; + PSW |= PSW_Z; temp |= (1 << op1); store_mem (op0 + op2, 1, temp); trace_output (OP_BIT); + + return 4; } /* not1 */ -void -OP_47C0 () +int +OP_47C0 (void) { unsigned int op0, op1, op2; int temp; trace_input ("not1", OP_BIT, 0); - op0 = State.regs[OP[0]]; + op0 = State.regs[ OP[0] ]; op1 = OP[1] & 0x7; - temp = SEXT16 (OP[2]); + temp = EXTEND16 (OP[2]); op2 = temp; temp = load_mem (op0 + op2, 1); - State.sregs[5] &= ~PSW_Z; + PSW &= ~PSW_Z; if ((temp & (1 << op1)) == 0) - State.sregs[5] |= PSW_Z; + PSW |= PSW_Z; temp ^= (1 << op1); store_mem (op0 + op2, 1, temp); trace_output (OP_BIT); + + return 4; } /* clr1 */ -void -OP_87C0 () +int +OP_87C0 (void) { unsigned int op0, op1, op2; int temp; trace_input ("clr1", OP_BIT, 0); - op0 = State.regs[OP[0]]; + op0 = State.regs[ OP[0] ]; op1 = OP[1] & 0x7; - temp = SEXT16 (OP[2]); + temp = EXTEND16 (OP[2]); op2 = temp; temp = load_mem (op0 + op2, 1); - State.sregs[5] &= ~PSW_Z; + PSW &= ~PSW_Z; if ((temp & (1 << op1)) == 0) - State.sregs[5] |= PSW_Z; + PSW |= PSW_Z; temp &= ~(1 << op1); store_mem (op0 + op2, 1, temp); trace_output (OP_BIT); + + return 4; } /* tst1 */ -void -OP_C7C0 () +int +OP_C7C0 (void) { unsigned int op0, op1, op2; int temp; trace_input ("tst1", OP_BIT, 0); - op0 = State.regs[OP[0]]; + op0 = State.regs[ OP[0] ]; op1 = OP[1] & 0x7; - temp = SEXT16 (OP[2]); + temp = EXTEND16 (OP[2]); op2 = temp; temp = load_mem (op0 + op2, 1); - State.sregs[5] &= ~PSW_Z; + PSW &= ~PSW_Z; if ((temp & (1 << op1)) == 0) - State.sregs[5] |= PSW_Z; + PSW |= PSW_Z; trace_output (OP_BIT); -} -/* breakpoint */ -void -OP_FFFF () -{ - State.exception = SIGTRAP; - PC -= 4; + return 4; } /* di */ -void -OP_16007E0 () +int +OP_16007E0 (void) { trace_input ("di", OP_NONE, 0); - State.sregs[5] |= PSW_ID; + PSW |= PSW_ID; trace_output (OP_NONE); + + return 4; } /* ei */ -void -OP_16087E0 () +int +OP_16087E0 (void) { trace_input ("ei", OP_NONE, 0); - State.sregs[5] &= ~PSW_ID; + PSW &= ~PSW_ID; trace_output (OP_NONE); -} -/* halt, not supported */ -void -OP_12007E0 () -{ - trace_input ("halt", OP_NONE, 0); - State.exception = SIGQUIT; - trace_output (OP_NONE); + return 4; } -/* reti, not supported */ -void -OP_14007E0 () +/* halt */ +int +OP_12007E0 (void) { - trace_input ("reti", OP_NONE, 0); + trace_input ("halt", OP_NONE, 0); + /* FIXME this should put processor into a mode where NMI still handled */ trace_output (OP_NONE); - - if ((State.sregs[5] & (PSW_NP | PSW_EP)) == PSW_NP) - { /* Only NP is on */ - PC = State.sregs[2] - 4; /* FEPC */ - State.sregs[5] = State.sregs[3]; /* FEPSW */ - } - else - { - PC = State.sregs[0] - 4; /* EIPC */ - State.sregs[5] = State.sregs[1]; /* EIPSW */ - } + sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC, + sim_stopped, SIM_SIGTRAP); + return 0; } -/* trap, not supportd */ -void -OP_10007E0 () +/* trap */ +int +OP_10007E0 (void) { - extern int errno; - trace_input ("trap", OP_TRAP, 0); trace_output (OP_TRAP); @@ -1985,21 +1626,55 @@ OP_10007E0 () #define MEMPTR(x) (map (x)) + RETERR = 0; + switch (FUNC) { -#if !defined(__GO32__) && !defined(_WIN32) - case SYS_fork: + +#ifdef HAVE_FORK +#ifdef TARGET_SYS_fork + case TARGET_SYS_fork: RETVAL = fork (); + RETERR = errno; break; - case SYS_execve: - RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), - (char **)MEMPTR (PARM3)); - break; - case SYS_execv: - RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL); - break; +#endif +#endif + +#ifdef HAVE_EXECVE +#ifdef TARGET_SYS_execv + case TARGET_SYS_execve: + { + char *path = fetch_str (simulator, PARM1); + char **argv = fetch_argv (simulator, PARM2); + char **envp = fetch_argv (simulator, PARM3); + RETVAL = execve (path, argv, envp); + free (path); + freeargv (argv); + freeargv (envp); + RETERR = errno; + break; + } +#endif +#endif + +#if HAVE_EXECV +#ifdef TARGET_SYS_execv + case TARGET_SYS_execv: + { + char *path = fetch_str (simulator, PARM1); + char **argv = fetch_argv (simulator, PARM2); + RETVAL = execv (path, argv); + free (path); + freeargv (argv); + RETERR = errno; + break; + } +#endif +#endif + #if 0 - case SYS_pipe: +#ifdef TARGET_SYS_pipe + case TARGET_SYS_pipe: { reg_t buf; int host_fd[2]; @@ -2007,129 +1682,1930 @@ OP_10007E0 () buf = PARM1; RETVAL = pipe (host_fd); SW (buf, host_fd[0]); - buf += sizeof(uint16); + buf += sizeof (uint16); SW (buf, host_fd[1]); + RETERR = errno; } break; +#endif +#endif - case SYS_wait: +#if 0 +#ifdef TARGET_SYS_wait + case TARGET_SYS_wait: { int status; RETVAL = wait (&status); SW (PARM1, status); + RETERR = errno; } break; #endif #endif - case SYS_read: - RETVAL = v850_callback->read (v850_callback, PARM1, MEMPTR (PARM2), - PARM3); - break; - case SYS_write: - if (PARM1 == 1) - RETVAL = (int)v850_callback->write_stdout (v850_callback, - MEMPTR (PARM2), PARM3); - else - RETVAL = (int)v850_callback->write (v850_callback, PARM1, - MEMPTR (PARM2), PARM3); - break; - case SYS_lseek: - RETVAL = v850_callback->lseek (v850_callback, PARM1, PARM2, PARM3); - break; - case SYS_close: - RETVAL = v850_callback->close (v850_callback, PARM1); +#ifdef TARGET_SYS_read + case TARGET_SYS_read: + { + char *buf = zalloc (PARM3); + RETVAL = sim_io_read (simulator, PARM1, buf, PARM3); + sim_write (simulator, PARM2, (unsigned char *) buf, PARM3); + free (buf); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + break; + } +#endif + +#ifdef TARGET_SYS_write + case TARGET_SYS_write: + { + char *buf = zalloc (PARM3); + sim_read (simulator, PARM2, (unsigned char *) buf, PARM3); + if (PARM1 == 1) + RETVAL = sim_io_write_stdout (simulator, buf, PARM3); + else + RETVAL = sim_io_write (simulator, PARM1, buf, PARM3); + free (buf); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + break; + } +#endif + +#ifdef TARGET_SYS_lseek + case TARGET_SYS_lseek: + RETVAL = sim_io_lseek (simulator, PARM1, PARM2, PARM3); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); break; - case SYS_open: - RETVAL = v850_callback->open (v850_callback, MEMPTR (PARM1), PARM2); +#endif + +#ifdef TARGET_SYS_close + case TARGET_SYS_close: + RETVAL = sim_io_close (simulator, PARM1); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); break; - case SYS_exit: - /* EXIT - caller can look in PARM1 to work out the - reason */ - if (PARM1 == 0xdead || PARM1 == 0x1) - State.exception = SIGABRT; +#endif + +#ifdef TARGET_SYS_open + case TARGET_SYS_open: + { + char *buf = fetch_str (simulator, PARM1); + RETVAL = sim_io_open (simulator, buf, PARM2); + free (buf); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + break; + } +#endif + +#ifdef TARGET_SYS_exit + case TARGET_SYS_exit: + if ((PARM1 & 0xffff0000) == 0xdead0000 && (PARM1 & 0xffff) != 0) + /* get signal encoded by kill */ + sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC, + sim_signalled, PARM1 & 0xffff); + else if (PARM1 == 0xdead) + /* old libraries */ + sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC, + sim_stopped, SIM_SIGABRT); else - State.exception = SIGQUIT; + /* PARM1 has exit status */ + sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC, + sim_exited, PARM1); break; +#endif -#if 0 - case SYS_stat: /* added at hmsi */ +#ifdef TARGET_SYS_stat + case TARGET_SYS_stat: /* added at hmsi */ /* stat system call */ + { + struct stat host_stat; + reg_t buf; + char *path = fetch_str (simulator, PARM1); + + RETVAL = sim_io_stat (simulator, path, &host_stat); + + free (path); + buf = PARM2; + + /* Just wild-assed guesses. */ + store_mem (buf, 2, host_stat.st_dev); + store_mem (buf + 2, 2, host_stat.st_ino); + store_mem (buf + 4, 4, host_stat.st_mode); + store_mem (buf + 8, 2, host_stat.st_nlink); + store_mem (buf + 10, 2, host_stat.st_uid); + store_mem (buf + 12, 2, host_stat.st_gid); + store_mem (buf + 14, 2, host_stat.st_rdev); + store_mem (buf + 16, 4, host_stat.st_size); + store_mem (buf + 20, 4, host_stat.st_atime); + store_mem (buf + 28, 4, host_stat.st_mtime); + store_mem (buf + 36, 4, host_stat.st_ctime); + + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + } + break; +#endif + +#ifdef TARGET_SYS_fstat + case TARGET_SYS_fstat: + /* fstat system call */ { struct stat host_stat; reg_t buf; - RETVAL = stat (MEMPTR (PARM1), &host_stat); + RETVAL = sim_io_fstat (simulator, PARM1, &host_stat); buf = PARM2; - /* The hard-coded offsets and sizes were determined by using - * the D10V compiler on a test program that used struct stat. - */ - SW (buf, host_stat.st_dev); - SW (buf+2, host_stat.st_ino); - SW (buf+4, host_stat.st_mode); - SW (buf+6, host_stat.st_nlink); - SW (buf+8, host_stat.st_uid); - SW (buf+10, host_stat.st_gid); - SW (buf+12, host_stat.st_rdev); - SLW (buf+16, host_stat.st_size); - SLW (buf+20, host_stat.st_atime); - SLW (buf+28, host_stat.st_mtime); - SLW (buf+36, host_stat.st_ctime); + /* Just wild-assed guesses. */ + store_mem (buf, 2, host_stat.st_dev); + store_mem (buf + 2, 2, host_stat.st_ino); + store_mem (buf + 4, 4, host_stat.st_mode); + store_mem (buf + 8, 2, host_stat.st_nlink); + store_mem (buf + 10, 2, host_stat.st_uid); + store_mem (buf + 12, 2, host_stat.st_gid); + store_mem (buf + 14, 2, host_stat.st_rdev); + store_mem (buf + 16, 4, host_stat.st_size); + store_mem (buf + 20, 4, host_stat.st_atime); + store_mem (buf + 28, 4, host_stat.st_mtime); + store_mem (buf + 36, 4, host_stat.st_ctime); + + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + } + break; +#endif + +#ifdef TARGET_SYS_rename + case TARGET_SYS_rename: + { + char *oldpath = fetch_str (simulator, PARM1); + char *newpath = fetch_str (simulator, PARM2); + RETVAL = sim_io_rename (simulator, oldpath, newpath); + free (oldpath); + free (newpath); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + } + break; +#endif + +#ifdef TARGET_SYS_unlink + case TARGET_SYS_unlink: + { + char *path = fetch_str (simulator, PARM1); + RETVAL = sim_io_unlink (simulator, path); + free (path); + if ((int) RETVAL < 0) + RETERR = sim_io_get_errno (simulator); + } + break; +#endif + +#ifdef HAVE_CHOWN +#ifdef TARGET_SYS_chown + case TARGET_SYS_chown: + { + char *path = fetch_str (simulator, PARM1); + RETVAL = chown (path, PARM2, PARM3); + free (path); + RETERR = errno; } break; +#endif +#endif - case SYS_chown: - RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3); +#if HAVE_CHMOD +#ifdef TARGET_SYS_chmod + case TARGET_SYS_chmod: + { + char *path = fetch_str (simulator, PARM1); + RETVAL = chmod (path, PARM2); + free (path); + RETERR = errno; + } break; #endif - case SYS_chmod: - RETVAL = chmod (MEMPTR (PARM1), PARM2); +#endif + +#ifdef TARGET_SYS_time +#if HAVE_TIME + case TARGET_SYS_time: + { + time_t now; + RETVAL = time (&now); + store_mem (PARM1, 4, now); + RETERR = errno; + } break; - case SYS_utime: - /* Cast the second argument to void *, to avoid type mismatch - if a prototype is present. */ - RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2)); +#endif +#endif + +#if !defined(__GO32__) && !defined(_WIN32) +#ifdef TARGET_SYS_times + case TARGET_SYS_times: + { + struct tms tms; + RETVAL = times (&tms); + store_mem (PARM1, 4, tms.tms_utime); + store_mem (PARM1 + 4, 4, tms.tms_stime); + store_mem (PARM1 + 8, 4, tms.tms_cutime); + store_mem (PARM1 + 12, 4, tms.tms_cstime); + reterr = errno; + break; + } +#endif +#endif + +#ifdef TARGET_SYS_gettimeofday +#if !defined(__GO32__) && !defined(_WIN32) + case TARGET_SYS_gettimeofday: + { + struct timeval t; + struct timezone tz; + RETVAL = gettimeofday (&t, &tz); + store_mem (PARM1, 4, t.tv_sec); + store_mem (PARM1 + 4, 4, t.tv_usec); + store_mem (PARM2, 4, tz.tz_minuteswest); + store_mem (PARM2 + 4, 4, tz.tz_dsttime); + RETERR = errno; + break; + } +#endif +#endif + +#ifdef TARGET_SYS_utime +#if HAVE_UTIME + case TARGET_SYS_utime: + { + /* Cast the second argument to void *, to avoid type mismatch + if a prototype is present. */ + sim_io_error (simulator, "Utime not supported"); + /* RETVAL = utime (path, (void *) MEMPTR (PARM2)); */ + } break; +#endif +#endif + default: abort (); } - RETERR = errno; errno = save_errno; + + return 4; } else { /* Trap 0 -> 30 */ - State.sregs[0] = PC + 4; /* EIPC */ - State.sregs[1] = State.sregs[5]; /* EIPSW */ - State.sregs[4] &= 0xffff0000; /* Mask out EICC */ - State.sregs[4] |= 0x40 + OP[0]; /* EICC */ - State.sregs[5] |= PSW_EP | PSW_ID; /* Now doing exception processing */ - PC = ((OP[0] < 0x10) ? 0x40 : 0x50) - 4; + EIPC = PC + 4; + EIPSW = PSW; + /* Mask out EICC */ + ECR &= 0xffff0000; + ECR |= 0x40 + OP[0]; + /* Flag that we are now doing exception processing. */ + PSW |= PSW_EP | PSW_ID; + PC = (OP[0] < 0x10) ? 0x40 : 0x50; + + return 0; } } -/* ldsr, reg,reg */ -void -OP_2007E0 () +/* tst1 reg2, [reg1] */ +int +OP_E607E0 (void) { - unsigned int op0; + int temp; - trace_input ("ldsr", OP_LDSR, 0); - op0 = State.regs[OP[0]]; - State.sregs[OP[1]] = op0; - trace_output (OP_LDSR); + trace_input ("tst1", OP_BIT, 1); + + temp = load_mem (State.regs[ OP[0] ], 1); + + PSW &= ~PSW_Z; + if ((temp & (1 << (State.regs[ OP[1] ] & 0x7))) == 0) + PSW |= PSW_Z; + + trace_output (OP_BIT); + + return 4; } -/* stsr, not supported */ -void -OP_4007E0 () +/* mulu reg1, reg2, reg3 */ +int +OP_22207E0 (void) { - unsigned int op0; + trace_input ("mulu", OP_REG_REG_REG, 0); + + Multiply64 (0, State.regs[ OP[0] ]); + + trace_output (OP_REG_REG_REG); - trace_input ("stsr", OP_STSR, 0); - op0 = State.sregs[OP[1]]; - State.regs[OP[0]] = op0; - trace_output (OP_STSR); + return 4; } + +#define BIT_CHANGE_OP( name, binop ) \ + unsigned int bit; \ + unsigned int temp; \ + \ + trace_input (name, OP_BIT_CHANGE, 0); \ + \ + bit = 1 << (State.regs[ OP[1] ] & 0x7); \ + temp = load_mem (State.regs[ OP[0] ], 1); \ + \ + PSW &= ~PSW_Z; \ + if ((temp & bit) == 0) \ + PSW |= PSW_Z; \ + temp binop bit; \ + \ + store_mem (State.regs[ OP[0] ], 1, temp); \ + \ + trace_output (OP_BIT_CHANGE); \ + \ + return 4; + +/* clr1 reg2, [reg1] */ +int +OP_E407E0 (void) +{ + BIT_CHANGE_OP ("clr1", &= ~ ); +} + +/* not1 reg2, [reg1] */ +int +OP_E207E0 (void) +{ + BIT_CHANGE_OP ("not1", ^= ); +} + +/* set1 */ +int +OP_E007E0 (void) +{ + BIT_CHANGE_OP ("set1", |= ); +} + +/* sasf */ +int +OP_20007E0 (void) +{ + trace_input ("sasf", OP_EX1, 0); + + State.regs[ OP[1] ] = (State.regs[ OP[1] ] << 1) | condition_met (OP[0]); + + trace_output (OP_EX1); + + return 4; +} + +/* This function is courtesy of Sugimoto at NEC, via Seow Tan + (Soew_Tan@el.nec.com) */ +void +divun +( + unsigned int N, + unsigned long int als, + unsigned long int sfi, + unsigned32 /*unsigned long int*/ * quotient_ptr, + unsigned32 /*unsigned long int*/ * remainder_ptr, + int * overflow_ptr +) +{ + unsigned long ald = sfi >> (N - 1); + unsigned long alo = als; + unsigned int Q = 1; + unsigned int C; + unsigned int S = 0; + unsigned int i; + unsigned int R1 = 1; + unsigned int DBZ = (als == 0) ? 1 : 0; + unsigned long alt = Q ? ~als : als; + + /* 1st Loop */ + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + C = C ^ Q; + Q = ~(C ^ S) & 1; + R1 = (alo == 0) ? 0 : (R1 & Q); + if ((S ^ (alo>>31)) && !C) + { + DBZ = 1; + } + S = alo >> 31; + sfi = (sfi << (32-N+1)) | Q; + ald = (alo << 1) | (sfi >> 31); + + /* 2nd - N-1th Loop */ + for (i = 2; i < N; i++) + { + alt = Q ? ~als : als; + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + C = C ^ Q; + Q = ~(C ^ S) & 1; + R1 = (alo == 0) ? 0 : (R1 & Q); + if ((S ^ (alo>>31)) && !C && !DBZ) + { + DBZ = 1; + } + S = alo >> 31; + sfi = (sfi << 1) | Q; + ald = (alo << 1) | (sfi >> 31); + } + + /* Nth Loop */ + alt = Q ? ~als : als; + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + C = C ^ Q; + Q = ~(C ^ S) & 1; + R1 = (alo == 0) ? 0 : (R1 & Q); + if ((S ^ (alo>>31)) && !C) + { + DBZ = 1; + } + + * quotient_ptr = (sfi << 1) | Q; + * remainder_ptr = Q ? alo : (alo + als); + * overflow_ptr = DBZ | R1; +} + +/* This function is courtesy of Sugimoto at NEC, via Seow Tan (Soew_Tan@el.nec.com) */ +void +divn +( + unsigned int N, + unsigned long int als, + unsigned long int sfi, + signed32 /*signed long int*/ * quotient_ptr, + signed32 /*signed long int*/ * remainder_ptr, + int * overflow_ptr +) +{ + unsigned long ald = (signed long) sfi >> (N - 1); + unsigned long alo = als; + unsigned int SS = als >> 31; + unsigned int SD = sfi >> 31; + unsigned int R1 = 1; + unsigned int OV; + unsigned int DBZ = als == 0 ? 1 : 0; + unsigned int Q = ~(SS ^ SD) & 1; + unsigned int C; + unsigned int S; + unsigned int i; + unsigned long alt = Q ? ~als : als; + + + /* 1st Loop */ + + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + Q = C ^ SS; + R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD))); + S = alo >> 31; + sfi = (sfi << (32-N+1)) | Q; + ald = (alo << 1) | (sfi >> 31); + if ((alo >> 31) ^ (ald >> 31)) + { + DBZ = 1; + } + + /* 2nd - N-1th Loop */ + + for (i = 2; i < N; i++) + { + alt = Q ? ~als : als; + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + Q = C ^ SS; + R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD))); + S = alo >> 31; + sfi = (sfi << 1) | Q; + ald = (alo << 1) | (sfi >> 31); + if ((alo >> 31) ^ (ald >> 31)) + { + DBZ = 1; + } + } + + /* Nth Loop */ + alt = Q ? ~als : als; + alo = ald + alt + Q; + C = (((alt >> 31) & (ald >> 31)) + | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31))); + Q = C ^ SS; + R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD))); + sfi = (sfi << (32-N+1)); + ald = alo; + + /* End */ + if (alo != 0) + { + alt = Q ? ~als : als; + alo = ald + alt + Q; + } + R1 = R1 & ((~alo >> 31) ^ SD); + if ((alo != 0) && ((Q ^ (SS ^ SD)) ^ R1)) alo = ald; + if (N != 32) + ald = sfi = (long) ((sfi >> 1) | (SS ^ SD) << 31) >> (32-N-1) | Q; + else + ald = sfi = sfi | Q; + + OV = DBZ | ((alo == 0) ? 0 : R1); + + * remainder_ptr = alo; + + /* Adj */ + if (((alo != 0) && ((SS ^ SD) ^ R1)) + || ((alo == 0) && (SS ^ R1))) + alo = ald + 1; + else + alo = ald; + + OV = (DBZ | R1) ? OV : ((alo >> 31) & (~ald >> 31)); + + * quotient_ptr = alo; + * overflow_ptr = OV; +} + +/* sdivun imm5, reg1, reg2, reg3 */ +int +OP_1C207E0 (void) +{ + unsigned32 /*unsigned long int*/ quotient; + unsigned32 /*unsigned long int*/ remainder; + unsigned long int divide_by; + unsigned long int divide_this; + int overflow = 0; + unsigned int imm5; + + trace_input ("sdivun", OP_IMM_REG_REG_REG, 0); + + imm5 = 32 - ((OP[3] & 0x3c0000) >> 17); + + divide_by = State.regs[ OP[0] ]; + divide_this = State.regs[ OP[1] ] << imm5; + + divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ OP[1] ] = quotient; + State.regs[ OP[2] >> 11 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); + + return 4; +} + +/* sdivn imm5, reg1, reg2, reg3 */ +int +OP_1C007E0 (void) +{ + signed32 /*signed long int*/ quotient; + signed32 /*signed long int*/ remainder; + signed long int divide_by; + signed long int divide_this; + int overflow = 0; + unsigned int imm5; + + trace_input ("sdivn", OP_IMM_REG_REG_REG, 0); + + imm5 = 32 - ((OP[3] & 0x3c0000) >> 17); + + divide_by = (signed32) State.regs[ OP[0] ]; + divide_this = (signed32) (State.regs[ OP[1] ] << imm5); + + divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ OP[1] ] = quotient; + State.regs[ OP[2] >> 11 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); + + return 4; +} + +/* sdivhun imm5, reg1, reg2, reg3 */ +int +OP_18207E0 (void) +{ + unsigned32 /*unsigned long int*/ quotient; + unsigned32 /*unsigned long int*/ remainder; + unsigned long int divide_by; + unsigned long int divide_this; + int overflow = 0; + unsigned int imm5; + + trace_input ("sdivhun", OP_IMM_REG_REG_REG, 0); + + imm5 = 32 - ((OP[3] & 0x3c0000) >> 17); + + divide_by = State.regs[ OP[0] ] & 0xffff; + divide_this = State.regs[ OP[1] ] << imm5; + + divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ OP[1] ] = quotient; + State.regs[ OP[2] >> 11 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); + + return 4; +} + +/* sdivhn imm5, reg1, reg2, reg3 */ +int +OP_18007E0 (void) +{ + signed32 /*signed long int*/ quotient; + signed32 /*signed long int*/ remainder; + signed long int divide_by; + signed long int divide_this; + int overflow = 0; + unsigned int imm5; + + trace_input ("sdivhn", OP_IMM_REG_REG_REG, 0); + + imm5 = 32 - ((OP[3] & 0x3c0000) >> 17); + + divide_by = EXTEND16 (State.regs[ OP[0] ]); + divide_this = (signed32) (State.regs[ OP[1] ] << imm5); + + divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ OP[1] ] = quotient; + State.regs[ OP[2] >> 11 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); + + return 4; +} + +/* divu reg1, reg2, reg3 */ +int +OP_2C207E0 (void) +{ + unsigned long int quotient; + unsigned long int remainder; + unsigned long int divide_by; + unsigned long int divide_this; + int overflow = 0; + + trace_input ("divu", OP_REG_REG_REG, 0); + + /* Compute the result. */ + + divide_by = State.regs[ OP[0] ]; + divide_this = State.regs[ OP[1] ]; + + if (divide_by == 0) + { + PSW |= PSW_OV; + } + else + { + State.regs[ OP[1] ] = quotient = divide_this / divide_by; + State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + } + + trace_output (OP_REG_REG_REG); + + return 4; +} + +/* div reg1, reg2, reg3 */ +int +OP_2C007E0 (void) +{ + signed long int quotient; + signed long int remainder; + signed long int divide_by; + signed long int divide_this; + + trace_input ("div", OP_REG_REG_REG, 0); + + /* Compute the result. */ + + divide_by = (signed32) State.regs[ OP[0] ]; + divide_this = State.regs[ OP[1] ]; + + if (divide_by == 0) + { + PSW |= PSW_OV; + } + else if (divide_by == -1 && divide_this == (1L << 31)) + { + PSW &= ~PSW_Z; + PSW |= PSW_OV | PSW_S; + State.regs[ OP[1] ] = (1 << 31); + State.regs[ OP[2] >> 11 ] = 0; + } + else + { + divide_this = (signed32) divide_this; + State.regs[ OP[1] ] = quotient = divide_this / divide_by; + State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + } + + trace_output (OP_REG_REG_REG); + + return 4; +} + +/* divhu reg1, reg2, reg3 */ +int +OP_28207E0 (void) +{ + unsigned long int quotient; + unsigned long int remainder; + unsigned long int divide_by; + unsigned long int divide_this; + int overflow = 0; + + trace_input ("divhu", OP_REG_REG_REG, 0); + + /* Compute the result. */ + + divide_by = State.regs[ OP[0] ] & 0xffff; + divide_this = State.regs[ OP[1] ]; + + if (divide_by == 0) + { + PSW |= PSW_OV; + } + else + { + State.regs[ OP[1] ] = quotient = divide_this / divide_by; + State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + } + + trace_output (OP_REG_REG_REG); + + return 4; +} + +/* divh reg1, reg2, reg3 */ +int +OP_28007E0 (void) +{ + signed long int quotient; + signed long int remainder; + signed long int divide_by; + signed long int divide_this; + int overflow = 0; + + trace_input ("divh", OP_REG_REG_REG, 0); + + /* Compute the result. */ + + divide_by = EXTEND16 (State.regs[ OP[0] ]); + divide_this = State.regs[ OP[1] ]; + + if (divide_by == 0) + { + PSW |= PSW_OV; + } + else if (divide_by == -1 && divide_this == (1L << 31)) + { + PSW &= ~PSW_Z; + PSW |= PSW_OV | PSW_S; + State.regs[ OP[1] ] = (1 << 31); + State.regs[ OP[2] >> 11 ] = 0; + } + else + { + divide_this = (signed32) divide_this; + State.regs[ OP[1] ] = quotient = divide_this / divide_by; + State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + } + + trace_output (OP_REG_REG_REG); + + return 4; +} + +/* mulu imm9, reg2, reg3 */ +int +OP_24207E0 (void) +{ + trace_input ("mulu", OP_IMM_REG_REG, 0); + + Multiply64 (0, (OP[3] & 0x1f) | ((OP[3] >> 13) & 0x1e0)); + + trace_output (OP_IMM_REG_REG); + + return 4; +} + +/* mul imm9, reg2, reg3 */ +int +OP_24007E0 (void) +{ + trace_input ("mul", OP_IMM_REG_REG, 0); + + Multiply64 (1, SEXT9 ((OP[3] & 0x1f) | ((OP[3] >> 13) & 0x1e0))); + + trace_output (OP_IMM_REG_REG); + + return 4; +} + +/* ld.hu */ +int +OP_107E0 (void) +{ + int adr; + + trace_input ("ld.hu", OP_LOAD32, 2); + + adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1); + adr &= ~0x1; + + State.regs[ OP[1] ] = load_mem (adr, 2); + + trace_output (OP_LOAD32); + + return 4; +} + + +/* ld.bu */ +int +OP_10780 (void) +{ + int adr; + + trace_input ("ld.bu", OP_LOAD32, 1); + + adr = (State.regs[ OP[0] ] + + (EXTEND16 (OP[2] & ~1) | ((OP[3] >> 5) & 1))); + + State.regs[ OP[1] ] = load_mem (adr, 1); + + trace_output (OP_LOAD32); + + return 4; +} + +/* prepare list12, imm5, imm32 */ +int +OP_1B0780 (void) +{ + int i; + + trace_input ("prepare", OP_PUSHPOP1, 0); + + /* Store the registers with lower number registers being placed at higher addresses. */ + for (i = 0; i < 12; i++) + if ((OP[3] & (1 << type1_regs[ i ]))) + { + SP -= 4; + store_mem (SP, 4, State.regs[ 20 + i ]); + } + + SP -= (OP[3] & 0x3e) << 1; + + EP = load_mem (PC + 4, 4); + + trace_output (OP_PUSHPOP1); + + return 8; +} + +/* prepare list12, imm5, imm16-32 */ +int +OP_130780 (void) +{ + int i; + + trace_input ("prepare", OP_PUSHPOP1, 0); + + /* Store the registers with lower number registers being placed at higher addresses. */ + for (i = 0; i < 12; i++) + if ((OP[3] & (1 << type1_regs[ i ]))) + { + SP -= 4; + store_mem (SP, 4, State.regs[ 20 + i ]); + } + + SP -= (OP[3] & 0x3e) << 1; + + EP = load_mem (PC + 4, 2) << 16; + + trace_output (OP_PUSHPOP1); + + return 6; +} + +/* prepare list12, imm5, imm16 */ +int +OP_B0780 (void) +{ + int i; + + trace_input ("prepare", OP_PUSHPOP1, 0); + + /* Store the registers with lower number registers being placed at higher addresses. */ + for (i = 0; i < 12; i++) + if ((OP[3] & (1 << type1_regs[ i ]))) + { + SP -= 4; + store_mem (SP, 4, State.regs[ 20 + i ]); + } + + SP -= (OP[3] & 0x3e) << 1; + + EP = EXTEND16 (load_mem (PC + 4, 2)); + + trace_output (OP_PUSHPOP1); + + return 6; +} + +/* prepare list12, imm5, sp */ +int +OP_30780 (void) +{ + int i; + + trace_input ("prepare", OP_PUSHPOP1, 0); + + /* Store the registers with lower number registers being placed at higher addresses. */ + for (i = 0; i < 12; i++) + if ((OP[3] & (1 << type1_regs[ i ]))) + { + SP -= 4; + store_mem (SP, 4, State.regs[ 20 + i ]); + } + + SP -= (OP[3] & 0x3e) << 1; + + EP = SP; + + trace_output (OP_PUSHPOP1); + + return 4; +} + +/* mul reg1, reg2, reg3 */ +int +OP_22007E0 (void) +{ + trace_input ("mul", OP_REG_REG_REG, 0); + + Multiply64 (1, State.regs[ OP[0] ]); + + trace_output (OP_REG_REG_REG); + + return 4; +} + +/* popmh list18 */ +int +OP_307F0 (void) +{ + int i; + + trace_input ("popmh", OP_PUSHPOP2, 0); + + if (OP[3] & (1 << 19)) + { + if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0)) + { + FEPSW = load_mem ( SP & ~ 3, 4); + FEPC = load_mem ((SP + 4) & ~ 3, 4); + } + else + { + EIPSW = load_mem ( SP & ~ 3, 4); + EIPC = load_mem ((SP + 4) & ~ 3, 4); + } + + SP += 8; + } + + /* Load the registers with lower number registers being retrieved from higher addresses. */ + for (i = 16; i--;) + if ((OP[3] & (1 << type2_regs[ i ]))) + { + State.regs[ i + 16 ] = load_mem (SP & ~ 3, 4); + SP += 4; + } + + trace_output (OP_PUSHPOP2); + + return 4; +} + +/* popml lsit18 */ +int +OP_107F0 (void) +{ + int i; + + trace_input ("popml", OP_PUSHPOP3, 0); + + if (OP[3] & (1 << 19)) + { + if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0)) + { + FEPSW = load_mem ( SP & ~ 3, 4); + FEPC = load_mem ((SP + 4) & ~ 3, 4); + } + else + { + EIPSW = load_mem ( SP & ~ 3, 4); + EIPC = load_mem ((SP + 4) & ~ 3, 4); + } + + SP += 8; + } + + if (OP[3] & (1 << 3)) + { + PSW = load_mem (SP & ~ 3, 4); + SP += 4; + } + + /* Load the registers with lower number registers being retrieved from higher addresses. */ + for (i = 15; i--;) + if ((OP[3] & (1 << type3_regs[ i ]))) + { + State.regs[ i + 1 ] = load_mem (SP & ~ 3, 4); + SP += 4; + } + + trace_output (OP_PUSHPOP2); + + return 4; +} + +/* pushmh list18 */ +int +OP_307E0 (void) +{ + int i; + + trace_input ("pushmh", OP_PUSHPOP2, 0); + + /* Store the registers with lower number registers being placed at higher addresses. */ + for (i = 0; i < 16; i++) + if ((OP[3] & (1 << type2_regs[ i ]))) + { + SP -= 4; + store_mem (SP & ~ 3, 4, State.regs[ i + 16 ]); + } + + if (OP[3] & (1 << 19)) + { + SP -= 8; + + if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0)) + { + store_mem ((SP + 4) & ~ 3, 4, FEPC); + store_mem ( SP & ~ 3, 4, FEPSW); + } + else + { + store_mem ((SP + 4) & ~ 3, 4, EIPC); + store_mem ( SP & ~ 3, 4, EIPSW); + } + } + + trace_output (OP_PUSHPOP2); + + return 4; +} + +/* V850E2R FPU functions */ +/* + sim_fpu_status_invalid_snan = 1, -V--- (sim spec.) + sim_fpu_status_invalid_qnan = 2, ----- (sim spec.) + sim_fpu_status_invalid_isi = 4, (inf - inf) -V--- + sim_fpu_status_invalid_idi = 8, (inf / inf) -V--- + sim_fpu_status_invalid_zdz = 16, (0 / 0) -V--- + sim_fpu_status_invalid_imz = 32, (inf * 0) -V--- + sim_fpu_status_invalid_cvi = 64, convert to integer -V--- + sim_fpu_status_invalid_div0 = 128, (X / 0) --Z-- + sim_fpu_status_invalid_cmp = 256, compare ----- (sim spec.) + sim_fpu_status_invalid_sqrt = 512, -V--- + sim_fpu_status_rounded = 1024, I---- + sim_fpu_status_inexact = 2048, I---- (sim spec.) + sim_fpu_status_overflow = 4096, I--O- + sim_fpu_status_underflow = 8192, I---U + sim_fpu_status_denorm = 16384, ----U (sim spec.) +*/ + +void +update_fpsr (SIM_DESC sd, sim_fpu_status status, unsigned int mask, unsigned int double_op_p) +{ + unsigned int fpsr = FPSR & mask; + + unsigned int flags = 0; + + if (fpsr & FPSR_XEI + && ((status & (sim_fpu_status_rounded + | sim_fpu_status_overflow + | sim_fpu_status_inexact)) + || (status & sim_fpu_status_underflow + && (fpsr & (FPSR_XEU | FPSR_XEI)) == 0 + && fpsr & FPSR_FS))) + { + flags |= FPSR_XCI | FPSR_XPI; + } + + if (fpsr & FPSR_XEV + && (status & (sim_fpu_status_invalid_isi + | sim_fpu_status_invalid_imz + | sim_fpu_status_invalid_zdz + | sim_fpu_status_invalid_idi + | sim_fpu_status_invalid_cvi + | sim_fpu_status_invalid_sqrt + | sim_fpu_status_invalid_snan))) + { + flags |= FPSR_XCV | FPSR_XPV; + } + + if (fpsr & FPSR_XEZ + && (status & sim_fpu_status_invalid_div0)) + { + flags |= FPSR_XCV | FPSR_XPV; + } + + if (fpsr & FPSR_XEO + && (status & sim_fpu_status_overflow)) + { + flags |= FPSR_XCO | FPSR_XPO; + } + + if (((fpsr & FPSR_XEU) || (fpsr & FPSR_FS) == 0) + && (status & (sim_fpu_status_underflow + | sim_fpu_status_denorm))) + { + flags |= FPSR_XCU | FPSR_XPU; + } + + if (flags) + { + FPSR &= ~FPSR_XC; + FPSR |= flags; + + SignalExceptionFPE (sd, double_op_p); + } +} + +/* Exception. */ + +void +SignalException (SIM_DESC sd) +{ + if (MPM & MPM_AUE) + { + PSW = PSW & ~(PSW_NPV | PSW_DMP | PSW_IMP); + } +} + +void +SignalExceptionFPE (SIM_DESC sd, unsigned int double_op_p) +{ + if (((PSW & (PSW_NP|PSW_ID)) == 0) + || !(FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM))) + { + EIPC = PC; + EIPSW = PSW; + EIIC = (FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM)) + ? 0x71 : 0x72; + PSW |= (PSW_EP | PSW_ID); + PC = 0x70; + + SignalException (sd); + } +} + +void +check_invalid_snan (SIM_DESC sd, sim_fpu_status status, unsigned int double_op_p) +{ + if ((FPSR & FPSR_XEI) + && (status & sim_fpu_status_invalid_snan)) + { + FPSR &= ~FPSR_XC; + FPSR |= FPSR_XCV; + FPSR |= FPSR_XPV; + SignalExceptionFPE (sd, double_op_p); + } +} + +int +v850_float_compare (SIM_DESC sd, int cmp, sim_fpu wop1, sim_fpu wop2, int double_op_p) +{ + int result = -1; + + if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2)) + { + if (cmp & 0x8) + { + if (FPSR & FPSR_XEV) + { + FPSR |= FPSR_XCV | FPSR_XPV; + SignalExceptionFPE (sd, double_op_p); + } + } + + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 1; + break; + case FPU_CMP_EQ: + result = 0; + break; + case FPU_CMP_UEQ: + result = 1; + break; + case FPU_CMP_OLT: + result = 0; + break; + case FPU_CMP_ULT: + result = 1; + break; + case FPU_CMP_OLE: + result = 0; + break; + case FPU_CMP_ULE: + result = 1; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 1; + break; + case FPU_CMP_SEQ: + result = 0; + break; + case FPU_CMP_NGL: + result = 1; + break; + case FPU_CMP_LT: + result = 0; + break; + case FPU_CMP_NGE: + result = 1; + break; + case FPU_CMP_LE: + result = 0; + break; + case FPU_CMP_NGT: + result = 1; + break; + default: + abort (); + } + } + else if (sim_fpu_is_infinity (&wop1) && sim_fpu_is_infinity (&wop2) + && sim_fpu_sign (&wop1) == sim_fpu_sign (&wop2)) + { + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 0; + break; + case FPU_CMP_EQ: + result = 1; + break; + case FPU_CMP_UEQ: + result = 1; + break; + case FPU_CMP_OLT: + result = 0; + break; + case FPU_CMP_ULT: + result = 0; + break; + case FPU_CMP_OLE: + result = 1; + break; + case FPU_CMP_ULE: + result = 1; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 0; + break; + case FPU_CMP_SEQ: + result = 1; + break; + case FPU_CMP_NGL: + result = 1; + break; + case FPU_CMP_LT: + result = 0; + break; + case FPU_CMP_NGE: + result = 0; + break; + case FPU_CMP_LE: + result = 1; + break; + case FPU_CMP_NGT: + result = 1; + break; + default: + abort (); + } + } + else + { + int gt = 0,lt = 0,eq = 0, status; + + status = sim_fpu_cmp (&wop1, &wop2); + + switch (status) + { + case SIM_FPU_IS_SNAN: + case SIM_FPU_IS_QNAN: + abort (); + break; + + case SIM_FPU_IS_NINF: + lt = 1; + break; + case SIM_FPU_IS_PINF: + gt = 1; + break; + case SIM_FPU_IS_NNUMBER: + lt = 1; + break; + case SIM_FPU_IS_PNUMBER: + gt = 1; + break; + case SIM_FPU_IS_NDENORM: + lt = 1; + break; + case SIM_FPU_IS_PDENORM: + gt = 1; + break; + case SIM_FPU_IS_NZERO: + case SIM_FPU_IS_PZERO: + eq = 1; + break; + } + + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 0; + break; + case FPU_CMP_EQ: + result = eq; + break; + case FPU_CMP_UEQ: + result = eq; + break; + case FPU_CMP_OLT: + result = lt; + break; + case FPU_CMP_ULT: + result = lt; + break; + case FPU_CMP_OLE: + result = lt || eq; + break; + case FPU_CMP_ULE: + result = lt || eq; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 0; + break; + case FPU_CMP_SEQ: + result = eq; + break; + case FPU_CMP_NGL: + result = eq; + break; + case FPU_CMP_LT: + result = lt; + break; + case FPU_CMP_NGE: + result = lt; + break; + case FPU_CMP_LE: + result = lt || eq; + break; + case FPU_CMP_NGT: + result = lt || eq; + break; + } + } + + ASSERT (result != -1); + return result; +} + +void +v850_div (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p) +{ + signed long int quotient; + signed long int remainder; + signed long int divide_by; + signed long int divide_this; + bfd_boolean overflow = FALSE; + + /* Compute the result. */ + divide_by = op0; + divide_this = op1; + + if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31))) + { + overflow = TRUE; + divide_by = 1; + } + + quotient = divide_this / divide_by; + remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + *op2p = quotient; + *op3p = remainder; +} + +void +v850_divu (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p) +{ + unsigned long int quotient; + unsigned long int remainder; + unsigned long int divide_by; + unsigned long int divide_this; + bfd_boolean overflow = FALSE; + + /* Compute the result. */ + + divide_by = op0; + divide_this = op1; + + if (divide_by == 0) + { + overflow = TRUE; + divide_by = 1; + } + + quotient = divide_this / divide_by; + remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + *op2p = quotient; + *op3p = remainder; +} + +void +v850_sar (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = (signed)op1 >> op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (op0 - 1))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void +v850_shl (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = op1 << op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (32 - op0))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void +v850_rotl (SIM_DESC sd, unsigned int amount, unsigned int src, unsigned int * dest) +{ + unsigned int result, z, s, cy; + + amount &= 0x1f; + result = src << amount; + result |= src >> (32 - amount); + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = ! (result & 1); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + * dest = result; +} + +void +v850_bins (SIM_DESC sd, unsigned int source, unsigned int lsb, unsigned int msb, + unsigned int * dest) +{ + unsigned int mask; + unsigned int result, pos, width; + unsigned int z, s; + + pos = lsb; + width = (msb - lsb) + 1; + + mask = ~ (-(1 << width)); + source &= mask; + mask <<= pos; + result = (* dest) & ~ mask; + result |= source << pos; + + /* Compute the condition codes. */ + z = (result == 0); + s = result & 0x80000000; + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV ); + PSW |= (z ? PSW_Z : 0) | (s ? PSW_S : 0); + + * dest = result; +} + +void +v850_shr (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = op1 >> op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (op0 - 1))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void +v850_satadd (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy, ov, sat; + + result = op0 + op1; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (result < op0 || result < op1); + ov = ((op0 & 0x80000000) == (op1 & 0x80000000) + && (op0 & 0x80000000) != (result & 0x80000000)); + sat = ov; + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + + /* Handle saturated results. */ + if (sat && s) + { + result = 0x7fffffff; + PSW &= ~PSW_S; + } + else if (sat) + { + result = 0x80000000; + PSW |= PSW_S; + } + + *op2p = result; +} + +void +v850_satsub (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy, ov, sat; + + /* Compute the result. */ + result = op1 - op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 < op0); + ov = ((op1 & 0x80000000) != (op0 & 0x80000000) + && (op1 & 0x80000000) != (result & 0x80000000)); + sat = ov; + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + + /* Handle saturated results. */ + if (sat && s) + { + result = 0x7fffffff; + PSW &= ~PSW_S; + } + else if (sat) + { + result = 0x80000000; + PSW |= PSW_S; + } + + *op2p = result; +} + +unsigned32 +load_data_mem (SIM_DESC sd, + SIM_ADDR addr, + int len) +{ + uint32 data; + + switch (len) + { + case 1: + data = sim_core_read_unaligned_1 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + case 2: + data = sim_core_read_unaligned_2 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + case 4: + data = sim_core_read_unaligned_4 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + default: + abort (); + } + return data; +} + +void +store_data_mem (SIM_DESC sd, + SIM_ADDR addr, + int len, + unsigned32 data) +{ + switch (len) + { + case 1: + store_mem (addr, 1, data); + break; + case 2: + store_mem (addr, 2, data); + break; + case 4: + store_mem (addr, 4, data); + break; + default: + abort (); + } +} + +int +mpu_load_mem_test (SIM_DESC sd, unsigned int addr, int size, int base_reg) +{ + int result = 1; + + if (PSW & PSW_DMP) + { + if (IPE0 && addr >= IPA2ADDR (IPA0L) && addr <= IPA2ADDR (IPA0L) && IPR0) + { + /* text area */ + } + else if (IPE1 && addr >= IPA2ADDR (IPA1L) && addr <= IPA2ADDR (IPA1L) && IPR1) + { + /* text area */ + } + else if (IPE2 && addr >= IPA2ADDR (IPA2L) && addr <= IPA2ADDR (IPA2L) && IPR2) + { + /* text area */ + } + else if (IPE3 && addr >= IPA2ADDR (IPA3L) && addr <= IPA2ADDR (IPA3L) && IPR3) + { + /* text area */ + } + else if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM)) + { + /* preifarallel area */ + } + else if (addr >= PPA2ADDR (SPAL) && addr <= DPA2ADDR (SPAU)) + { + /* stack area */ + } + else if (DPE0 && addr >= DPA2ADDR (DPA0L) && addr <= DPA2ADDR (DPA0L) && DPR0 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE1 && addr >= DPA2ADDR (DPA1L) && addr <= DPA2ADDR (DPA1L) && DPR1 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE2 && addr >= DPA2ADDR (DPA2L) && addr <= DPA2ADDR (DPA2L) && DPR2 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE3 && addr >= DPA2ADDR (DPA3L) && addr <= DPA2ADDR (DPA3L) && DPR3 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else + { + VMECR &= ~(VMECR_VMW | VMECR_VMX); + VMECR |= VMECR_VMR; + VMADR = addr; + VMTID = TID; + FEIC = 0x431; + + PC = 0x30; + + SignalException (sd); + result = 0; + } + } + + return result; +} + +int +mpu_store_mem_test (SIM_DESC sd, unsigned int addr, int size, int base_reg) +{ + int result = 1; + + if (PSW & PSW_DMP) + { + if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM)) + { + /* preifarallel area */ + } + else if (addr >= PPA2ADDR (SPAL) && addr <= DPA2ADDR (SPAU)) + { + /* stack area */ + } + else if (DPE0 && addr >= DPA2ADDR (DPA0L) && addr <= DPA2ADDR (DPA0L) && DPW0 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE1 && addr >= DPA2ADDR (DPA1L) && addr <= DPA2ADDR (DPA1L) && DPW1 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE2 && addr >= DPA2ADDR (DPA2L) && addr <= DPA2ADDR (DPA2L) && DPW2 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE3 && addr >= DPA2ADDR (DPA3L) && addr <= DPA2ADDR (DPA3L) && DPW3 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else + { + if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM)) + { + FEIC = 0x432; + VPTID = TID; + VPADR = PC; +#ifdef NOT_YET + VIP_PP; + VPECR; +#endif + } + else + { + FEIC = 0x431; + VMTID = TID; + VMADR = VMECR; + VMECR &= ~(VMECR_VMW | VMECR_VMX); + VMECR |= VMECR_VMR; + PC = 0x30; + } + result = 0; + } + } + + return result; +} +