166e63ce3Schristos #include "sim-main.h"
266e63ce3Schristos #include "v850_sim.h"
366e63ce3Schristos #include "simops.h"
466e63ce3Schristos
566e63ce3Schristos #include <sys/types.h>
666e63ce3Schristos
766e63ce3Schristos #ifdef HAVE_UTIME_H
866e63ce3Schristos #include <utime.h>
966e63ce3Schristos #endif
1066e63ce3Schristos
1166e63ce3Schristos #ifdef HAVE_TIME_H
1266e63ce3Schristos #include <time.h>
1366e63ce3Schristos #endif
1466e63ce3Schristos
1566e63ce3Schristos #ifdef HAVE_UNISTD_H
1666e63ce3Schristos #include <unistd.h>
1766e63ce3Schristos #endif
1866e63ce3Schristos
1966e63ce3Schristos #ifdef HAVE_STRING_H
2066e63ce3Schristos #include <string.h>
2166e63ce3Schristos #else
2266e63ce3Schristos #ifdef HAVE_STRINGS_H
2366e63ce3Schristos #include <strings.h>
2466e63ce3Schristos #endif
2566e63ce3Schristos #endif
2666e63ce3Schristos
2766e63ce3Schristos #include "targ-vals.h"
2866e63ce3Schristos
2966e63ce3Schristos #include "libiberty.h"
3066e63ce3Schristos
3166e63ce3Schristos #include <errno.h>
3266e63ce3Schristos #if !defined(__GO32__) && !defined(_WIN32)
3366e63ce3Schristos #include <sys/stat.h>
3466e63ce3Schristos #include <sys/times.h>
3566e63ce3Schristos #include <sys/time.h>
3666e63ce3Schristos #endif
3766e63ce3Schristos
3866e63ce3Schristos /* This is an array of the bit positions of registers r20 .. r31 in
3966e63ce3Schristos that order in a prepare/dispose instruction. */
4066e63ce3Schristos int type1_regs[12] = { 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 0, 21 };
4166e63ce3Schristos /* This is an array of the bit positions of registers r16 .. r31 in
4266e63ce3Schristos that order in a push/pop instruction. */
4366e63ce3Schristos int type2_regs[16] = { 3, 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21};
4466e63ce3Schristos /* This is an array of the bit positions of registers r1 .. r15 in
4566e63ce3Schristos that order in a push/pop instruction. */
4666e63ce3Schristos int type3_regs[15] = { 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21};
4766e63ce3Schristos
4866e63ce3Schristos #ifdef DEBUG
4966e63ce3Schristos #ifndef SIZE_INSTRUCTION
5066e63ce3Schristos #define SIZE_INSTRUCTION 18
5166e63ce3Schristos #endif
5266e63ce3Schristos
5366e63ce3Schristos #ifndef SIZE_VALUES
5466e63ce3Schristos #define SIZE_VALUES 11
5566e63ce3Schristos #endif
5666e63ce3Schristos
5766e63ce3Schristos
5866e63ce3Schristos unsigned32 trace_values[3];
5966e63ce3Schristos int trace_num_values;
6066e63ce3Schristos unsigned32 trace_pc;
6166e63ce3Schristos const char * trace_name;
6266e63ce3Schristos int trace_module;
6366e63ce3Schristos
6466e63ce3Schristos
6566e63ce3Schristos void
trace_input(char * name,enum op_types type,int size)66ed6a76a9Schristos trace_input (char *name, enum op_types type, int size)
6766e63ce3Schristos {
6866e63ce3Schristos if (!TRACE_ALU_P (STATE_CPU (simulator, 0)))
6966e63ce3Schristos return;
7066e63ce3Schristos
7166e63ce3Schristos trace_pc = PC;
7266e63ce3Schristos trace_name = name;
7366e63ce3Schristos trace_module = TRACE_ALU_IDX;
7466e63ce3Schristos
7566e63ce3Schristos switch (type)
7666e63ce3Schristos {
7766e63ce3Schristos default:
7866e63ce3Schristos case OP_UNKNOWN:
7966e63ce3Schristos case OP_NONE:
8066e63ce3Schristos case OP_TRAP:
8166e63ce3Schristos trace_num_values = 0;
8266e63ce3Schristos break;
8366e63ce3Schristos
8466e63ce3Schristos case OP_REG:
8566e63ce3Schristos case OP_REG_REG_MOVE:
8666e63ce3Schristos trace_values[0] = State.regs[OP[0]];
8766e63ce3Schristos trace_num_values = 1;
8866e63ce3Schristos break;
8966e63ce3Schristos
9066e63ce3Schristos case OP_BIT_CHANGE:
9166e63ce3Schristos case OP_REG_REG:
9266e63ce3Schristos case OP_REG_REG_CMP:
9366e63ce3Schristos trace_values[0] = State.regs[OP[1]];
9466e63ce3Schristos trace_values[1] = State.regs[OP[0]];
9566e63ce3Schristos trace_num_values = 2;
9666e63ce3Schristos break;
9766e63ce3Schristos
9866e63ce3Schristos case OP_IMM_REG:
9966e63ce3Schristos case OP_IMM_REG_CMP:
10066e63ce3Schristos trace_values[0] = SEXT5 (OP[0]);
10166e63ce3Schristos trace_values[1] = OP[1];
10266e63ce3Schristos trace_num_values = 2;
10366e63ce3Schristos break;
10466e63ce3Schristos
10566e63ce3Schristos case OP_IMM_REG_MOVE:
10666e63ce3Schristos trace_values[0] = SEXT5 (OP[0]);
10766e63ce3Schristos trace_num_values = 1;
10866e63ce3Schristos break;
10966e63ce3Schristos
11066e63ce3Schristos case OP_COND_BR:
11166e63ce3Schristos trace_values[0] = State.pc;
11266e63ce3Schristos trace_values[1] = SEXT9 (OP[0]);
11366e63ce3Schristos trace_values[2] = PSW;
11466e63ce3Schristos trace_num_values = 3;
11566e63ce3Schristos break;
11666e63ce3Schristos
11766e63ce3Schristos case OP_LOAD16:
11866e63ce3Schristos trace_values[0] = OP[1] * size;
11966e63ce3Schristos trace_values[1] = State.regs[30];
12066e63ce3Schristos trace_num_values = 2;
12166e63ce3Schristos break;
12266e63ce3Schristos
12366e63ce3Schristos case OP_STORE16:
12466e63ce3Schristos trace_values[0] = State.regs[OP[0]];
12566e63ce3Schristos trace_values[1] = OP[1] * size;
12666e63ce3Schristos trace_values[2] = State.regs[30];
12766e63ce3Schristos trace_num_values = 3;
12866e63ce3Schristos break;
12966e63ce3Schristos
13066e63ce3Schristos case OP_LOAD32:
13166e63ce3Schristos trace_values[0] = EXTEND16 (OP[2]);
13266e63ce3Schristos trace_values[1] = State.regs[OP[0]];
13366e63ce3Schristos trace_num_values = 2;
13466e63ce3Schristos break;
13566e63ce3Schristos
13666e63ce3Schristos case OP_STORE32:
13766e63ce3Schristos trace_values[0] = State.regs[OP[1]];
13866e63ce3Schristos trace_values[1] = EXTEND16 (OP[2]);
13966e63ce3Schristos trace_values[2] = State.regs[OP[0]];
14066e63ce3Schristos trace_num_values = 3;
14166e63ce3Schristos break;
14266e63ce3Schristos
14366e63ce3Schristos case OP_JUMP:
14466e63ce3Schristos trace_values[0] = SEXT22 (OP[0]);
14566e63ce3Schristos trace_values[1] = State.pc;
14666e63ce3Schristos trace_num_values = 2;
14766e63ce3Schristos break;
14866e63ce3Schristos
14966e63ce3Schristos case OP_IMM_REG_REG:
15066e63ce3Schristos trace_values[0] = EXTEND16 (OP[0]) << size;
15166e63ce3Schristos trace_values[1] = State.regs[OP[1]];
15266e63ce3Schristos trace_num_values = 2;
15366e63ce3Schristos break;
15466e63ce3Schristos
15566e63ce3Schristos case OP_IMM16_REG_REG:
15666e63ce3Schristos trace_values[0] = EXTEND16 (OP[2]) << size;
15766e63ce3Schristos trace_values[1] = State.regs[OP[1]];
15866e63ce3Schristos trace_num_values = 2;
15966e63ce3Schristos break;
16066e63ce3Schristos
16166e63ce3Schristos case OP_UIMM_REG_REG:
16266e63ce3Schristos trace_values[0] = (OP[0] & 0xffff) << size;
16366e63ce3Schristos trace_values[1] = State.regs[OP[1]];
16466e63ce3Schristos trace_num_values = 2;
16566e63ce3Schristos break;
16666e63ce3Schristos
16766e63ce3Schristos case OP_UIMM16_REG_REG:
16866e63ce3Schristos trace_values[0] = (OP[2]) << size;
16966e63ce3Schristos trace_values[1] = State.regs[OP[1]];
17066e63ce3Schristos trace_num_values = 2;
17166e63ce3Schristos break;
17266e63ce3Schristos
17366e63ce3Schristos case OP_BIT:
17466e63ce3Schristos trace_num_values = 0;
17566e63ce3Schristos break;
17666e63ce3Schristos
17766e63ce3Schristos case OP_EX1:
17866e63ce3Schristos trace_values[0] = PSW;
17966e63ce3Schristos trace_num_values = 1;
18066e63ce3Schristos break;
18166e63ce3Schristos
18266e63ce3Schristos case OP_EX2:
18366e63ce3Schristos trace_num_values = 0;
18466e63ce3Schristos break;
18566e63ce3Schristos
18666e63ce3Schristos case OP_LDSR:
18766e63ce3Schristos trace_values[0] = State.regs[OP[0]];
18866e63ce3Schristos trace_num_values = 1;
18966e63ce3Schristos break;
19066e63ce3Schristos
19166e63ce3Schristos case OP_STSR:
19266e63ce3Schristos trace_values[0] = State.sregs[OP[1]];
19366e63ce3Schristos trace_num_values = 1;
19466e63ce3Schristos }
19566e63ce3Schristos
19666e63ce3Schristos }
19766e63ce3Schristos
19866e63ce3Schristos void
trace_result(int has_result,unsigned32 result)19966e63ce3Schristos trace_result (int has_result, unsigned32 result)
20066e63ce3Schristos {
20166e63ce3Schristos char buf[1000];
20266e63ce3Schristos char *chp;
20366e63ce3Schristos
20466e63ce3Schristos buf[0] = '\0';
20566e63ce3Schristos chp = buf;
20666e63ce3Schristos
20766e63ce3Schristos /* write out the values saved during the trace_input call */
20866e63ce3Schristos {
20966e63ce3Schristos int i;
21066e63ce3Schristos for (i = 0; i < trace_num_values; i++)
21166e63ce3Schristos {
21266e63ce3Schristos sprintf (chp, "%*s0x%.8lx", SIZE_VALUES - 10, "",
21366e63ce3Schristos (long) trace_values[i]);
21466e63ce3Schristos chp = strchr (chp, '\0');
21566e63ce3Schristos }
21666e63ce3Schristos while (i++ < 3)
21766e63ce3Schristos {
21866e63ce3Schristos sprintf (chp, "%*s", SIZE_VALUES, "");
21966e63ce3Schristos chp = strchr (chp, '\0');
22066e63ce3Schristos }
22166e63ce3Schristos }
22266e63ce3Schristos
22366e63ce3Schristos /* append any result to the end of the buffer */
22466e63ce3Schristos if (has_result)
22566e63ce3Schristos sprintf (chp, " :: 0x%.8lx", (unsigned long) result);
22666e63ce3Schristos
227ed6a76a9Schristos trace_generic (simulator, STATE_CPU (simulator, 0), trace_module, "%s", buf);
22866e63ce3Schristos }
22966e63ce3Schristos
23066e63ce3Schristos void
trace_output(enum op_types result)231ed6a76a9Schristos trace_output (enum op_types result)
23266e63ce3Schristos {
23366e63ce3Schristos if (!TRACE_ALU_P (STATE_CPU (simulator, 0)))
23466e63ce3Schristos return;
23566e63ce3Schristos
23666e63ce3Schristos switch (result)
23766e63ce3Schristos {
23866e63ce3Schristos default:
23966e63ce3Schristos case OP_UNKNOWN:
24066e63ce3Schristos case OP_NONE:
24166e63ce3Schristos case OP_TRAP:
24266e63ce3Schristos case OP_REG:
24366e63ce3Schristos case OP_REG_REG_CMP:
24466e63ce3Schristos case OP_IMM_REG_CMP:
24566e63ce3Schristos case OP_COND_BR:
24666e63ce3Schristos case OP_STORE16:
24766e63ce3Schristos case OP_STORE32:
24866e63ce3Schristos case OP_BIT:
24966e63ce3Schristos case OP_EX2:
25066e63ce3Schristos trace_result (0, 0);
25166e63ce3Schristos break;
25266e63ce3Schristos
25366e63ce3Schristos case OP_LOAD16:
25466e63ce3Schristos case OP_STSR:
25566e63ce3Schristos trace_result (1, State.regs[OP[0]]);
25666e63ce3Schristos break;
25766e63ce3Schristos
25866e63ce3Schristos case OP_REG_REG:
25966e63ce3Schristos case OP_REG_REG_MOVE:
26066e63ce3Schristos case OP_IMM_REG:
26166e63ce3Schristos case OP_IMM_REG_MOVE:
26266e63ce3Schristos case OP_LOAD32:
26366e63ce3Schristos case OP_EX1:
26466e63ce3Schristos trace_result (1, State.regs[OP[1]]);
26566e63ce3Schristos break;
26666e63ce3Schristos
26766e63ce3Schristos case OP_IMM_REG_REG:
26866e63ce3Schristos case OP_UIMM_REG_REG:
26966e63ce3Schristos case OP_IMM16_REG_REG:
27066e63ce3Schristos case OP_UIMM16_REG_REG:
27166e63ce3Schristos trace_result (1, State.regs[OP[1]]);
27266e63ce3Schristos break;
27366e63ce3Schristos
27466e63ce3Schristos case OP_JUMP:
27566e63ce3Schristos if (OP[1] != 0)
27666e63ce3Schristos trace_result (1, State.regs[OP[1]]);
27766e63ce3Schristos else
27866e63ce3Schristos trace_result (0, 0);
27966e63ce3Schristos break;
28066e63ce3Schristos
28166e63ce3Schristos case OP_LDSR:
28266e63ce3Schristos trace_result (1, State.sregs[OP[1]]);
28366e63ce3Schristos break;
28466e63ce3Schristos }
28566e63ce3Schristos }
28666e63ce3Schristos #endif
28766e63ce3Schristos
28866e63ce3Schristos
28966e63ce3Schristos /* Returns 1 if the specific condition is met, returns 0 otherwise. */
29066e63ce3Schristos int
condition_met(unsigned code)29166e63ce3Schristos condition_met (unsigned code)
29266e63ce3Schristos {
29366e63ce3Schristos unsigned int psw = PSW;
29466e63ce3Schristos
29566e63ce3Schristos switch (code & 0xf)
29666e63ce3Schristos {
29766e63ce3Schristos case 0x0: return ((psw & PSW_OV) != 0);
29866e63ce3Schristos case 0x1: return ((psw & PSW_CY) != 0);
29966e63ce3Schristos case 0x2: return ((psw & PSW_Z) != 0);
30066e63ce3Schristos case 0x3: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) != 0);
30166e63ce3Schristos case 0x4: return ((psw & PSW_S) != 0);
30266e63ce3Schristos /*case 0x5: return 1;*/
30366e63ce3Schristos case 0x6: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) != 0);
30466e63ce3Schristos case 0x7: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) != 0);
30566e63ce3Schristos case 0x8: return ((psw & PSW_OV) == 0);
30666e63ce3Schristos case 0x9: return ((psw & PSW_CY) == 0);
30766e63ce3Schristos case 0xa: return ((psw & PSW_Z) == 0);
30866e63ce3Schristos case 0xb: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) == 0);
30966e63ce3Schristos case 0xc: return ((psw & PSW_S) == 0);
31066e63ce3Schristos case 0xd: return ((psw & PSW_SAT) != 0);
31166e63ce3Schristos case 0xe: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) == 0);
31266e63ce3Schristos case 0xf: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) == 0);
31366e63ce3Schristos }
31466e63ce3Schristos
31566e63ce3Schristos return 1;
31666e63ce3Schristos }
31766e63ce3Schristos
31848596154Schristos unsigned long
Add32(unsigned long a1,unsigned long a2,int * carry)31966e63ce3Schristos Add32 (unsigned long a1, unsigned long a2, int * carry)
32066e63ce3Schristos {
32166e63ce3Schristos unsigned long result = (a1 + a2);
32266e63ce3Schristos
32366e63ce3Schristos * carry = (result < a1);
32466e63ce3Schristos
32566e63ce3Schristos return result;
32666e63ce3Schristos }
32766e63ce3Schristos
32866e63ce3Schristos static void
Multiply64(int sign,unsigned long op0)32966e63ce3Schristos Multiply64 (int sign, unsigned long op0)
33066e63ce3Schristos {
33166e63ce3Schristos unsigned long op1;
33266e63ce3Schristos unsigned long lo;
33366e63ce3Schristos unsigned long mid1;
33466e63ce3Schristos unsigned long mid2;
33566e63ce3Schristos unsigned long hi;
33666e63ce3Schristos unsigned long RdLo;
33766e63ce3Schristos unsigned long RdHi;
33866e63ce3Schristos int carry;
33966e63ce3Schristos
34066e63ce3Schristos op1 = State.regs[ OP[1] ];
34166e63ce3Schristos
34266e63ce3Schristos if (sign)
34366e63ce3Schristos {
34466e63ce3Schristos /* Compute sign of result and adjust operands if necessary. */
34566e63ce3Schristos
34666e63ce3Schristos sign = (op0 ^ op1) & 0x80000000;
34766e63ce3Schristos
34866e63ce3Schristos if (((signed long) op0) < 0)
34966e63ce3Schristos op0 = - op0;
35066e63ce3Schristos
35166e63ce3Schristos if (((signed long) op1) < 0)
35266e63ce3Schristos op1 = - op1;
35366e63ce3Schristos }
35466e63ce3Schristos
35566e63ce3Schristos /* We can split the 32x32 into four 16x16 operations. This ensures
35666e63ce3Schristos that we do not lose precision on 32bit only hosts: */
35766e63ce3Schristos lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF));
35866e63ce3Schristos mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
35966e63ce3Schristos mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF));
36066e63ce3Schristos hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
36166e63ce3Schristos
36266e63ce3Schristos /* We now need to add all of these results together, taking care
36366e63ce3Schristos to propogate the carries from the additions: */
36466e63ce3Schristos RdLo = Add32 (lo, (mid1 << 16), & carry);
36566e63ce3Schristos RdHi = carry;
36666e63ce3Schristos RdLo = Add32 (RdLo, (mid2 << 16), & carry);
36766e63ce3Schristos RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
36866e63ce3Schristos
36966e63ce3Schristos if (sign)
37066e63ce3Schristos {
37166e63ce3Schristos /* Negate result if necessary. */
37266e63ce3Schristos
37366e63ce3Schristos RdLo = ~ RdLo;
37466e63ce3Schristos RdHi = ~ RdHi;
37566e63ce3Schristos if (RdLo == 0xFFFFFFFF)
37666e63ce3Schristos {
37766e63ce3Schristos RdLo = 0;
37866e63ce3Schristos RdHi += 1;
37966e63ce3Schristos }
38066e63ce3Schristos else
38166e63ce3Schristos RdLo += 1;
38266e63ce3Schristos }
38366e63ce3Schristos
38466e63ce3Schristos /* Don't store into register 0. */
38566e63ce3Schristos if (OP[1])
38666e63ce3Schristos State.regs[ OP[1] ] = RdLo;
38766e63ce3Schristos if (OP[2] >> 11)
38866e63ce3Schristos State.regs[ OP[2] >> 11 ] = RdHi;
38966e63ce3Schristos
39066e63ce3Schristos return;
39166e63ce3Schristos }
39266e63ce3Schristos
39366e63ce3Schristos
394ed6a76a9Schristos /* Read a null terminated string from memory, return in a buffer. */
395ed6a76a9Schristos
39666e63ce3Schristos static char *
fetch_str(SIM_DESC sd,address_word addr)397ed6a76a9Schristos fetch_str (SIM_DESC sd, address_word addr)
39866e63ce3Schristos {
39966e63ce3Schristos char *buf;
40066e63ce3Schristos int nr = 0;
401ed6a76a9Schristos
40266e63ce3Schristos while (sim_core_read_1 (STATE_CPU (sd, 0),
40366e63ce3Schristos PC, read_map, addr + nr) != 0)
40466e63ce3Schristos nr++;
405ed6a76a9Schristos
40666e63ce3Schristos buf = NZALLOC (char, nr + 1);
407ed6a76a9Schristos sim_read (simulator, addr, (unsigned char *) buf, nr);
408ed6a76a9Schristos
40966e63ce3Schristos return buf;
41066e63ce3Schristos }
41166e63ce3Schristos
41266e63ce3Schristos /* Read a null terminated argument vector from memory, return in a
413ed6a76a9Schristos buffer. */
414ed6a76a9Schristos
41566e63ce3Schristos static char **
fetch_argv(SIM_DESC sd,address_word addr)416ed6a76a9Schristos fetch_argv (SIM_DESC sd, address_word addr)
41766e63ce3Schristos {
41866e63ce3Schristos int max_nr = 64;
41966e63ce3Schristos int nr = 0;
42066e63ce3Schristos char **buf = xmalloc (max_nr * sizeof (char*));
421ed6a76a9Schristos
42266e63ce3Schristos while (1)
42366e63ce3Schristos {
42466e63ce3Schristos unsigned32 a = sim_core_read_4 (STATE_CPU (sd, 0),
42566e63ce3Schristos PC, read_map, addr + nr * 4);
42666e63ce3Schristos if (a == 0) break;
42766e63ce3Schristos buf[nr] = fetch_str (sd, a);
42866e63ce3Schristos nr ++;
42966e63ce3Schristos if (nr == max_nr - 1)
43066e63ce3Schristos {
43166e63ce3Schristos max_nr += 50;
43266e63ce3Schristos buf = xrealloc (buf, max_nr * sizeof (char*));
43366e63ce3Schristos }
43466e63ce3Schristos }
43566e63ce3Schristos buf[nr] = 0;
43666e63ce3Schristos return buf;
43766e63ce3Schristos }
43866e63ce3Schristos
43966e63ce3Schristos
44066e63ce3Schristos /* sst.b */
44166e63ce3Schristos int
OP_380(void)442ed6a76a9Schristos OP_380 (void)
44366e63ce3Schristos {
44466e63ce3Schristos trace_input ("sst.b", OP_STORE16, 1);
44566e63ce3Schristos
44666e63ce3Schristos store_mem (State.regs[30] + (OP[3] & 0x7f), 1, State.regs[ OP[1] ]);
44766e63ce3Schristos
44866e63ce3Schristos trace_output (OP_STORE16);
44966e63ce3Schristos
45066e63ce3Schristos return 2;
45166e63ce3Schristos }
45266e63ce3Schristos
45366e63ce3Schristos /* sst.h */
45466e63ce3Schristos int
OP_480(void)455ed6a76a9Schristos OP_480 (void)
45666e63ce3Schristos {
45766e63ce3Schristos trace_input ("sst.h", OP_STORE16, 2);
45866e63ce3Schristos
45966e63ce3Schristos store_mem (State.regs[30] + ((OP[3] & 0x7f) << 1), 2, State.regs[ OP[1] ]);
46066e63ce3Schristos
46166e63ce3Schristos trace_output (OP_STORE16);
46266e63ce3Schristos
46366e63ce3Schristos return 2;
46466e63ce3Schristos }
46566e63ce3Schristos
46666e63ce3Schristos /* sst.w */
46766e63ce3Schristos int
OP_501(void)468ed6a76a9Schristos OP_501 (void)
46966e63ce3Schristos {
47066e63ce3Schristos trace_input ("sst.w", OP_STORE16, 4);
47166e63ce3Schristos
47266e63ce3Schristos store_mem (State.regs[30] + ((OP[3] & 0x7e) << 1), 4, State.regs[ OP[1] ]);
47366e63ce3Schristos
47466e63ce3Schristos trace_output (OP_STORE16);
47566e63ce3Schristos
47666e63ce3Schristos return 2;
47766e63ce3Schristos }
47866e63ce3Schristos
47966e63ce3Schristos /* ld.b */
48066e63ce3Schristos int
OP_700(void)481ed6a76a9Schristos OP_700 (void)
48266e63ce3Schristos {
48366e63ce3Schristos int adr;
48466e63ce3Schristos
48566e63ce3Schristos trace_input ("ld.b", OP_LOAD32, 1);
48666e63ce3Schristos
48766e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]);
48866e63ce3Schristos
48966e63ce3Schristos State.regs[ OP[1] ] = EXTEND8 (load_mem (adr, 1));
49066e63ce3Schristos
49166e63ce3Schristos trace_output (OP_LOAD32);
49266e63ce3Schristos
49366e63ce3Schristos return 4;
49466e63ce3Schristos }
49566e63ce3Schristos
49666e63ce3Schristos /* ld.h */
49766e63ce3Schristos int
OP_720(void)498ed6a76a9Schristos OP_720 (void)
49966e63ce3Schristos {
50066e63ce3Schristos int adr;
50166e63ce3Schristos
50266e63ce3Schristos trace_input ("ld.h", OP_LOAD32, 2);
50366e63ce3Schristos
50466e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]);
50566e63ce3Schristos adr &= ~0x1;
50666e63ce3Schristos
50766e63ce3Schristos State.regs[ OP[1] ] = EXTEND16 (load_mem (adr, 2));
50866e63ce3Schristos
50966e63ce3Schristos trace_output (OP_LOAD32);
51066e63ce3Schristos
51166e63ce3Schristos return 4;
51266e63ce3Schristos }
51366e63ce3Schristos
51466e63ce3Schristos /* ld.w */
51566e63ce3Schristos int
OP_10720(void)516ed6a76a9Schristos OP_10720 (void)
51766e63ce3Schristos {
51866e63ce3Schristos int adr;
51966e63ce3Schristos
52066e63ce3Schristos trace_input ("ld.w", OP_LOAD32, 4);
52166e63ce3Schristos
52266e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1);
52366e63ce3Schristos adr &= ~0x3;
52466e63ce3Schristos
52566e63ce3Schristos State.regs[ OP[1] ] = load_mem (adr, 4);
52666e63ce3Schristos
52766e63ce3Schristos trace_output (OP_LOAD32);
52866e63ce3Schristos
52966e63ce3Schristos return 4;
53066e63ce3Schristos }
53166e63ce3Schristos
53266e63ce3Schristos /* st.b */
53366e63ce3Schristos int
OP_740(void)534ed6a76a9Schristos OP_740 (void)
53566e63ce3Schristos {
53666e63ce3Schristos trace_input ("st.b", OP_STORE32, 1);
53766e63ce3Schristos
53866e63ce3Schristos store_mem (State.regs[ OP[0] ] + EXTEND16 (OP[2]), 1, State.regs[ OP[1] ]);
53966e63ce3Schristos
54066e63ce3Schristos trace_output (OP_STORE32);
54166e63ce3Schristos
54266e63ce3Schristos return 4;
54366e63ce3Schristos }
54466e63ce3Schristos
54566e63ce3Schristos /* st.h */
54666e63ce3Schristos int
OP_760(void)547ed6a76a9Schristos OP_760 (void)
54866e63ce3Schristos {
54966e63ce3Schristos int adr;
55066e63ce3Schristos
55166e63ce3Schristos trace_input ("st.h", OP_STORE32, 2);
55266e63ce3Schristos
55366e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]);
55466e63ce3Schristos adr &= ~1;
55566e63ce3Schristos
55666e63ce3Schristos store_mem (adr, 2, State.regs[ OP[1] ]);
55766e63ce3Schristos
55866e63ce3Schristos trace_output (OP_STORE32);
55966e63ce3Schristos
56066e63ce3Schristos return 4;
56166e63ce3Schristos }
56266e63ce3Schristos
56366e63ce3Schristos /* st.w */
56466e63ce3Schristos int
OP_10760(void)565ed6a76a9Schristos OP_10760 (void)
56666e63ce3Schristos {
56766e63ce3Schristos int adr;
56866e63ce3Schristos
56966e63ce3Schristos trace_input ("st.w", OP_STORE32, 4);
57066e63ce3Schristos
57166e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1);
57266e63ce3Schristos adr &= ~3;
57366e63ce3Schristos
57466e63ce3Schristos store_mem (adr, 4, State.regs[ OP[1] ]);
57566e63ce3Schristos
57666e63ce3Schristos trace_output (OP_STORE32);
57766e63ce3Schristos
57866e63ce3Schristos return 4;
57966e63ce3Schristos }
58066e63ce3Schristos
58166e63ce3Schristos /* add reg, reg */
58266e63ce3Schristos int
OP_1C0(void)583ed6a76a9Schristos OP_1C0 (void)
58466e63ce3Schristos {
58566e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
58666e63ce3Schristos
58766e63ce3Schristos trace_input ("add", OP_REG_REG, 0);
58866e63ce3Schristos
58966e63ce3Schristos /* Compute the result. */
59066e63ce3Schristos
59166e63ce3Schristos op0 = State.regs[ OP[0] ];
59266e63ce3Schristos op1 = State.regs[ OP[1] ];
59366e63ce3Schristos
59466e63ce3Schristos result = op0 + op1;
59566e63ce3Schristos
59666e63ce3Schristos /* Compute the condition codes. */
59766e63ce3Schristos z = (result == 0);
59866e63ce3Schristos s = (result & 0x80000000);
59966e63ce3Schristos cy = (result < op0 || result < op1);
60066e63ce3Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
60166e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
60266e63ce3Schristos
60366e63ce3Schristos /* Store the result and condition codes. */
60466e63ce3Schristos State.regs[OP[1]] = result;
60566e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
60666e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
60766e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
60866e63ce3Schristos trace_output (OP_REG_REG);
60966e63ce3Schristos
61066e63ce3Schristos return 2;
61166e63ce3Schristos }
61266e63ce3Schristos
61366e63ce3Schristos /* add sign_extend(imm5), reg */
61466e63ce3Schristos int
OP_240(void)615ed6a76a9Schristos OP_240 (void)
61666e63ce3Schristos {
61766e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
61866e63ce3Schristos int temp;
61966e63ce3Schristos
62066e63ce3Schristos trace_input ("add", OP_IMM_REG, 0);
62166e63ce3Schristos
62266e63ce3Schristos /* Compute the result. */
62366e63ce3Schristos temp = SEXT5 (OP[0]);
62466e63ce3Schristos op0 = temp;
62566e63ce3Schristos op1 = State.regs[OP[1]];
62666e63ce3Schristos result = op0 + op1;
62766e63ce3Schristos
62866e63ce3Schristos /* Compute the condition codes. */
62966e63ce3Schristos z = (result == 0);
63066e63ce3Schristos s = (result & 0x80000000);
63166e63ce3Schristos cy = (result < op0 || result < op1);
63266e63ce3Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
63366e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
63466e63ce3Schristos
63566e63ce3Schristos /* Store the result and condition codes. */
63666e63ce3Schristos State.regs[OP[1]] = result;
63766e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
63866e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
63966e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
64066e63ce3Schristos trace_output (OP_IMM_REG);
64166e63ce3Schristos
64266e63ce3Schristos return 2;
64366e63ce3Schristos }
64466e63ce3Schristos
64566e63ce3Schristos /* addi sign_extend(imm16), reg, reg */
64666e63ce3Schristos int
OP_600(void)647ed6a76a9Schristos OP_600 (void)
64866e63ce3Schristos {
64966e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
65066e63ce3Schristos
65166e63ce3Schristos trace_input ("addi", OP_IMM16_REG_REG, 0);
65266e63ce3Schristos
65366e63ce3Schristos /* Compute the result. */
65466e63ce3Schristos
65566e63ce3Schristos op0 = EXTEND16 (OP[2]);
65666e63ce3Schristos op1 = State.regs[ OP[0] ];
65766e63ce3Schristos result = op0 + op1;
65866e63ce3Schristos
65966e63ce3Schristos /* Compute the condition codes. */
66066e63ce3Schristos z = (result == 0);
66166e63ce3Schristos s = (result & 0x80000000);
66266e63ce3Schristos cy = (result < op0 || result < op1);
66366e63ce3Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
66466e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
66566e63ce3Schristos
66666e63ce3Schristos /* Store the result and condition codes. */
66766e63ce3Schristos State.regs[OP[1]] = result;
66866e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
66966e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
67066e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
67166e63ce3Schristos trace_output (OP_IMM16_REG_REG);
67266e63ce3Schristos
67366e63ce3Schristos return 4;
67466e63ce3Schristos }
67566e63ce3Schristos
67666e63ce3Schristos /* sub reg1, reg2 */
67766e63ce3Schristos int
OP_1A0(void)678ed6a76a9Schristos OP_1A0 (void)
67966e63ce3Schristos {
68066e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
68166e63ce3Schristos
68266e63ce3Schristos trace_input ("sub", OP_REG_REG, 0);
68366e63ce3Schristos /* Compute the result. */
68466e63ce3Schristos op0 = State.regs[ OP[0] ];
68566e63ce3Schristos op1 = State.regs[ OP[1] ];
68666e63ce3Schristos result = op1 - op0;
68766e63ce3Schristos
68866e63ce3Schristos /* Compute the condition codes. */
68966e63ce3Schristos z = (result == 0);
69066e63ce3Schristos s = (result & 0x80000000);
69166e63ce3Schristos cy = (op1 < op0);
69266e63ce3Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
69366e63ce3Schristos && (op1 & 0x80000000) != (result & 0x80000000));
69466e63ce3Schristos
69566e63ce3Schristos /* Store the result and condition codes. */
69666e63ce3Schristos State.regs[OP[1]] = result;
69766e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
69866e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
69966e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
70066e63ce3Schristos trace_output (OP_REG_REG);
70166e63ce3Schristos
70266e63ce3Schristos return 2;
70366e63ce3Schristos }
70466e63ce3Schristos
70566e63ce3Schristos /* subr reg1, reg2 */
70666e63ce3Schristos int
OP_180(void)707ed6a76a9Schristos OP_180 (void)
70866e63ce3Schristos {
70966e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
71066e63ce3Schristos
71166e63ce3Schristos trace_input ("subr", OP_REG_REG, 0);
71266e63ce3Schristos /* Compute the result. */
71366e63ce3Schristos op0 = State.regs[ OP[0] ];
71466e63ce3Schristos op1 = State.regs[ OP[1] ];
71566e63ce3Schristos result = op0 - op1;
71666e63ce3Schristos
71766e63ce3Schristos /* Compute the condition codes. */
71866e63ce3Schristos z = (result == 0);
71966e63ce3Schristos s = (result & 0x80000000);
72066e63ce3Schristos cy = (op0 < op1);
72166e63ce3Schristos ov = ((op0 & 0x80000000) != (op1 & 0x80000000)
72266e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
72366e63ce3Schristos
72466e63ce3Schristos /* Store the result and condition codes. */
72566e63ce3Schristos State.regs[OP[1]] = result;
72666e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
72766e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
72866e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
72966e63ce3Schristos trace_output (OP_REG_REG);
73066e63ce3Schristos
73166e63ce3Schristos return 2;
73266e63ce3Schristos }
73366e63ce3Schristos
73466e63ce3Schristos /* sxh reg1 */
73566e63ce3Schristos int
OP_E0(void)736ed6a76a9Schristos OP_E0 (void)
73766e63ce3Schristos {
73866e63ce3Schristos trace_input ("mulh", OP_REG_REG, 0);
73966e63ce3Schristos
74066e63ce3Schristos State.regs[ OP[1] ] = (EXTEND16 (State.regs[ OP[1] ]) * EXTEND16 (State.regs[ OP[0] ]));
74166e63ce3Schristos
74266e63ce3Schristos trace_output (OP_REG_REG);
74366e63ce3Schristos
74466e63ce3Schristos return 2;
74566e63ce3Schristos }
74666e63ce3Schristos
74766e63ce3Schristos /* mulh sign_extend(imm5), reg2 */
74866e63ce3Schristos int
OP_2E0(void)749ed6a76a9Schristos OP_2E0 (void)
75066e63ce3Schristos {
75166e63ce3Schristos trace_input ("mulh", OP_IMM_REG, 0);
75266e63ce3Schristos
75366e63ce3Schristos State.regs[ OP[1] ] = EXTEND16 (State.regs[ OP[1] ]) * SEXT5 (OP[0]);
75466e63ce3Schristos
75566e63ce3Schristos trace_output (OP_IMM_REG);
75666e63ce3Schristos
75766e63ce3Schristos return 2;
75866e63ce3Schristos }
75966e63ce3Schristos
76066e63ce3Schristos /* mulhi imm16, reg1, reg2 */
76166e63ce3Schristos int
OP_6E0(void)762ed6a76a9Schristos OP_6E0 (void)
76366e63ce3Schristos {
76466e63ce3Schristos trace_input ("mulhi", OP_IMM16_REG_REG, 0);
76566e63ce3Schristos
76666e63ce3Schristos State.regs[ OP[1] ] = EXTEND16 (State.regs[ OP[0] ]) * EXTEND16 (OP[2]);
76766e63ce3Schristos
76866e63ce3Schristos trace_output (OP_IMM16_REG_REG);
76966e63ce3Schristos
77066e63ce3Schristos return 4;
77166e63ce3Schristos }
77266e63ce3Schristos
77366e63ce3Schristos /* cmp reg, reg */
77466e63ce3Schristos int
OP_1E0(void)775ed6a76a9Schristos OP_1E0 (void)
77666e63ce3Schristos {
77766e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
77866e63ce3Schristos
77966e63ce3Schristos trace_input ("cmp", OP_REG_REG_CMP, 0);
78066e63ce3Schristos /* Compute the result. */
78166e63ce3Schristos op0 = State.regs[ OP[0] ];
78266e63ce3Schristos op1 = State.regs[ OP[1] ];
78366e63ce3Schristos result = op1 - op0;
78466e63ce3Schristos
78566e63ce3Schristos /* Compute the condition codes. */
78666e63ce3Schristos z = (result == 0);
78766e63ce3Schristos s = (result & 0x80000000);
78866e63ce3Schristos cy = (op1 < op0);
78966e63ce3Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
79066e63ce3Schristos && (op1 & 0x80000000) != (result & 0x80000000));
79166e63ce3Schristos
79266e63ce3Schristos /* Set condition codes. */
79366e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
79466e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
79566e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
79666e63ce3Schristos trace_output (OP_REG_REG_CMP);
79766e63ce3Schristos
79866e63ce3Schristos return 2;
79966e63ce3Schristos }
80066e63ce3Schristos
80166e63ce3Schristos /* cmp sign_extend(imm5), reg */
80266e63ce3Schristos int
OP_260(void)803ed6a76a9Schristos OP_260 (void)
80466e63ce3Schristos {
80566e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov;
80666e63ce3Schristos int temp;
80766e63ce3Schristos
80866e63ce3Schristos /* Compute the result. */
80966e63ce3Schristos trace_input ("cmp", OP_IMM_REG_CMP, 0);
81066e63ce3Schristos temp = SEXT5 (OP[0]);
81166e63ce3Schristos op0 = temp;
81266e63ce3Schristos op1 = State.regs[OP[1]];
81366e63ce3Schristos result = op1 - op0;
81466e63ce3Schristos
81566e63ce3Schristos /* Compute the condition codes. */
81666e63ce3Schristos z = (result == 0);
81766e63ce3Schristos s = (result & 0x80000000);
81866e63ce3Schristos cy = (op1 < op0);
81966e63ce3Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
82066e63ce3Schristos && (op1 & 0x80000000) != (result & 0x80000000));
82166e63ce3Schristos
82266e63ce3Schristos /* Set condition codes. */
82366e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
82466e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
82566e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
82666e63ce3Schristos trace_output (OP_IMM_REG_CMP);
82766e63ce3Schristos
82866e63ce3Schristos return 2;
82966e63ce3Schristos }
83066e63ce3Schristos
83166e63ce3Schristos /* setf cccc,reg2 */
83266e63ce3Schristos int
OP_7E0(void)833ed6a76a9Schristos OP_7E0 (void)
83466e63ce3Schristos {
83566e63ce3Schristos trace_input ("setf", OP_EX1, 0);
83666e63ce3Schristos
83766e63ce3Schristos State.regs[ OP[1] ] = condition_met (OP[0]);
83866e63ce3Schristos
83966e63ce3Schristos trace_output (OP_EX1);
84066e63ce3Schristos
84166e63ce3Schristos return 4;
84266e63ce3Schristos }
84366e63ce3Schristos
84466e63ce3Schristos /* satadd reg,reg */
84566e63ce3Schristos int
OP_C0(void)846ed6a76a9Schristos OP_C0 (void)
84766e63ce3Schristos {
84866e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov, sat;
84966e63ce3Schristos
85066e63ce3Schristos trace_input ("satadd", OP_REG_REG, 0);
85166e63ce3Schristos /* Compute the result. */
85266e63ce3Schristos op0 = State.regs[ OP[0] ];
85366e63ce3Schristos op1 = State.regs[ OP[1] ];
85466e63ce3Schristos result = op0 + op1;
85566e63ce3Schristos
85666e63ce3Schristos /* Compute the condition codes. */
85766e63ce3Schristos z = (result == 0);
85866e63ce3Schristos s = (result & 0x80000000);
85966e63ce3Schristos cy = (result < op0 || result < op1);
86066e63ce3Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
86166e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
86266e63ce3Schristos sat = ov;
86366e63ce3Schristos
86466e63ce3Schristos /* Handle saturated results. */
86566e63ce3Schristos if (sat && s)
86666e63ce3Schristos {
86766e63ce3Schristos /* An overflow that results in a negative result implies that we
86866e63ce3Schristos became too positive. */
86966e63ce3Schristos result = 0x7fffffff;
87066e63ce3Schristos s = 0;
87166e63ce3Schristos }
87266e63ce3Schristos else if (sat)
87366e63ce3Schristos {
87466e63ce3Schristos /* Any other overflow must have thus been too negative. */
87566e63ce3Schristos result = 0x80000000;
87666e63ce3Schristos s = 1;
87766e63ce3Schristos z = 0;
87866e63ce3Schristos }
87966e63ce3Schristos
88066e63ce3Schristos /* Store the result and condition codes. */
88166e63ce3Schristos State.regs[OP[1]] = result;
88266e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
88366e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
88466e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
88566e63ce3Schristos | (sat ? PSW_SAT : 0));
88666e63ce3Schristos
88766e63ce3Schristos trace_output (OP_REG_REG);
88866e63ce3Schristos
88966e63ce3Schristos return 2;
89066e63ce3Schristos }
89166e63ce3Schristos
89266e63ce3Schristos /* satadd sign_extend(imm5), reg */
89366e63ce3Schristos int
OP_220(void)894ed6a76a9Schristos OP_220 (void)
89566e63ce3Schristos {
89666e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov, sat;
89766e63ce3Schristos
89866e63ce3Schristos int temp;
89966e63ce3Schristos
90066e63ce3Schristos trace_input ("satadd", OP_IMM_REG, 0);
90166e63ce3Schristos
90266e63ce3Schristos /* Compute the result. */
90366e63ce3Schristos temp = SEXT5 (OP[0]);
90466e63ce3Schristos op0 = temp;
90566e63ce3Schristos op1 = State.regs[OP[1]];
90666e63ce3Schristos result = op0 + op1;
90766e63ce3Schristos
90866e63ce3Schristos /* Compute the condition codes. */
90966e63ce3Schristos z = (result == 0);
91066e63ce3Schristos s = (result & 0x80000000);
91166e63ce3Schristos cy = (result < op0 || result < op1);
91266e63ce3Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
91366e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
91466e63ce3Schristos sat = ov;
91566e63ce3Schristos
91666e63ce3Schristos /* Handle saturated results. */
91766e63ce3Schristos if (sat && s)
91866e63ce3Schristos {
91966e63ce3Schristos /* An overflow that results in a negative result implies that we
92066e63ce3Schristos became too positive. */
92166e63ce3Schristos result = 0x7fffffff;
92266e63ce3Schristos s = 0;
92366e63ce3Schristos }
92466e63ce3Schristos else if (sat)
92566e63ce3Schristos {
92666e63ce3Schristos /* Any other overflow must have thus been too negative. */
92766e63ce3Schristos result = 0x80000000;
92866e63ce3Schristos s = 1;
92966e63ce3Schristos z = 0;
93066e63ce3Schristos }
93166e63ce3Schristos
93266e63ce3Schristos /* Store the result and condition codes. */
93366e63ce3Schristos State.regs[OP[1]] = result;
93466e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
93566e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
93666e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
93766e63ce3Schristos | (sat ? PSW_SAT : 0));
93866e63ce3Schristos trace_output (OP_IMM_REG);
93966e63ce3Schristos
94066e63ce3Schristos return 2;
94166e63ce3Schristos }
94266e63ce3Schristos
94366e63ce3Schristos /* satsub reg1, reg2 */
94466e63ce3Schristos int
OP_A0(void)945ed6a76a9Schristos OP_A0 (void)
94666e63ce3Schristos {
94766e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov, sat;
94866e63ce3Schristos
94966e63ce3Schristos trace_input ("satsub", OP_REG_REG, 0);
95066e63ce3Schristos
95166e63ce3Schristos /* Compute the result. */
95266e63ce3Schristos op0 = State.regs[ OP[0] ];
95366e63ce3Schristos op1 = State.regs[ OP[1] ];
95466e63ce3Schristos result = op1 - op0;
95566e63ce3Schristos
95666e63ce3Schristos /* Compute the condition codes. */
95766e63ce3Schristos z = (result == 0);
95866e63ce3Schristos s = (result & 0x80000000);
95966e63ce3Schristos cy = (op1 < op0);
96066e63ce3Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
96166e63ce3Schristos && (op1 & 0x80000000) != (result & 0x80000000));
96266e63ce3Schristos sat = ov;
96366e63ce3Schristos
96466e63ce3Schristos /* Handle saturated results. */
96566e63ce3Schristos if (sat && s)
96666e63ce3Schristos {
96766e63ce3Schristos /* An overflow that results in a negative result implies that we
96866e63ce3Schristos became too positive. */
96966e63ce3Schristos result = 0x7fffffff;
97066e63ce3Schristos s = 0;
97166e63ce3Schristos }
97266e63ce3Schristos else if (sat)
97366e63ce3Schristos {
97466e63ce3Schristos /* Any other overflow must have thus been too negative. */
97566e63ce3Schristos result = 0x80000000;
97666e63ce3Schristos s = 1;
97766e63ce3Schristos z = 0;
97866e63ce3Schristos }
97966e63ce3Schristos
98066e63ce3Schristos /* Store the result and condition codes. */
98166e63ce3Schristos State.regs[OP[1]] = result;
98266e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
98366e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
98466e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
98566e63ce3Schristos | (sat ? PSW_SAT : 0));
98666e63ce3Schristos
98766e63ce3Schristos trace_output (OP_REG_REG);
98866e63ce3Schristos return 2;
98966e63ce3Schristos }
99066e63ce3Schristos
99166e63ce3Schristos /* satsubi sign_extend(imm16), reg */
99266e63ce3Schristos int
OP_660(void)993ed6a76a9Schristos OP_660 (void)
99466e63ce3Schristos {
99566e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov, sat;
99666e63ce3Schristos int temp;
99766e63ce3Schristos
99866e63ce3Schristos trace_input ("satsubi", OP_IMM_REG, 0);
99966e63ce3Schristos
100066e63ce3Schristos /* Compute the result. */
100166e63ce3Schristos temp = EXTEND16 (OP[2]);
100266e63ce3Schristos op0 = temp;
100366e63ce3Schristos op1 = State.regs[ OP[0] ];
100466e63ce3Schristos result = op1 - op0;
100566e63ce3Schristos
100666e63ce3Schristos /* Compute the condition codes. */
100766e63ce3Schristos z = (result == 0);
100866e63ce3Schristos s = (result & 0x80000000);
100966e63ce3Schristos cy = (op1 < op0);
101066e63ce3Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
101166e63ce3Schristos && (op1 & 0x80000000) != (result & 0x80000000));
101266e63ce3Schristos sat = ov;
101366e63ce3Schristos
101466e63ce3Schristos /* Handle saturated results. */
101566e63ce3Schristos if (sat && s)
101666e63ce3Schristos {
101766e63ce3Schristos /* An overflow that results in a negative result implies that we
101866e63ce3Schristos became too positive. */
101966e63ce3Schristos result = 0x7fffffff;
102066e63ce3Schristos s = 0;
102166e63ce3Schristos }
102266e63ce3Schristos else if (sat)
102366e63ce3Schristos {
102466e63ce3Schristos /* Any other overflow must have thus been too negative. */
102566e63ce3Schristos result = 0x80000000;
102666e63ce3Schristos s = 1;
102766e63ce3Schristos z = 0;
102866e63ce3Schristos }
102966e63ce3Schristos
103066e63ce3Schristos /* Store the result and condition codes. */
103166e63ce3Schristos State.regs[OP[1]] = result;
103266e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
103366e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
103466e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
103566e63ce3Schristos | (sat ? PSW_SAT : 0));
103666e63ce3Schristos
103766e63ce3Schristos trace_output (OP_IMM_REG);
103866e63ce3Schristos
103966e63ce3Schristos return 4;
104066e63ce3Schristos }
104166e63ce3Schristos
104266e63ce3Schristos /* satsubr reg,reg */
104366e63ce3Schristos int
OP_80(void)1044ed6a76a9Schristos OP_80 (void)
104566e63ce3Schristos {
104666e63ce3Schristos unsigned int op0, op1, result, z, s, cy, ov, sat;
104766e63ce3Schristos
104866e63ce3Schristos trace_input ("satsubr", OP_REG_REG, 0);
104966e63ce3Schristos
105066e63ce3Schristos /* Compute the result. */
105166e63ce3Schristos op0 = State.regs[ OP[0] ];
105266e63ce3Schristos op1 = State.regs[ OP[1] ];
105366e63ce3Schristos result = op0 - op1;
105466e63ce3Schristos
105566e63ce3Schristos /* Compute the condition codes. */
105666e63ce3Schristos z = (result == 0);
105766e63ce3Schristos s = (result & 0x80000000);
105866e63ce3Schristos cy = (op0 < op1);
105966e63ce3Schristos ov = ((op0 & 0x80000000) != (op1 & 0x80000000)
106066e63ce3Schristos && (op0 & 0x80000000) != (result & 0x80000000));
106166e63ce3Schristos sat = ov;
106266e63ce3Schristos
106366e63ce3Schristos /* Handle saturated results. */
106466e63ce3Schristos if (sat && s)
106566e63ce3Schristos {
106666e63ce3Schristos /* An overflow that results in a negative result implies that we
106766e63ce3Schristos became too positive. */
106866e63ce3Schristos result = 0x7fffffff;
106966e63ce3Schristos s = 0;
107066e63ce3Schristos }
107166e63ce3Schristos else if (sat)
107266e63ce3Schristos {
107366e63ce3Schristos /* Any other overflow must have thus been too negative. */
107466e63ce3Schristos result = 0x80000000;
107566e63ce3Schristos s = 1;
107666e63ce3Schristos z = 0;
107766e63ce3Schristos }
107866e63ce3Schristos
107966e63ce3Schristos /* Store the result and condition codes. */
108066e63ce3Schristos State.regs[OP[1]] = result;
108166e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
108266e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
108366e63ce3Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
108466e63ce3Schristos | (sat ? PSW_SAT : 0));
108566e63ce3Schristos
108666e63ce3Schristos trace_output (OP_REG_REG);
108766e63ce3Schristos
108866e63ce3Schristos return 2;
108966e63ce3Schristos }
109066e63ce3Schristos
109166e63ce3Schristos /* tst reg,reg */
109266e63ce3Schristos int
OP_160(void)1093ed6a76a9Schristos OP_160 (void)
109466e63ce3Schristos {
109566e63ce3Schristos unsigned int op0, op1, result, z, s;
109666e63ce3Schristos
109766e63ce3Schristos trace_input ("tst", OP_REG_REG_CMP, 0);
109866e63ce3Schristos
109966e63ce3Schristos /* Compute the result. */
110066e63ce3Schristos op0 = State.regs[ OP[0] ];
110166e63ce3Schristos op1 = State.regs[ OP[1] ];
110266e63ce3Schristos result = op0 & op1;
110366e63ce3Schristos
110466e63ce3Schristos /* Compute the condition codes. */
110566e63ce3Schristos z = (result == 0);
110666e63ce3Schristos s = (result & 0x80000000);
110766e63ce3Schristos
110866e63ce3Schristos /* Store the condition codes. */
110966e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
111066e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
111166e63ce3Schristos trace_output (OP_REG_REG_CMP);
111266e63ce3Schristos
111366e63ce3Schristos return 2;
111466e63ce3Schristos }
111566e63ce3Schristos
111666e63ce3Schristos /* mov sign_extend(imm5), reg */
111766e63ce3Schristos int
OP_200(void)1118ed6a76a9Schristos OP_200 (void)
111966e63ce3Schristos {
112066e63ce3Schristos int value = SEXT5 (OP[0]);
112166e63ce3Schristos
112266e63ce3Schristos trace_input ("mov", OP_IMM_REG_MOVE, 0);
112366e63ce3Schristos
112466e63ce3Schristos State.regs[ OP[1] ] = value;
112566e63ce3Schristos
112666e63ce3Schristos trace_output (OP_IMM_REG_MOVE);
112766e63ce3Schristos
112866e63ce3Schristos return 2;
112966e63ce3Schristos }
113066e63ce3Schristos
113166e63ce3Schristos /* movhi imm16, reg, reg */
113266e63ce3Schristos int
OP_640(void)1133ed6a76a9Schristos OP_640 (void)
113466e63ce3Schristos {
113566e63ce3Schristos trace_input ("movhi", OP_UIMM16_REG_REG, 16);
113666e63ce3Schristos
113766e63ce3Schristos State.regs[ OP[1] ] = State.regs[ OP[0] ] + (OP[2] << 16);
113866e63ce3Schristos
113966e63ce3Schristos trace_output (OP_UIMM16_REG_REG);
114066e63ce3Schristos
114166e63ce3Schristos return 4;
114266e63ce3Schristos }
114366e63ce3Schristos
114466e63ce3Schristos /* sar zero_extend(imm5),reg1 */
114566e63ce3Schristos int
OP_2A0(void)1146ed6a76a9Schristos OP_2A0 (void)
114766e63ce3Schristos {
114866e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
114966e63ce3Schristos
115066e63ce3Schristos trace_input ("sar", OP_IMM_REG, 0);
115166e63ce3Schristos op0 = OP[0];
115266e63ce3Schristos op1 = State.regs[ OP[1] ];
115366e63ce3Schristos result = (signed)op1 >> op0;
115466e63ce3Schristos
115566e63ce3Schristos /* Compute the condition codes. */
115666e63ce3Schristos z = (result == 0);
115766e63ce3Schristos s = (result & 0x80000000);
115866e63ce3Schristos cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
115966e63ce3Schristos
116066e63ce3Schristos /* Store the result and condition codes. */
116166e63ce3Schristos State.regs[ OP[1] ] = result;
116266e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
116366e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
116466e63ce3Schristos | (cy ? PSW_CY : 0));
116566e63ce3Schristos trace_output (OP_IMM_REG);
116666e63ce3Schristos
116766e63ce3Schristos return 2;
116866e63ce3Schristos }
116966e63ce3Schristos
117066e63ce3Schristos /* sar reg1, reg2 */
117166e63ce3Schristos int
OP_A007E0(void)1172ed6a76a9Schristos OP_A007E0 (void)
117366e63ce3Schristos {
117466e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
117566e63ce3Schristos
117666e63ce3Schristos trace_input ("sar", OP_REG_REG, 0);
117766e63ce3Schristos
117866e63ce3Schristos op0 = State.regs[ OP[0] ] & 0x1f;
117966e63ce3Schristos op1 = State.regs[ OP[1] ];
118066e63ce3Schristos result = (signed)op1 >> op0;
118166e63ce3Schristos
118266e63ce3Schristos /* Compute the condition codes. */
118366e63ce3Schristos z = (result == 0);
118466e63ce3Schristos s = (result & 0x80000000);
118566e63ce3Schristos cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
118666e63ce3Schristos
118766e63ce3Schristos /* Store the result and condition codes. */
118866e63ce3Schristos State.regs[OP[1]] = result;
118966e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
119066e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
119166e63ce3Schristos | (cy ? PSW_CY : 0));
119266e63ce3Schristos trace_output (OP_REG_REG);
119366e63ce3Schristos
119466e63ce3Schristos return 4;
119566e63ce3Schristos }
119666e63ce3Schristos
119766e63ce3Schristos /* shl zero_extend(imm5),reg1 */
119866e63ce3Schristos int
OP_2C0(void)1199ed6a76a9Schristos OP_2C0 (void)
120066e63ce3Schristos {
120166e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
120266e63ce3Schristos
120366e63ce3Schristos trace_input ("shl", OP_IMM_REG, 0);
120466e63ce3Schristos op0 = OP[0];
120566e63ce3Schristos op1 = State.regs[ OP[1] ];
120666e63ce3Schristos result = op1 << op0;
120766e63ce3Schristos
120866e63ce3Schristos /* Compute the condition codes. */
120966e63ce3Schristos z = (result == 0);
121066e63ce3Schristos s = (result & 0x80000000);
121166e63ce3Schristos cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
121266e63ce3Schristos
121366e63ce3Schristos /* Store the result and condition codes. */
121466e63ce3Schristos State.regs[OP[1]] = result;
121566e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
121666e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
121766e63ce3Schristos | (cy ? PSW_CY : 0));
121866e63ce3Schristos trace_output (OP_IMM_REG);
121966e63ce3Schristos
122066e63ce3Schristos return 2;
122166e63ce3Schristos }
122266e63ce3Schristos
122366e63ce3Schristos /* shl reg1, reg2 */
122466e63ce3Schristos int
OP_C007E0(void)1225ed6a76a9Schristos OP_C007E0 (void)
122666e63ce3Schristos {
122766e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
122866e63ce3Schristos
122966e63ce3Schristos trace_input ("shl", OP_REG_REG, 0);
123066e63ce3Schristos op0 = State.regs[ OP[0] ] & 0x1f;
123166e63ce3Schristos op1 = State.regs[ OP[1] ];
123266e63ce3Schristos result = op1 << op0;
123366e63ce3Schristos
123466e63ce3Schristos /* Compute the condition codes. */
123566e63ce3Schristos z = (result == 0);
123666e63ce3Schristos s = (result & 0x80000000);
123766e63ce3Schristos cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
123866e63ce3Schristos
123966e63ce3Schristos /* Store the result and condition codes. */
124066e63ce3Schristos State.regs[OP[1]] = result;
124166e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
124266e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
124366e63ce3Schristos | (cy ? PSW_CY : 0));
124466e63ce3Schristos trace_output (OP_REG_REG);
124566e63ce3Schristos
124666e63ce3Schristos return 4;
124766e63ce3Schristos }
124866e63ce3Schristos
124966e63ce3Schristos /* shr zero_extend(imm5),reg1 */
125066e63ce3Schristos int
OP_280(void)1251ed6a76a9Schristos OP_280 (void)
125266e63ce3Schristos {
125366e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
125466e63ce3Schristos
125566e63ce3Schristos trace_input ("shr", OP_IMM_REG, 0);
125666e63ce3Schristos op0 = OP[0];
125766e63ce3Schristos op1 = State.regs[ OP[1] ];
125866e63ce3Schristos result = op1 >> op0;
125966e63ce3Schristos
126066e63ce3Schristos /* Compute the condition codes. */
126166e63ce3Schristos z = (result == 0);
126266e63ce3Schristos s = (result & 0x80000000);
126366e63ce3Schristos cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
126466e63ce3Schristos
126566e63ce3Schristos /* Store the result and condition codes. */
126666e63ce3Schristos State.regs[OP[1]] = result;
126766e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
126866e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
126966e63ce3Schristos | (cy ? PSW_CY : 0));
127066e63ce3Schristos trace_output (OP_IMM_REG);
127166e63ce3Schristos
127266e63ce3Schristos return 2;
127366e63ce3Schristos }
127466e63ce3Schristos
127566e63ce3Schristos /* shr reg1, reg2 */
127666e63ce3Schristos int
OP_8007E0(void)1277ed6a76a9Schristos OP_8007E0 (void)
127866e63ce3Schristos {
127966e63ce3Schristos unsigned int op0, op1, result, z, s, cy;
128066e63ce3Schristos
128166e63ce3Schristos trace_input ("shr", OP_REG_REG, 0);
128266e63ce3Schristos op0 = State.regs[ OP[0] ] & 0x1f;
128366e63ce3Schristos op1 = State.regs[ OP[1] ];
128466e63ce3Schristos result = op1 >> op0;
128566e63ce3Schristos
128666e63ce3Schristos /* Compute the condition codes. */
128766e63ce3Schristos z = (result == 0);
128866e63ce3Schristos s = (result & 0x80000000);
128966e63ce3Schristos cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
129066e63ce3Schristos
129166e63ce3Schristos /* Store the result and condition codes. */
129266e63ce3Schristos State.regs[OP[1]] = result;
129366e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
129466e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
129566e63ce3Schristos | (cy ? PSW_CY : 0));
129666e63ce3Schristos trace_output (OP_REG_REG);
129766e63ce3Schristos
129866e63ce3Schristos return 4;
129966e63ce3Schristos }
130066e63ce3Schristos
130166e63ce3Schristos /* or reg, reg */
130266e63ce3Schristos int
OP_100(void)1303ed6a76a9Schristos OP_100 (void)
130466e63ce3Schristos {
130566e63ce3Schristos unsigned int op0, op1, result, z, s;
130666e63ce3Schristos
130766e63ce3Schristos trace_input ("or", OP_REG_REG, 0);
130866e63ce3Schristos
130966e63ce3Schristos /* Compute the result. */
131066e63ce3Schristos op0 = State.regs[ OP[0] ];
131166e63ce3Schristos op1 = State.regs[ OP[1] ];
131266e63ce3Schristos result = op0 | op1;
131366e63ce3Schristos
131466e63ce3Schristos /* Compute the condition codes. */
131566e63ce3Schristos z = (result == 0);
131666e63ce3Schristos s = (result & 0x80000000);
131766e63ce3Schristos
131866e63ce3Schristos /* Store the result and condition codes. */
131966e63ce3Schristos State.regs[OP[1]] = result;
132066e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
132166e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
132266e63ce3Schristos trace_output (OP_REG_REG);
132366e63ce3Schristos
132466e63ce3Schristos return 2;
132566e63ce3Schristos }
132666e63ce3Schristos
132766e63ce3Schristos /* ori zero_extend(imm16), reg, reg */
132866e63ce3Schristos int
OP_680(void)1329ed6a76a9Schristos OP_680 (void)
133066e63ce3Schristos {
133166e63ce3Schristos unsigned int op0, op1, result, z, s;
133266e63ce3Schristos
133366e63ce3Schristos trace_input ("ori", OP_UIMM16_REG_REG, 0);
133466e63ce3Schristos op0 = OP[2];
133566e63ce3Schristos op1 = State.regs[ OP[0] ];
133666e63ce3Schristos result = op0 | op1;
133766e63ce3Schristos
133866e63ce3Schristos /* Compute the condition codes. */
133966e63ce3Schristos z = (result == 0);
134066e63ce3Schristos s = (result & 0x80000000);
134166e63ce3Schristos
134266e63ce3Schristos /* Store the result and condition codes. */
134366e63ce3Schristos State.regs[OP[1]] = result;
134466e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
134566e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
134666e63ce3Schristos trace_output (OP_UIMM16_REG_REG);
134766e63ce3Schristos
134866e63ce3Schristos return 4;
134966e63ce3Schristos }
135066e63ce3Schristos
135166e63ce3Schristos /* and reg, reg */
135266e63ce3Schristos int
OP_140(void)1353ed6a76a9Schristos OP_140 (void)
135466e63ce3Schristos {
135566e63ce3Schristos unsigned int op0, op1, result, z, s;
135666e63ce3Schristos
135766e63ce3Schristos trace_input ("and", OP_REG_REG, 0);
135866e63ce3Schristos
135966e63ce3Schristos /* Compute the result. */
136066e63ce3Schristos op0 = State.regs[ OP[0] ];
136166e63ce3Schristos op1 = State.regs[ OP[1] ];
136266e63ce3Schristos result = op0 & op1;
136366e63ce3Schristos
136466e63ce3Schristos /* Compute the condition codes. */
136566e63ce3Schristos z = (result == 0);
136666e63ce3Schristos s = (result & 0x80000000);
136766e63ce3Schristos
136866e63ce3Schristos /* Store the result and condition codes. */
136966e63ce3Schristos State.regs[OP[1]] = result;
137066e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
137166e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
137266e63ce3Schristos trace_output (OP_REG_REG);
137366e63ce3Schristos
137466e63ce3Schristos return 2;
137566e63ce3Schristos }
137666e63ce3Schristos
137766e63ce3Schristos /* andi zero_extend(imm16), reg, reg */
137866e63ce3Schristos int
OP_6C0(void)1379ed6a76a9Schristos OP_6C0 (void)
138066e63ce3Schristos {
138166e63ce3Schristos unsigned int result, z;
138266e63ce3Schristos
138366e63ce3Schristos trace_input ("andi", OP_UIMM16_REG_REG, 0);
138466e63ce3Schristos
138566e63ce3Schristos result = OP[2] & State.regs[ OP[0] ];
138666e63ce3Schristos
138766e63ce3Schristos /* Compute the condition codes. */
138866e63ce3Schristos z = (result == 0);
138966e63ce3Schristos
139066e63ce3Schristos /* Store the result and condition codes. */
139166e63ce3Schristos State.regs[ OP[1] ] = result;
139266e63ce3Schristos
139366e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
139466e63ce3Schristos PSW |= (z ? PSW_Z : 0);
139566e63ce3Schristos
139666e63ce3Schristos trace_output (OP_UIMM16_REG_REG);
139766e63ce3Schristos
139866e63ce3Schristos return 4;
139966e63ce3Schristos }
140066e63ce3Schristos
140166e63ce3Schristos /* xor reg, reg */
140266e63ce3Schristos int
OP_120(void)1403ed6a76a9Schristos OP_120 (void)
140466e63ce3Schristos {
140566e63ce3Schristos unsigned int op0, op1, result, z, s;
140666e63ce3Schristos
140766e63ce3Schristos trace_input ("xor", OP_REG_REG, 0);
140866e63ce3Schristos
140966e63ce3Schristos /* Compute the result. */
141066e63ce3Schristos op0 = State.regs[ OP[0] ];
141166e63ce3Schristos op1 = State.regs[ OP[1] ];
141266e63ce3Schristos result = op0 ^ op1;
141366e63ce3Schristos
141466e63ce3Schristos /* Compute the condition codes. */
141566e63ce3Schristos z = (result == 0);
141666e63ce3Schristos s = (result & 0x80000000);
141766e63ce3Schristos
141866e63ce3Schristos /* Store the result and condition codes. */
141966e63ce3Schristos State.regs[OP[1]] = result;
142066e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
142166e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
142266e63ce3Schristos trace_output (OP_REG_REG);
142366e63ce3Schristos
142466e63ce3Schristos return 2;
142566e63ce3Schristos }
142666e63ce3Schristos
142766e63ce3Schristos /* xori zero_extend(imm16), reg, reg */
142866e63ce3Schristos int
OP_6A0(void)1429ed6a76a9Schristos OP_6A0 (void)
143066e63ce3Schristos {
143166e63ce3Schristos unsigned int op0, op1, result, z, s;
143266e63ce3Schristos
143366e63ce3Schristos trace_input ("xori", OP_UIMM16_REG_REG, 0);
143466e63ce3Schristos op0 = OP[2];
143566e63ce3Schristos op1 = State.regs[ OP[0] ];
143666e63ce3Schristos result = op0 ^ op1;
143766e63ce3Schristos
143866e63ce3Schristos /* Compute the condition codes. */
143966e63ce3Schristos z = (result == 0);
144066e63ce3Schristos s = (result & 0x80000000);
144166e63ce3Schristos
144266e63ce3Schristos /* Store the result and condition codes. */
144366e63ce3Schristos State.regs[OP[1]] = result;
144466e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
144566e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
144666e63ce3Schristos trace_output (OP_UIMM16_REG_REG);
144766e63ce3Schristos
144866e63ce3Schristos return 4;
144966e63ce3Schristos }
145066e63ce3Schristos
145166e63ce3Schristos /* not reg1, reg2 */
145266e63ce3Schristos int
OP_20(void)1453ed6a76a9Schristos OP_20 (void)
145466e63ce3Schristos {
145566e63ce3Schristos unsigned int op0, result, z, s;
145666e63ce3Schristos
145766e63ce3Schristos trace_input ("not", OP_REG_REG_MOVE, 0);
145866e63ce3Schristos /* Compute the result. */
145966e63ce3Schristos op0 = State.regs[ OP[0] ];
146066e63ce3Schristos result = ~op0;
146166e63ce3Schristos
146266e63ce3Schristos /* Compute the condition codes. */
146366e63ce3Schristos z = (result == 0);
146466e63ce3Schristos s = (result & 0x80000000);
146566e63ce3Schristos
146666e63ce3Schristos /* Store the result and condition codes. */
146766e63ce3Schristos State.regs[OP[1]] = result;
146866e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
146966e63ce3Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
147066e63ce3Schristos trace_output (OP_REG_REG_MOVE);
147166e63ce3Schristos
147266e63ce3Schristos return 2;
147366e63ce3Schristos }
147466e63ce3Schristos
147566e63ce3Schristos /* set1 */
147666e63ce3Schristos int
OP_7C0(void)1477ed6a76a9Schristos OP_7C0 (void)
147866e63ce3Schristos {
147966e63ce3Schristos unsigned int op0, op1, op2;
148066e63ce3Schristos int temp;
148166e63ce3Schristos
148266e63ce3Schristos trace_input ("set1", OP_BIT, 0);
148366e63ce3Schristos op0 = State.regs[ OP[0] ];
148466e63ce3Schristos op1 = OP[1] & 0x7;
148566e63ce3Schristos temp = EXTEND16 (OP[2]);
148666e63ce3Schristos op2 = temp;
148766e63ce3Schristos temp = load_mem (op0 + op2, 1);
148866e63ce3Schristos PSW &= ~PSW_Z;
148966e63ce3Schristos if ((temp & (1 << op1)) == 0)
149066e63ce3Schristos PSW |= PSW_Z;
149166e63ce3Schristos temp |= (1 << op1);
149266e63ce3Schristos store_mem (op0 + op2, 1, temp);
149366e63ce3Schristos trace_output (OP_BIT);
149466e63ce3Schristos
149566e63ce3Schristos return 4;
149666e63ce3Schristos }
149766e63ce3Schristos
149866e63ce3Schristos /* not1 */
149966e63ce3Schristos int
OP_47C0(void)1500ed6a76a9Schristos OP_47C0 (void)
150166e63ce3Schristos {
150266e63ce3Schristos unsigned int op0, op1, op2;
150366e63ce3Schristos int temp;
150466e63ce3Schristos
150566e63ce3Schristos trace_input ("not1", OP_BIT, 0);
150666e63ce3Schristos op0 = State.regs[ OP[0] ];
150766e63ce3Schristos op1 = OP[1] & 0x7;
150866e63ce3Schristos temp = EXTEND16 (OP[2]);
150966e63ce3Schristos op2 = temp;
151066e63ce3Schristos temp = load_mem (op0 + op2, 1);
151166e63ce3Schristos PSW &= ~PSW_Z;
151266e63ce3Schristos if ((temp & (1 << op1)) == 0)
151366e63ce3Schristos PSW |= PSW_Z;
151466e63ce3Schristos temp ^= (1 << op1);
151566e63ce3Schristos store_mem (op0 + op2, 1, temp);
151666e63ce3Schristos trace_output (OP_BIT);
151766e63ce3Schristos
151866e63ce3Schristos return 4;
151966e63ce3Schristos }
152066e63ce3Schristos
152166e63ce3Schristos /* clr1 */
152266e63ce3Schristos int
OP_87C0(void)1523ed6a76a9Schristos OP_87C0 (void)
152466e63ce3Schristos {
152566e63ce3Schristos unsigned int op0, op1, op2;
152666e63ce3Schristos int temp;
152766e63ce3Schristos
152866e63ce3Schristos trace_input ("clr1", OP_BIT, 0);
152966e63ce3Schristos op0 = State.regs[ OP[0] ];
153066e63ce3Schristos op1 = OP[1] & 0x7;
153166e63ce3Schristos temp = EXTEND16 (OP[2]);
153266e63ce3Schristos op2 = temp;
153366e63ce3Schristos temp = load_mem (op0 + op2, 1);
153466e63ce3Schristos PSW &= ~PSW_Z;
153566e63ce3Schristos if ((temp & (1 << op1)) == 0)
153666e63ce3Schristos PSW |= PSW_Z;
153766e63ce3Schristos temp &= ~(1 << op1);
153866e63ce3Schristos store_mem (op0 + op2, 1, temp);
153966e63ce3Schristos trace_output (OP_BIT);
154066e63ce3Schristos
154166e63ce3Schristos return 4;
154266e63ce3Schristos }
154366e63ce3Schristos
154466e63ce3Schristos /* tst1 */
154566e63ce3Schristos int
OP_C7C0(void)1546ed6a76a9Schristos OP_C7C0 (void)
154766e63ce3Schristos {
154866e63ce3Schristos unsigned int op0, op1, op2;
154966e63ce3Schristos int temp;
155066e63ce3Schristos
155166e63ce3Schristos trace_input ("tst1", OP_BIT, 0);
155266e63ce3Schristos op0 = State.regs[ OP[0] ];
155366e63ce3Schristos op1 = OP[1] & 0x7;
155466e63ce3Schristos temp = EXTEND16 (OP[2]);
155566e63ce3Schristos op2 = temp;
155666e63ce3Schristos temp = load_mem (op0 + op2, 1);
155766e63ce3Schristos PSW &= ~PSW_Z;
155866e63ce3Schristos if ((temp & (1 << op1)) == 0)
155966e63ce3Schristos PSW |= PSW_Z;
156066e63ce3Schristos trace_output (OP_BIT);
156166e63ce3Schristos
156266e63ce3Schristos return 4;
156366e63ce3Schristos }
156466e63ce3Schristos
156566e63ce3Schristos /* di */
156666e63ce3Schristos int
OP_16007E0(void)1567ed6a76a9Schristos OP_16007E0 (void)
156866e63ce3Schristos {
156966e63ce3Schristos trace_input ("di", OP_NONE, 0);
157066e63ce3Schristos PSW |= PSW_ID;
157166e63ce3Schristos trace_output (OP_NONE);
157266e63ce3Schristos
157366e63ce3Schristos return 4;
157466e63ce3Schristos }
157566e63ce3Schristos
157666e63ce3Schristos /* ei */
157766e63ce3Schristos int
OP_16087E0(void)1578ed6a76a9Schristos OP_16087E0 (void)
157966e63ce3Schristos {
158066e63ce3Schristos trace_input ("ei", OP_NONE, 0);
158166e63ce3Schristos PSW &= ~PSW_ID;
158266e63ce3Schristos trace_output (OP_NONE);
158366e63ce3Schristos
158466e63ce3Schristos return 4;
158566e63ce3Schristos }
158666e63ce3Schristos
158766e63ce3Schristos /* halt */
158866e63ce3Schristos int
OP_12007E0(void)1589ed6a76a9Schristos OP_12007E0 (void)
159066e63ce3Schristos {
159166e63ce3Schristos trace_input ("halt", OP_NONE, 0);
159266e63ce3Schristos /* FIXME this should put processor into a mode where NMI still handled */
159366e63ce3Schristos trace_output (OP_NONE);
159466e63ce3Schristos sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC,
159566e63ce3Schristos sim_stopped, SIM_SIGTRAP);
159666e63ce3Schristos return 0;
159766e63ce3Schristos }
159866e63ce3Schristos
159966e63ce3Schristos /* trap */
160066e63ce3Schristos int
OP_10007E0(void)1601ed6a76a9Schristos OP_10007E0 (void)
160266e63ce3Schristos {
160366e63ce3Schristos trace_input ("trap", OP_TRAP, 0);
160466e63ce3Schristos trace_output (OP_TRAP);
160566e63ce3Schristos
160666e63ce3Schristos /* Trap 31 is used for simulating OS I/O functions */
160766e63ce3Schristos
160866e63ce3Schristos if (OP[0] == 31)
160966e63ce3Schristos {
161066e63ce3Schristos int save_errno = errno;
161166e63ce3Schristos errno = 0;
161266e63ce3Schristos
161366e63ce3Schristos /* Registers passed to trap 0 */
161466e63ce3Schristos
161566e63ce3Schristos #define FUNC State.regs[6] /* function number, return value */
161666e63ce3Schristos #define PARM1 State.regs[7] /* optional parm 1 */
161766e63ce3Schristos #define PARM2 State.regs[8] /* optional parm 2 */
161866e63ce3Schristos #define PARM3 State.regs[9] /* optional parm 3 */
161966e63ce3Schristos
162066e63ce3Schristos /* Registers set by trap 0 */
162166e63ce3Schristos
162266e63ce3Schristos #define RETVAL State.regs[10] /* return value */
162366e63ce3Schristos #define RETERR State.regs[11] /* return error code */
162466e63ce3Schristos
162566e63ce3Schristos /* Turn a pointer in a register into a pointer into real memory. */
162666e63ce3Schristos
162766e63ce3Schristos #define MEMPTR(x) (map (x))
162866e63ce3Schristos
162966e63ce3Schristos RETERR = 0;
163066e63ce3Schristos
163166e63ce3Schristos switch (FUNC)
163266e63ce3Schristos {
163366e63ce3Schristos
163466e63ce3Schristos #ifdef HAVE_FORK
163566e63ce3Schristos #ifdef TARGET_SYS_fork
163666e63ce3Schristos case TARGET_SYS_fork:
163766e63ce3Schristos RETVAL = fork ();
163866e63ce3Schristos RETERR = errno;
163966e63ce3Schristos break;
164066e63ce3Schristos #endif
164166e63ce3Schristos #endif
164266e63ce3Schristos
164366e63ce3Schristos #ifdef HAVE_EXECVE
164466e63ce3Schristos #ifdef TARGET_SYS_execv
164566e63ce3Schristos case TARGET_SYS_execve:
164666e63ce3Schristos {
164766e63ce3Schristos char *path = fetch_str (simulator, PARM1);
164866e63ce3Schristos char **argv = fetch_argv (simulator, PARM2);
164966e63ce3Schristos char **envp = fetch_argv (simulator, PARM3);
165066e63ce3Schristos RETVAL = execve (path, argv, envp);
165166e63ce3Schristos free (path);
165266e63ce3Schristos freeargv (argv);
165366e63ce3Schristos freeargv (envp);
165466e63ce3Schristos RETERR = errno;
165566e63ce3Schristos break;
165666e63ce3Schristos }
165766e63ce3Schristos #endif
165866e63ce3Schristos #endif
165966e63ce3Schristos
166066e63ce3Schristos #if HAVE_EXECV
166166e63ce3Schristos #ifdef TARGET_SYS_execv
166266e63ce3Schristos case TARGET_SYS_execv:
166366e63ce3Schristos {
166466e63ce3Schristos char *path = fetch_str (simulator, PARM1);
166566e63ce3Schristos char **argv = fetch_argv (simulator, PARM2);
166666e63ce3Schristos RETVAL = execv (path, argv);
166766e63ce3Schristos free (path);
166866e63ce3Schristos freeargv (argv);
166966e63ce3Schristos RETERR = errno;
167066e63ce3Schristos break;
167166e63ce3Schristos }
167266e63ce3Schristos #endif
167366e63ce3Schristos #endif
167466e63ce3Schristos
167566e63ce3Schristos #if 0
167666e63ce3Schristos #ifdef TARGET_SYS_pipe
167766e63ce3Schristos case TARGET_SYS_pipe:
167866e63ce3Schristos {
167966e63ce3Schristos reg_t buf;
168066e63ce3Schristos int host_fd[2];
168166e63ce3Schristos
168266e63ce3Schristos buf = PARM1;
168366e63ce3Schristos RETVAL = pipe (host_fd);
168466e63ce3Schristos SW (buf, host_fd[0]);
168566e63ce3Schristos buf += sizeof (uint16);
168666e63ce3Schristos SW (buf, host_fd[1]);
168766e63ce3Schristos RETERR = errno;
168866e63ce3Schristos }
168966e63ce3Schristos break;
169066e63ce3Schristos #endif
169166e63ce3Schristos #endif
169266e63ce3Schristos
169366e63ce3Schristos #if 0
169466e63ce3Schristos #ifdef TARGET_SYS_wait
169566e63ce3Schristos case TARGET_SYS_wait:
169666e63ce3Schristos {
169766e63ce3Schristos int status;
169866e63ce3Schristos
169966e63ce3Schristos RETVAL = wait (&status);
170066e63ce3Schristos SW (PARM1, status);
170166e63ce3Schristos RETERR = errno;
170266e63ce3Schristos }
170366e63ce3Schristos break;
170466e63ce3Schristos #endif
170566e63ce3Schristos #endif
170666e63ce3Schristos
170766e63ce3Schristos #ifdef TARGET_SYS_read
170866e63ce3Schristos case TARGET_SYS_read:
170966e63ce3Schristos {
171066e63ce3Schristos char *buf = zalloc (PARM3);
171166e63ce3Schristos RETVAL = sim_io_read (simulator, PARM1, buf, PARM3);
1712ed6a76a9Schristos sim_write (simulator, PARM2, (unsigned char *) buf, PARM3);
171366e63ce3Schristos free (buf);
171466e63ce3Schristos if ((int) RETVAL < 0)
171566e63ce3Schristos RETERR = sim_io_get_errno (simulator);
171666e63ce3Schristos break;
171766e63ce3Schristos }
171866e63ce3Schristos #endif
171966e63ce3Schristos
172066e63ce3Schristos #ifdef TARGET_SYS_write
172166e63ce3Schristos case TARGET_SYS_write:
172266e63ce3Schristos {
172366e63ce3Schristos char *buf = zalloc (PARM3);
1724ed6a76a9Schristos sim_read (simulator, PARM2, (unsigned char *) buf, PARM3);
172566e63ce3Schristos if (PARM1 == 1)
172666e63ce3Schristos RETVAL = sim_io_write_stdout (simulator, buf, PARM3);
172766e63ce3Schristos else
172866e63ce3Schristos RETVAL = sim_io_write (simulator, PARM1, buf, PARM3);
172966e63ce3Schristos free (buf);
173066e63ce3Schristos if ((int) RETVAL < 0)
173166e63ce3Schristos RETERR = sim_io_get_errno (simulator);
173266e63ce3Schristos break;
173366e63ce3Schristos }
173466e63ce3Schristos #endif
173566e63ce3Schristos
173666e63ce3Schristos #ifdef TARGET_SYS_lseek
173766e63ce3Schristos case TARGET_SYS_lseek:
173866e63ce3Schristos RETVAL = sim_io_lseek (simulator, PARM1, PARM2, PARM3);
173966e63ce3Schristos if ((int) RETVAL < 0)
174066e63ce3Schristos RETERR = sim_io_get_errno (simulator);
174166e63ce3Schristos break;
174266e63ce3Schristos #endif
174366e63ce3Schristos
174466e63ce3Schristos #ifdef TARGET_SYS_close
174566e63ce3Schristos case TARGET_SYS_close:
174666e63ce3Schristos RETVAL = sim_io_close (simulator, PARM1);
174766e63ce3Schristos if ((int) RETVAL < 0)
174866e63ce3Schristos RETERR = sim_io_get_errno (simulator);
174966e63ce3Schristos break;
175066e63ce3Schristos #endif
175166e63ce3Schristos
175266e63ce3Schristos #ifdef TARGET_SYS_open
175366e63ce3Schristos case TARGET_SYS_open:
175466e63ce3Schristos {
175566e63ce3Schristos char *buf = fetch_str (simulator, PARM1);
175666e63ce3Schristos RETVAL = sim_io_open (simulator, buf, PARM2);
175766e63ce3Schristos free (buf);
175866e63ce3Schristos if ((int) RETVAL < 0)
175966e63ce3Schristos RETERR = sim_io_get_errno (simulator);
176066e63ce3Schristos break;
176166e63ce3Schristos }
176266e63ce3Schristos #endif
176366e63ce3Schristos
176466e63ce3Schristos #ifdef TARGET_SYS_exit
176566e63ce3Schristos case TARGET_SYS_exit:
176666e63ce3Schristos if ((PARM1 & 0xffff0000) == 0xdead0000 && (PARM1 & 0xffff) != 0)
176766e63ce3Schristos /* get signal encoded by kill */
176866e63ce3Schristos sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC,
176966e63ce3Schristos sim_signalled, PARM1 & 0xffff);
177066e63ce3Schristos else if (PARM1 == 0xdead)
177166e63ce3Schristos /* old libraries */
177266e63ce3Schristos sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC,
177366e63ce3Schristos sim_stopped, SIM_SIGABRT);
177466e63ce3Schristos else
177566e63ce3Schristos /* PARM1 has exit status */
177666e63ce3Schristos sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC,
177766e63ce3Schristos sim_exited, PARM1);
177866e63ce3Schristos break;
177966e63ce3Schristos #endif
178066e63ce3Schristos
178166e63ce3Schristos #ifdef TARGET_SYS_stat
178266e63ce3Schristos case TARGET_SYS_stat: /* added at hmsi */
178366e63ce3Schristos /* stat system call */
178466e63ce3Schristos {
178566e63ce3Schristos struct stat host_stat;
178666e63ce3Schristos reg_t buf;
178766e63ce3Schristos char *path = fetch_str (simulator, PARM1);
178866e63ce3Schristos
178966e63ce3Schristos RETVAL = sim_io_stat (simulator, path, &host_stat);
179066e63ce3Schristos
179166e63ce3Schristos free (path);
179266e63ce3Schristos buf = PARM2;
179366e63ce3Schristos
179466e63ce3Schristos /* Just wild-assed guesses. */
179566e63ce3Schristos store_mem (buf, 2, host_stat.st_dev);
179666e63ce3Schristos store_mem (buf + 2, 2, host_stat.st_ino);
179766e63ce3Schristos store_mem (buf + 4, 4, host_stat.st_mode);
179866e63ce3Schristos store_mem (buf + 8, 2, host_stat.st_nlink);
179966e63ce3Schristos store_mem (buf + 10, 2, host_stat.st_uid);
180066e63ce3Schristos store_mem (buf + 12, 2, host_stat.st_gid);
180166e63ce3Schristos store_mem (buf + 14, 2, host_stat.st_rdev);
180266e63ce3Schristos store_mem (buf + 16, 4, host_stat.st_size);
180366e63ce3Schristos store_mem (buf + 20, 4, host_stat.st_atime);
180466e63ce3Schristos store_mem (buf + 28, 4, host_stat.st_mtime);
180566e63ce3Schristos store_mem (buf + 36, 4, host_stat.st_ctime);
180666e63ce3Schristos
180766e63ce3Schristos if ((int) RETVAL < 0)
180866e63ce3Schristos RETERR = sim_io_get_errno (simulator);
180966e63ce3Schristos }
181066e63ce3Schristos break;
181166e63ce3Schristos #endif
181266e63ce3Schristos
181366e63ce3Schristos #ifdef TARGET_SYS_fstat
181466e63ce3Schristos case TARGET_SYS_fstat:
181566e63ce3Schristos /* fstat system call */
181666e63ce3Schristos {
181766e63ce3Schristos struct stat host_stat;
181866e63ce3Schristos reg_t buf;
181966e63ce3Schristos
182066e63ce3Schristos RETVAL = sim_io_fstat (simulator, PARM1, &host_stat);
182166e63ce3Schristos
182266e63ce3Schristos buf = PARM2;
182366e63ce3Schristos
182466e63ce3Schristos /* Just wild-assed guesses. */
182566e63ce3Schristos store_mem (buf, 2, host_stat.st_dev);
182666e63ce3Schristos store_mem (buf + 2, 2, host_stat.st_ino);
182766e63ce3Schristos store_mem (buf + 4, 4, host_stat.st_mode);
182866e63ce3Schristos store_mem (buf + 8, 2, host_stat.st_nlink);
182966e63ce3Schristos store_mem (buf + 10, 2, host_stat.st_uid);
183066e63ce3Schristos store_mem (buf + 12, 2, host_stat.st_gid);
183166e63ce3Schristos store_mem (buf + 14, 2, host_stat.st_rdev);
183266e63ce3Schristos store_mem (buf + 16, 4, host_stat.st_size);
183366e63ce3Schristos store_mem (buf + 20, 4, host_stat.st_atime);
183466e63ce3Schristos store_mem (buf + 28, 4, host_stat.st_mtime);
183566e63ce3Schristos store_mem (buf + 36, 4, host_stat.st_ctime);
183666e63ce3Schristos
183766e63ce3Schristos if ((int) RETVAL < 0)
183866e63ce3Schristos RETERR = sim_io_get_errno (simulator);
183966e63ce3Schristos }
184066e63ce3Schristos break;
184166e63ce3Schristos #endif
184266e63ce3Schristos
184366e63ce3Schristos #ifdef TARGET_SYS_rename
184466e63ce3Schristos case TARGET_SYS_rename:
184566e63ce3Schristos {
184666e63ce3Schristos char *oldpath = fetch_str (simulator, PARM1);
184766e63ce3Schristos char *newpath = fetch_str (simulator, PARM2);
184866e63ce3Schristos RETVAL = sim_io_rename (simulator, oldpath, newpath);
184966e63ce3Schristos free (oldpath);
185066e63ce3Schristos free (newpath);
185166e63ce3Schristos if ((int) RETVAL < 0)
185266e63ce3Schristos RETERR = sim_io_get_errno (simulator);
185366e63ce3Schristos }
185466e63ce3Schristos break;
185566e63ce3Schristos #endif
185666e63ce3Schristos
185766e63ce3Schristos #ifdef TARGET_SYS_unlink
185866e63ce3Schristos case TARGET_SYS_unlink:
185966e63ce3Schristos {
186066e63ce3Schristos char *path = fetch_str (simulator, PARM1);
186166e63ce3Schristos RETVAL = sim_io_unlink (simulator, path);
186266e63ce3Schristos free (path);
186366e63ce3Schristos if ((int) RETVAL < 0)
186466e63ce3Schristos RETERR = sim_io_get_errno (simulator);
186566e63ce3Schristos }
186666e63ce3Schristos break;
186766e63ce3Schristos #endif
186866e63ce3Schristos
186966e63ce3Schristos #ifdef HAVE_CHOWN
187066e63ce3Schristos #ifdef TARGET_SYS_chown
187166e63ce3Schristos case TARGET_SYS_chown:
187266e63ce3Schristos {
187366e63ce3Schristos char *path = fetch_str (simulator, PARM1);
187466e63ce3Schristos RETVAL = chown (path, PARM2, PARM3);
187566e63ce3Schristos free (path);
187666e63ce3Schristos RETERR = errno;
187766e63ce3Schristos }
187866e63ce3Schristos break;
187966e63ce3Schristos #endif
188066e63ce3Schristos #endif
188166e63ce3Schristos
188266e63ce3Schristos #if HAVE_CHMOD
188366e63ce3Schristos #ifdef TARGET_SYS_chmod
188466e63ce3Schristos case TARGET_SYS_chmod:
188566e63ce3Schristos {
188666e63ce3Schristos char *path = fetch_str (simulator, PARM1);
188766e63ce3Schristos RETVAL = chmod (path, PARM2);
188866e63ce3Schristos free (path);
188966e63ce3Schristos RETERR = errno;
189066e63ce3Schristos }
189166e63ce3Schristos break;
189266e63ce3Schristos #endif
189366e63ce3Schristos #endif
189466e63ce3Schristos
189566e63ce3Schristos #ifdef TARGET_SYS_time
189666e63ce3Schristos #if HAVE_TIME
189766e63ce3Schristos case TARGET_SYS_time:
189866e63ce3Schristos {
189966e63ce3Schristos time_t now;
190066e63ce3Schristos RETVAL = time (&now);
190166e63ce3Schristos store_mem (PARM1, 4, now);
190266e63ce3Schristos RETERR = errno;
190366e63ce3Schristos }
190466e63ce3Schristos break;
190566e63ce3Schristos #endif
190666e63ce3Schristos #endif
190766e63ce3Schristos
190866e63ce3Schristos #if !defined(__GO32__) && !defined(_WIN32)
190966e63ce3Schristos #ifdef TARGET_SYS_times
191066e63ce3Schristos case TARGET_SYS_times:
191166e63ce3Schristos {
191266e63ce3Schristos struct tms tms;
191366e63ce3Schristos RETVAL = times (&tms);
191466e63ce3Schristos store_mem (PARM1, 4, tms.tms_utime);
191566e63ce3Schristos store_mem (PARM1 + 4, 4, tms.tms_stime);
191666e63ce3Schristos store_mem (PARM1 + 8, 4, tms.tms_cutime);
191766e63ce3Schristos store_mem (PARM1 + 12, 4, tms.tms_cstime);
191866e63ce3Schristos reterr = errno;
191966e63ce3Schristos break;
192066e63ce3Schristos }
192166e63ce3Schristos #endif
192266e63ce3Schristos #endif
192366e63ce3Schristos
192466e63ce3Schristos #ifdef TARGET_SYS_gettimeofday
192566e63ce3Schristos #if !defined(__GO32__) && !defined(_WIN32)
192666e63ce3Schristos case TARGET_SYS_gettimeofday:
192766e63ce3Schristos {
192866e63ce3Schristos struct timeval t;
192966e63ce3Schristos struct timezone tz;
193066e63ce3Schristos RETVAL = gettimeofday (&t, &tz);
193166e63ce3Schristos store_mem (PARM1, 4, t.tv_sec);
193266e63ce3Schristos store_mem (PARM1 + 4, 4, t.tv_usec);
193366e63ce3Schristos store_mem (PARM2, 4, tz.tz_minuteswest);
193466e63ce3Schristos store_mem (PARM2 + 4, 4, tz.tz_dsttime);
193566e63ce3Schristos RETERR = errno;
193666e63ce3Schristos break;
193766e63ce3Schristos }
193866e63ce3Schristos #endif
193966e63ce3Schristos #endif
194066e63ce3Schristos
194166e63ce3Schristos #ifdef TARGET_SYS_utime
194266e63ce3Schristos #if HAVE_UTIME
194366e63ce3Schristos case TARGET_SYS_utime:
194466e63ce3Schristos {
194566e63ce3Schristos /* Cast the second argument to void *, to avoid type mismatch
194666e63ce3Schristos if a prototype is present. */
194766e63ce3Schristos sim_io_error (simulator, "Utime not supported");
194866e63ce3Schristos /* RETVAL = utime (path, (void *) MEMPTR (PARM2)); */
194966e63ce3Schristos }
195066e63ce3Schristos break;
195166e63ce3Schristos #endif
195266e63ce3Schristos #endif
195366e63ce3Schristos
195466e63ce3Schristos default:
195566e63ce3Schristos abort ();
195666e63ce3Schristos }
195766e63ce3Schristos errno = save_errno;
195866e63ce3Schristos
195966e63ce3Schristos return 4;
196066e63ce3Schristos }
196166e63ce3Schristos else
196266e63ce3Schristos { /* Trap 0 -> 30 */
196366e63ce3Schristos EIPC = PC + 4;
196466e63ce3Schristos EIPSW = PSW;
196566e63ce3Schristos /* Mask out EICC */
196666e63ce3Schristos ECR &= 0xffff0000;
196766e63ce3Schristos ECR |= 0x40 + OP[0];
196866e63ce3Schristos /* Flag that we are now doing exception processing. */
196966e63ce3Schristos PSW |= PSW_EP | PSW_ID;
197066e63ce3Schristos PC = (OP[0] < 0x10) ? 0x40 : 0x50;
197166e63ce3Schristos
197266e63ce3Schristos return 0;
197366e63ce3Schristos }
197466e63ce3Schristos }
197566e63ce3Schristos
197666e63ce3Schristos /* tst1 reg2, [reg1] */
197766e63ce3Schristos int
OP_E607E0(void)197866e63ce3Schristos OP_E607E0 (void)
197966e63ce3Schristos {
198066e63ce3Schristos int temp;
198166e63ce3Schristos
198266e63ce3Schristos trace_input ("tst1", OP_BIT, 1);
198366e63ce3Schristos
198466e63ce3Schristos temp = load_mem (State.regs[ OP[0] ], 1);
198566e63ce3Schristos
198666e63ce3Schristos PSW &= ~PSW_Z;
198766e63ce3Schristos if ((temp & (1 << (State.regs[ OP[1] ] & 0x7))) == 0)
198866e63ce3Schristos PSW |= PSW_Z;
198966e63ce3Schristos
199066e63ce3Schristos trace_output (OP_BIT);
199166e63ce3Schristos
199266e63ce3Schristos return 4;
199366e63ce3Schristos }
199466e63ce3Schristos
199566e63ce3Schristos /* mulu reg1, reg2, reg3 */
199666e63ce3Schristos int
OP_22207E0(void)199766e63ce3Schristos OP_22207E0 (void)
199866e63ce3Schristos {
199966e63ce3Schristos trace_input ("mulu", OP_REG_REG_REG, 0);
200066e63ce3Schristos
200166e63ce3Schristos Multiply64 (0, State.regs[ OP[0] ]);
200266e63ce3Schristos
200366e63ce3Schristos trace_output (OP_REG_REG_REG);
200466e63ce3Schristos
200566e63ce3Schristos return 4;
200666e63ce3Schristos }
200766e63ce3Schristos
200866e63ce3Schristos #define BIT_CHANGE_OP( name, binop ) \
200966e63ce3Schristos unsigned int bit; \
201066e63ce3Schristos unsigned int temp; \
201166e63ce3Schristos \
201266e63ce3Schristos trace_input (name, OP_BIT_CHANGE, 0); \
201366e63ce3Schristos \
201466e63ce3Schristos bit = 1 << (State.regs[ OP[1] ] & 0x7); \
201566e63ce3Schristos temp = load_mem (State.regs[ OP[0] ], 1); \
201666e63ce3Schristos \
201766e63ce3Schristos PSW &= ~PSW_Z; \
201866e63ce3Schristos if ((temp & bit) == 0) \
201966e63ce3Schristos PSW |= PSW_Z; \
202066e63ce3Schristos temp binop bit; \
202166e63ce3Schristos \
202266e63ce3Schristos store_mem (State.regs[ OP[0] ], 1, temp); \
202366e63ce3Schristos \
202466e63ce3Schristos trace_output (OP_BIT_CHANGE); \
202566e63ce3Schristos \
202666e63ce3Schristos return 4;
202766e63ce3Schristos
202866e63ce3Schristos /* clr1 reg2, [reg1] */
202966e63ce3Schristos int
OP_E407E0(void)203066e63ce3Schristos OP_E407E0 (void)
203166e63ce3Schristos {
203266e63ce3Schristos BIT_CHANGE_OP ("clr1", &= ~ );
203366e63ce3Schristos }
203466e63ce3Schristos
203566e63ce3Schristos /* not1 reg2, [reg1] */
203666e63ce3Schristos int
OP_E207E0(void)203766e63ce3Schristos OP_E207E0 (void)
203866e63ce3Schristos {
203966e63ce3Schristos BIT_CHANGE_OP ("not1", ^= );
204066e63ce3Schristos }
204166e63ce3Schristos
204266e63ce3Schristos /* set1 */
204366e63ce3Schristos int
OP_E007E0(void)204466e63ce3Schristos OP_E007E0 (void)
204566e63ce3Schristos {
204666e63ce3Schristos BIT_CHANGE_OP ("set1", |= );
204766e63ce3Schristos }
204866e63ce3Schristos
204966e63ce3Schristos /* sasf */
205066e63ce3Schristos int
OP_20007E0(void)205166e63ce3Schristos OP_20007E0 (void)
205266e63ce3Schristos {
205366e63ce3Schristos trace_input ("sasf", OP_EX1, 0);
205466e63ce3Schristos
205566e63ce3Schristos State.regs[ OP[1] ] = (State.regs[ OP[1] ] << 1) | condition_met (OP[0]);
205666e63ce3Schristos
205766e63ce3Schristos trace_output (OP_EX1);
205866e63ce3Schristos
205966e63ce3Schristos return 4;
206066e63ce3Schristos }
206166e63ce3Schristos
206266e63ce3Schristos /* This function is courtesy of Sugimoto at NEC, via Seow Tan
206366e63ce3Schristos (Soew_Tan@el.nec.com) */
206466e63ce3Schristos void
divun(unsigned int N,unsigned long int als,unsigned long int sfi,unsigned32 * quotient_ptr,unsigned32 * remainder_ptr,int * overflow_ptr)206566e63ce3Schristos divun
206666e63ce3Schristos (
206766e63ce3Schristos unsigned int N,
206866e63ce3Schristos unsigned long int als,
206966e63ce3Schristos unsigned long int sfi,
207066e63ce3Schristos unsigned32 /*unsigned long int*/ * quotient_ptr,
207166e63ce3Schristos unsigned32 /*unsigned long int*/ * remainder_ptr,
207266e63ce3Schristos int * overflow_ptr
207366e63ce3Schristos )
207466e63ce3Schristos {
207566e63ce3Schristos unsigned long ald = sfi >> (N - 1);
207666e63ce3Schristos unsigned long alo = als;
207766e63ce3Schristos unsigned int Q = 1;
207866e63ce3Schristos unsigned int C;
207966e63ce3Schristos unsigned int S = 0;
208066e63ce3Schristos unsigned int i;
208166e63ce3Schristos unsigned int R1 = 1;
208266e63ce3Schristos unsigned int DBZ = (als == 0) ? 1 : 0;
208366e63ce3Schristos unsigned long alt = Q ? ~als : als;
208466e63ce3Schristos
208566e63ce3Schristos /* 1st Loop */
208666e63ce3Schristos alo = ald + alt + Q;
208766e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
208866e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
208966e63ce3Schristos C = C ^ Q;
209066e63ce3Schristos Q = ~(C ^ S) & 1;
209166e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & Q);
209266e63ce3Schristos if ((S ^ (alo>>31)) && !C)
209366e63ce3Schristos {
209466e63ce3Schristos DBZ = 1;
209566e63ce3Schristos }
209666e63ce3Schristos S = alo >> 31;
209766e63ce3Schristos sfi = (sfi << (32-N+1)) | Q;
209866e63ce3Schristos ald = (alo << 1) | (sfi >> 31);
209966e63ce3Schristos
210066e63ce3Schristos /* 2nd - N-1th Loop */
210166e63ce3Schristos for (i = 2; i < N; i++)
210266e63ce3Schristos {
210366e63ce3Schristos alt = Q ? ~als : als;
210466e63ce3Schristos alo = ald + alt + Q;
210566e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
210666e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
210766e63ce3Schristos C = C ^ Q;
210866e63ce3Schristos Q = ~(C ^ S) & 1;
210966e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & Q);
211066e63ce3Schristos if ((S ^ (alo>>31)) && !C && !DBZ)
211166e63ce3Schristos {
211266e63ce3Schristos DBZ = 1;
211366e63ce3Schristos }
211466e63ce3Schristos S = alo >> 31;
211566e63ce3Schristos sfi = (sfi << 1) | Q;
211666e63ce3Schristos ald = (alo << 1) | (sfi >> 31);
211766e63ce3Schristos }
211866e63ce3Schristos
211966e63ce3Schristos /* Nth Loop */
212066e63ce3Schristos alt = Q ? ~als : als;
212166e63ce3Schristos alo = ald + alt + Q;
212266e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
212366e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
212466e63ce3Schristos C = C ^ Q;
212566e63ce3Schristos Q = ~(C ^ S) & 1;
212666e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & Q);
212766e63ce3Schristos if ((S ^ (alo>>31)) && !C)
212866e63ce3Schristos {
212966e63ce3Schristos DBZ = 1;
213066e63ce3Schristos }
213166e63ce3Schristos
213266e63ce3Schristos * quotient_ptr = (sfi << 1) | Q;
213366e63ce3Schristos * remainder_ptr = Q ? alo : (alo + als);
213466e63ce3Schristos * overflow_ptr = DBZ | R1;
213566e63ce3Schristos }
213666e63ce3Schristos
213766e63ce3Schristos /* This function is courtesy of Sugimoto at NEC, via Seow Tan (Soew_Tan@el.nec.com) */
213866e63ce3Schristos void
divn(unsigned int N,unsigned long int als,unsigned long int sfi,signed32 * quotient_ptr,signed32 * remainder_ptr,int * overflow_ptr)213966e63ce3Schristos divn
214066e63ce3Schristos (
214166e63ce3Schristos unsigned int N,
214266e63ce3Schristos unsigned long int als,
214366e63ce3Schristos unsigned long int sfi,
214466e63ce3Schristos signed32 /*signed long int*/ * quotient_ptr,
214566e63ce3Schristos signed32 /*signed long int*/ * remainder_ptr,
214666e63ce3Schristos int * overflow_ptr
214766e63ce3Schristos )
214866e63ce3Schristos {
214966e63ce3Schristos unsigned long ald = (signed long) sfi >> (N - 1);
215066e63ce3Schristos unsigned long alo = als;
215166e63ce3Schristos unsigned int SS = als >> 31;
215266e63ce3Schristos unsigned int SD = sfi >> 31;
215366e63ce3Schristos unsigned int R1 = 1;
215466e63ce3Schristos unsigned int OV;
215566e63ce3Schristos unsigned int DBZ = als == 0 ? 1 : 0;
215666e63ce3Schristos unsigned int Q = ~(SS ^ SD) & 1;
215766e63ce3Schristos unsigned int C;
215866e63ce3Schristos unsigned int S;
215966e63ce3Schristos unsigned int i;
216066e63ce3Schristos unsigned long alt = Q ? ~als : als;
216166e63ce3Schristos
216266e63ce3Schristos
216366e63ce3Schristos /* 1st Loop */
216466e63ce3Schristos
216566e63ce3Schristos alo = ald + alt + Q;
216666e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
216766e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
216866e63ce3Schristos Q = C ^ SS;
216966e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
217066e63ce3Schristos S = alo >> 31;
217166e63ce3Schristos sfi = (sfi << (32-N+1)) | Q;
217266e63ce3Schristos ald = (alo << 1) | (sfi >> 31);
217366e63ce3Schristos if ((alo >> 31) ^ (ald >> 31))
217466e63ce3Schristos {
217566e63ce3Schristos DBZ = 1;
217666e63ce3Schristos }
217766e63ce3Schristos
217866e63ce3Schristos /* 2nd - N-1th Loop */
217966e63ce3Schristos
218066e63ce3Schristos for (i = 2; i < N; i++)
218166e63ce3Schristos {
218266e63ce3Schristos alt = Q ? ~als : als;
218366e63ce3Schristos alo = ald + alt + Q;
218466e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
218566e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
218666e63ce3Schristos Q = C ^ SS;
218766e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
218866e63ce3Schristos S = alo >> 31;
218966e63ce3Schristos sfi = (sfi << 1) | Q;
219066e63ce3Schristos ald = (alo << 1) | (sfi >> 31);
219166e63ce3Schristos if ((alo >> 31) ^ (ald >> 31))
219266e63ce3Schristos {
219366e63ce3Schristos DBZ = 1;
219466e63ce3Schristos }
219566e63ce3Schristos }
219666e63ce3Schristos
219766e63ce3Schristos /* Nth Loop */
219866e63ce3Schristos alt = Q ? ~als : als;
219966e63ce3Schristos alo = ald + alt + Q;
220066e63ce3Schristos C = (((alt >> 31) & (ald >> 31))
220166e63ce3Schristos | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
220266e63ce3Schristos Q = C ^ SS;
220366e63ce3Schristos R1 = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
220466e63ce3Schristos sfi = (sfi << (32-N+1));
220566e63ce3Schristos ald = alo;
220666e63ce3Schristos
220766e63ce3Schristos /* End */
220866e63ce3Schristos if (alo != 0)
220966e63ce3Schristos {
221066e63ce3Schristos alt = Q ? ~als : als;
221166e63ce3Schristos alo = ald + alt + Q;
221266e63ce3Schristos }
221366e63ce3Schristos R1 = R1 & ((~alo >> 31) ^ SD);
221466e63ce3Schristos if ((alo != 0) && ((Q ^ (SS ^ SD)) ^ R1)) alo = ald;
221566e63ce3Schristos if (N != 32)
221666e63ce3Schristos ald = sfi = (long) ((sfi >> 1) | (SS ^ SD) << 31) >> (32-N-1) | Q;
221766e63ce3Schristos else
221866e63ce3Schristos ald = sfi = sfi | Q;
221966e63ce3Schristos
222066e63ce3Schristos OV = DBZ | ((alo == 0) ? 0 : R1);
222166e63ce3Schristos
222266e63ce3Schristos * remainder_ptr = alo;
222366e63ce3Schristos
222466e63ce3Schristos /* Adj */
222566e63ce3Schristos if (((alo != 0) && ((SS ^ SD) ^ R1))
222666e63ce3Schristos || ((alo == 0) && (SS ^ R1)))
222766e63ce3Schristos alo = ald + 1;
222866e63ce3Schristos else
222966e63ce3Schristos alo = ald;
223066e63ce3Schristos
223166e63ce3Schristos OV = (DBZ | R1) ? OV : ((alo >> 31) & (~ald >> 31));
223266e63ce3Schristos
223366e63ce3Schristos * quotient_ptr = alo;
223466e63ce3Schristos * overflow_ptr = OV;
223566e63ce3Schristos }
223666e63ce3Schristos
223766e63ce3Schristos /* sdivun imm5, reg1, reg2, reg3 */
223866e63ce3Schristos int
OP_1C207E0(void)223966e63ce3Schristos OP_1C207E0 (void)
224066e63ce3Schristos {
224166e63ce3Schristos unsigned32 /*unsigned long int*/ quotient;
224266e63ce3Schristos unsigned32 /*unsigned long int*/ remainder;
224366e63ce3Schristos unsigned long int divide_by;
224466e63ce3Schristos unsigned long int divide_this;
224566e63ce3Schristos int overflow = 0;
224666e63ce3Schristos unsigned int imm5;
224766e63ce3Schristos
224866e63ce3Schristos trace_input ("sdivun", OP_IMM_REG_REG_REG, 0);
224966e63ce3Schristos
225066e63ce3Schristos imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
225166e63ce3Schristos
225266e63ce3Schristos divide_by = State.regs[ OP[0] ];
225366e63ce3Schristos divide_this = State.regs[ OP[1] ] << imm5;
225466e63ce3Schristos
225566e63ce3Schristos divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
225666e63ce3Schristos
225766e63ce3Schristos State.regs[ OP[1] ] = quotient;
225866e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder;
225966e63ce3Schristos
226066e63ce3Schristos /* Set condition codes. */
226166e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
226266e63ce3Schristos
226366e63ce3Schristos if (overflow) PSW |= PSW_OV;
226466e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
226566e63ce3Schristos if (quotient & 0x80000000) PSW |= PSW_S;
226666e63ce3Schristos
226766e63ce3Schristos trace_output (OP_IMM_REG_REG_REG);
226866e63ce3Schristos
226966e63ce3Schristos return 4;
227066e63ce3Schristos }
227166e63ce3Schristos
227266e63ce3Schristos /* sdivn imm5, reg1, reg2, reg3 */
227366e63ce3Schristos int
OP_1C007E0(void)227466e63ce3Schristos OP_1C007E0 (void)
227566e63ce3Schristos {
227666e63ce3Schristos signed32 /*signed long int*/ quotient;
227766e63ce3Schristos signed32 /*signed long int*/ remainder;
227866e63ce3Schristos signed long int divide_by;
227966e63ce3Schristos signed long int divide_this;
228066e63ce3Schristos int overflow = 0;
228166e63ce3Schristos unsigned int imm5;
228266e63ce3Schristos
228366e63ce3Schristos trace_input ("sdivn", OP_IMM_REG_REG_REG, 0);
228466e63ce3Schristos
228566e63ce3Schristos imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
228666e63ce3Schristos
228766e63ce3Schristos divide_by = (signed32) State.regs[ OP[0] ];
228866e63ce3Schristos divide_this = (signed32) (State.regs[ OP[1] ] << imm5);
228966e63ce3Schristos
229066e63ce3Schristos divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
229166e63ce3Schristos
229266e63ce3Schristos State.regs[ OP[1] ] = quotient;
229366e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder;
229466e63ce3Schristos
229566e63ce3Schristos /* Set condition codes. */
229666e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
229766e63ce3Schristos
229866e63ce3Schristos if (overflow) PSW |= PSW_OV;
229966e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
230066e63ce3Schristos if (quotient < 0) PSW |= PSW_S;
230166e63ce3Schristos
230266e63ce3Schristos trace_output (OP_IMM_REG_REG_REG);
230366e63ce3Schristos
230466e63ce3Schristos return 4;
230566e63ce3Schristos }
230666e63ce3Schristos
230766e63ce3Schristos /* sdivhun imm5, reg1, reg2, reg3 */
230866e63ce3Schristos int
OP_18207E0(void)230966e63ce3Schristos OP_18207E0 (void)
231066e63ce3Schristos {
231166e63ce3Schristos unsigned32 /*unsigned long int*/ quotient;
231266e63ce3Schristos unsigned32 /*unsigned long int*/ remainder;
231366e63ce3Schristos unsigned long int divide_by;
231466e63ce3Schristos unsigned long int divide_this;
231566e63ce3Schristos int overflow = 0;
231666e63ce3Schristos unsigned int imm5;
231766e63ce3Schristos
231866e63ce3Schristos trace_input ("sdivhun", OP_IMM_REG_REG_REG, 0);
231966e63ce3Schristos
232066e63ce3Schristos imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
232166e63ce3Schristos
232266e63ce3Schristos divide_by = State.regs[ OP[0] ] & 0xffff;
232366e63ce3Schristos divide_this = State.regs[ OP[1] ] << imm5;
232466e63ce3Schristos
232566e63ce3Schristos divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
232666e63ce3Schristos
232766e63ce3Schristos State.regs[ OP[1] ] = quotient;
232866e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder;
232966e63ce3Schristos
233066e63ce3Schristos /* Set condition codes. */
233166e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
233266e63ce3Schristos
233366e63ce3Schristos if (overflow) PSW |= PSW_OV;
233466e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
233566e63ce3Schristos if (quotient & 0x80000000) PSW |= PSW_S;
233666e63ce3Schristos
233766e63ce3Schristos trace_output (OP_IMM_REG_REG_REG);
233866e63ce3Schristos
233966e63ce3Schristos return 4;
234066e63ce3Schristos }
234166e63ce3Schristos
234266e63ce3Schristos /* sdivhn imm5, reg1, reg2, reg3 */
234366e63ce3Schristos int
OP_18007E0(void)234466e63ce3Schristos OP_18007E0 (void)
234566e63ce3Schristos {
234666e63ce3Schristos signed32 /*signed long int*/ quotient;
234766e63ce3Schristos signed32 /*signed long int*/ remainder;
234866e63ce3Schristos signed long int divide_by;
234966e63ce3Schristos signed long int divide_this;
235066e63ce3Schristos int overflow = 0;
235166e63ce3Schristos unsigned int imm5;
235266e63ce3Schristos
235366e63ce3Schristos trace_input ("sdivhn", OP_IMM_REG_REG_REG, 0);
235466e63ce3Schristos
235566e63ce3Schristos imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
235666e63ce3Schristos
235766e63ce3Schristos divide_by = EXTEND16 (State.regs[ OP[0] ]);
235866e63ce3Schristos divide_this = (signed32) (State.regs[ OP[1] ] << imm5);
235966e63ce3Schristos
236066e63ce3Schristos divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
236166e63ce3Schristos
236266e63ce3Schristos State.regs[ OP[1] ] = quotient;
236366e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder;
236466e63ce3Schristos
236566e63ce3Schristos /* Set condition codes. */
236666e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
236766e63ce3Schristos
236866e63ce3Schristos if (overflow) PSW |= PSW_OV;
236966e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
237066e63ce3Schristos if (quotient < 0) PSW |= PSW_S;
237166e63ce3Schristos
237266e63ce3Schristos trace_output (OP_IMM_REG_REG_REG);
237366e63ce3Schristos
237466e63ce3Schristos return 4;
237566e63ce3Schristos }
237666e63ce3Schristos
237766e63ce3Schristos /* divu reg1, reg2, reg3 */
237866e63ce3Schristos int
OP_2C207E0(void)237966e63ce3Schristos OP_2C207E0 (void)
238066e63ce3Schristos {
238166e63ce3Schristos unsigned long int quotient;
238266e63ce3Schristos unsigned long int remainder;
238366e63ce3Schristos unsigned long int divide_by;
238466e63ce3Schristos unsigned long int divide_this;
238566e63ce3Schristos int overflow = 0;
238666e63ce3Schristos
238766e63ce3Schristos trace_input ("divu", OP_REG_REG_REG, 0);
238866e63ce3Schristos
238966e63ce3Schristos /* Compute the result. */
239066e63ce3Schristos
239166e63ce3Schristos divide_by = State.regs[ OP[0] ];
239266e63ce3Schristos divide_this = State.regs[ OP[1] ];
239366e63ce3Schristos
239466e63ce3Schristos if (divide_by == 0)
239566e63ce3Schristos {
239666e63ce3Schristos PSW |= PSW_OV;
239766e63ce3Schristos }
239866e63ce3Schristos else
239966e63ce3Schristos {
240066e63ce3Schristos State.regs[ OP[1] ] = quotient = divide_this / divide_by;
240166e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
240266e63ce3Schristos
240366e63ce3Schristos /* Set condition codes. */
240466e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
240566e63ce3Schristos
240666e63ce3Schristos if (overflow) PSW |= PSW_OV;
240766e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
240866e63ce3Schristos if (quotient & 0x80000000) PSW |= PSW_S;
240966e63ce3Schristos }
241066e63ce3Schristos
241166e63ce3Schristos trace_output (OP_REG_REG_REG);
241266e63ce3Schristos
241366e63ce3Schristos return 4;
241466e63ce3Schristos }
241566e63ce3Schristos
241666e63ce3Schristos /* div reg1, reg2, reg3 */
241766e63ce3Schristos int
OP_2C007E0(void)241866e63ce3Schristos OP_2C007E0 (void)
241966e63ce3Schristos {
242066e63ce3Schristos signed long int quotient;
242166e63ce3Schristos signed long int remainder;
242266e63ce3Schristos signed long int divide_by;
242366e63ce3Schristos signed long int divide_this;
242466e63ce3Schristos
242566e63ce3Schristos trace_input ("div", OP_REG_REG_REG, 0);
242666e63ce3Schristos
242766e63ce3Schristos /* Compute the result. */
242866e63ce3Schristos
242966e63ce3Schristos divide_by = (signed32) State.regs[ OP[0] ];
243066e63ce3Schristos divide_this = State.regs[ OP[1] ];
243166e63ce3Schristos
243266e63ce3Schristos if (divide_by == 0)
243366e63ce3Schristos {
243466e63ce3Schristos PSW |= PSW_OV;
243566e63ce3Schristos }
243666e63ce3Schristos else if (divide_by == -1 && divide_this == (1L << 31))
243766e63ce3Schristos {
243866e63ce3Schristos PSW &= ~PSW_Z;
243966e63ce3Schristos PSW |= PSW_OV | PSW_S;
244066e63ce3Schristos State.regs[ OP[1] ] = (1 << 31);
244166e63ce3Schristos State.regs[ OP[2] >> 11 ] = 0;
244266e63ce3Schristos }
244366e63ce3Schristos else
244466e63ce3Schristos {
244566e63ce3Schristos divide_this = (signed32) divide_this;
244666e63ce3Schristos State.regs[ OP[1] ] = quotient = divide_this / divide_by;
244766e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
244866e63ce3Schristos
244966e63ce3Schristos /* Set condition codes. */
245066e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
245166e63ce3Schristos
245266e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
245366e63ce3Schristos if (quotient < 0) PSW |= PSW_S;
245466e63ce3Schristos }
245566e63ce3Schristos
245666e63ce3Schristos trace_output (OP_REG_REG_REG);
245766e63ce3Schristos
245866e63ce3Schristos return 4;
245966e63ce3Schristos }
246066e63ce3Schristos
246166e63ce3Schristos /* divhu reg1, reg2, reg3 */
246266e63ce3Schristos int
OP_28207E0(void)246366e63ce3Schristos OP_28207E0 (void)
246466e63ce3Schristos {
246566e63ce3Schristos unsigned long int quotient;
246666e63ce3Schristos unsigned long int remainder;
246766e63ce3Schristos unsigned long int divide_by;
246866e63ce3Schristos unsigned long int divide_this;
246966e63ce3Schristos int overflow = 0;
247066e63ce3Schristos
247166e63ce3Schristos trace_input ("divhu", OP_REG_REG_REG, 0);
247266e63ce3Schristos
247366e63ce3Schristos /* Compute the result. */
247466e63ce3Schristos
247566e63ce3Schristos divide_by = State.regs[ OP[0] ] & 0xffff;
247666e63ce3Schristos divide_this = State.regs[ OP[1] ];
247766e63ce3Schristos
247866e63ce3Schristos if (divide_by == 0)
247966e63ce3Schristos {
248066e63ce3Schristos PSW |= PSW_OV;
248166e63ce3Schristos }
248266e63ce3Schristos else
248366e63ce3Schristos {
248466e63ce3Schristos State.regs[ OP[1] ] = quotient = divide_this / divide_by;
248566e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
248666e63ce3Schristos
248766e63ce3Schristos /* Set condition codes. */
248866e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
248966e63ce3Schristos
249066e63ce3Schristos if (overflow) PSW |= PSW_OV;
249166e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
249266e63ce3Schristos if (quotient & 0x80000000) PSW |= PSW_S;
249366e63ce3Schristos }
249466e63ce3Schristos
249566e63ce3Schristos trace_output (OP_REG_REG_REG);
249666e63ce3Schristos
249766e63ce3Schristos return 4;
249866e63ce3Schristos }
249966e63ce3Schristos
250066e63ce3Schristos /* divh reg1, reg2, reg3 */
250166e63ce3Schristos int
OP_28007E0(void)250266e63ce3Schristos OP_28007E0 (void)
250366e63ce3Schristos {
250466e63ce3Schristos signed long int quotient;
250566e63ce3Schristos signed long int remainder;
250666e63ce3Schristos signed long int divide_by;
250766e63ce3Schristos signed long int divide_this;
250866e63ce3Schristos int overflow = 0;
250966e63ce3Schristos
251066e63ce3Schristos trace_input ("divh", OP_REG_REG_REG, 0);
251166e63ce3Schristos
251266e63ce3Schristos /* Compute the result. */
251366e63ce3Schristos
251466e63ce3Schristos divide_by = EXTEND16 (State.regs[ OP[0] ]);
251566e63ce3Schristos divide_this = State.regs[ OP[1] ];
251666e63ce3Schristos
251766e63ce3Schristos if (divide_by == 0)
251866e63ce3Schristos {
251966e63ce3Schristos PSW |= PSW_OV;
252066e63ce3Schristos }
252166e63ce3Schristos else if (divide_by == -1 && divide_this == (1L << 31))
252266e63ce3Schristos {
252366e63ce3Schristos PSW &= ~PSW_Z;
252466e63ce3Schristos PSW |= PSW_OV | PSW_S;
252566e63ce3Schristos State.regs[ OP[1] ] = (1 << 31);
252666e63ce3Schristos State.regs[ OP[2] >> 11 ] = 0;
252766e63ce3Schristos }
252866e63ce3Schristos else
252966e63ce3Schristos {
253066e63ce3Schristos divide_this = (signed32) divide_this;
253166e63ce3Schristos State.regs[ OP[1] ] = quotient = divide_this / divide_by;
253266e63ce3Schristos State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
253366e63ce3Schristos
253466e63ce3Schristos /* Set condition codes. */
253566e63ce3Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
253666e63ce3Schristos
253766e63ce3Schristos if (quotient == 0) PSW |= PSW_Z;
253866e63ce3Schristos if (quotient < 0) PSW |= PSW_S;
253966e63ce3Schristos }
254066e63ce3Schristos
254166e63ce3Schristos trace_output (OP_REG_REG_REG);
254266e63ce3Schristos
254366e63ce3Schristos return 4;
254466e63ce3Schristos }
254566e63ce3Schristos
254666e63ce3Schristos /* mulu imm9, reg2, reg3 */
254766e63ce3Schristos int
OP_24207E0(void)254866e63ce3Schristos OP_24207E0 (void)
254966e63ce3Schristos {
255066e63ce3Schristos trace_input ("mulu", OP_IMM_REG_REG, 0);
255166e63ce3Schristos
255266e63ce3Schristos Multiply64 (0, (OP[3] & 0x1f) | ((OP[3] >> 13) & 0x1e0));
255366e63ce3Schristos
255466e63ce3Schristos trace_output (OP_IMM_REG_REG);
255566e63ce3Schristos
255666e63ce3Schristos return 4;
255766e63ce3Schristos }
255866e63ce3Schristos
255966e63ce3Schristos /* mul imm9, reg2, reg3 */
256066e63ce3Schristos int
OP_24007E0(void)256166e63ce3Schristos OP_24007E0 (void)
256266e63ce3Schristos {
256366e63ce3Schristos trace_input ("mul", OP_IMM_REG_REG, 0);
256466e63ce3Schristos
256566e63ce3Schristos Multiply64 (1, SEXT9 ((OP[3] & 0x1f) | ((OP[3] >> 13) & 0x1e0)));
256666e63ce3Schristos
256766e63ce3Schristos trace_output (OP_IMM_REG_REG);
256866e63ce3Schristos
256966e63ce3Schristos return 4;
257066e63ce3Schristos }
257166e63ce3Schristos
257266e63ce3Schristos /* ld.hu */
257366e63ce3Schristos int
OP_107E0(void)257466e63ce3Schristos OP_107E0 (void)
257566e63ce3Schristos {
257666e63ce3Schristos int adr;
257766e63ce3Schristos
257866e63ce3Schristos trace_input ("ld.hu", OP_LOAD32, 2);
257966e63ce3Schristos
258066e63ce3Schristos adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1);
258166e63ce3Schristos adr &= ~0x1;
258266e63ce3Schristos
258366e63ce3Schristos State.regs[ OP[1] ] = load_mem (adr, 2);
258466e63ce3Schristos
258566e63ce3Schristos trace_output (OP_LOAD32);
258666e63ce3Schristos
258766e63ce3Schristos return 4;
258866e63ce3Schristos }
258966e63ce3Schristos
259066e63ce3Schristos
259166e63ce3Schristos /* ld.bu */
259266e63ce3Schristos int
OP_10780(void)259366e63ce3Schristos OP_10780 (void)
259466e63ce3Schristos {
259566e63ce3Schristos int adr;
259666e63ce3Schristos
259766e63ce3Schristos trace_input ("ld.bu", OP_LOAD32, 1);
259866e63ce3Schristos
259966e63ce3Schristos adr = (State.regs[ OP[0] ]
260066e63ce3Schristos + (EXTEND16 (OP[2] & ~1) | ((OP[3] >> 5) & 1)));
260166e63ce3Schristos
260266e63ce3Schristos State.regs[ OP[1] ] = load_mem (adr, 1);
260366e63ce3Schristos
260466e63ce3Schristos trace_output (OP_LOAD32);
260566e63ce3Schristos
260666e63ce3Schristos return 4;
260766e63ce3Schristos }
260866e63ce3Schristos
260966e63ce3Schristos /* prepare list12, imm5, imm32 */
261066e63ce3Schristos int
OP_1B0780(void)261166e63ce3Schristos OP_1B0780 (void)
261266e63ce3Schristos {
261366e63ce3Schristos int i;
261466e63ce3Schristos
261566e63ce3Schristos trace_input ("prepare", OP_PUSHPOP1, 0);
261666e63ce3Schristos
261766e63ce3Schristos /* Store the registers with lower number registers being placed at higher addresses. */
261866e63ce3Schristos for (i = 0; i < 12; i++)
261966e63ce3Schristos if ((OP[3] & (1 << type1_regs[ i ])))
262066e63ce3Schristos {
262166e63ce3Schristos SP -= 4;
262266e63ce3Schristos store_mem (SP, 4, State.regs[ 20 + i ]);
262366e63ce3Schristos }
262466e63ce3Schristos
262566e63ce3Schristos SP -= (OP[3] & 0x3e) << 1;
262666e63ce3Schristos
262766e63ce3Schristos EP = load_mem (PC + 4, 4);
262866e63ce3Schristos
262966e63ce3Schristos trace_output (OP_PUSHPOP1);
263066e63ce3Schristos
263166e63ce3Schristos return 8;
263266e63ce3Schristos }
263366e63ce3Schristos
263466e63ce3Schristos /* prepare list12, imm5, imm16-32 */
263566e63ce3Schristos int
OP_130780(void)263666e63ce3Schristos OP_130780 (void)
263766e63ce3Schristos {
263866e63ce3Schristos int i;
263966e63ce3Schristos
264066e63ce3Schristos trace_input ("prepare", OP_PUSHPOP1, 0);
264166e63ce3Schristos
264266e63ce3Schristos /* Store the registers with lower number registers being placed at higher addresses. */
264366e63ce3Schristos for (i = 0; i < 12; i++)
264466e63ce3Schristos if ((OP[3] & (1 << type1_regs[ i ])))
264566e63ce3Schristos {
264666e63ce3Schristos SP -= 4;
264766e63ce3Schristos store_mem (SP, 4, State.regs[ 20 + i ]);
264866e63ce3Schristos }
264966e63ce3Schristos
265066e63ce3Schristos SP -= (OP[3] & 0x3e) << 1;
265166e63ce3Schristos
265266e63ce3Schristos EP = load_mem (PC + 4, 2) << 16;
265366e63ce3Schristos
265466e63ce3Schristos trace_output (OP_PUSHPOP1);
265566e63ce3Schristos
265666e63ce3Schristos return 6;
265766e63ce3Schristos }
265866e63ce3Schristos
265966e63ce3Schristos /* prepare list12, imm5, imm16 */
266066e63ce3Schristos int
OP_B0780(void)266166e63ce3Schristos OP_B0780 (void)
266266e63ce3Schristos {
266366e63ce3Schristos int i;
266466e63ce3Schristos
266566e63ce3Schristos trace_input ("prepare", OP_PUSHPOP1, 0);
266666e63ce3Schristos
266766e63ce3Schristos /* Store the registers with lower number registers being placed at higher addresses. */
266866e63ce3Schristos for (i = 0; i < 12; i++)
266966e63ce3Schristos if ((OP[3] & (1 << type1_regs[ i ])))
267066e63ce3Schristos {
267166e63ce3Schristos SP -= 4;
267266e63ce3Schristos store_mem (SP, 4, State.regs[ 20 + i ]);
267366e63ce3Schristos }
267466e63ce3Schristos
267566e63ce3Schristos SP -= (OP[3] & 0x3e) << 1;
267666e63ce3Schristos
267766e63ce3Schristos EP = EXTEND16 (load_mem (PC + 4, 2));
267866e63ce3Schristos
267966e63ce3Schristos trace_output (OP_PUSHPOP1);
268066e63ce3Schristos
268166e63ce3Schristos return 6;
268266e63ce3Schristos }
268366e63ce3Schristos
268466e63ce3Schristos /* prepare list12, imm5, sp */
268566e63ce3Schristos int
OP_30780(void)268666e63ce3Schristos OP_30780 (void)
268766e63ce3Schristos {
268866e63ce3Schristos int i;
268966e63ce3Schristos
269066e63ce3Schristos trace_input ("prepare", OP_PUSHPOP1, 0);
269166e63ce3Schristos
269266e63ce3Schristos /* Store the registers with lower number registers being placed at higher addresses. */
269366e63ce3Schristos for (i = 0; i < 12; i++)
269466e63ce3Schristos if ((OP[3] & (1 << type1_regs[ i ])))
269566e63ce3Schristos {
269666e63ce3Schristos SP -= 4;
269766e63ce3Schristos store_mem (SP, 4, State.regs[ 20 + i ]);
269866e63ce3Schristos }
269966e63ce3Schristos
270066e63ce3Schristos SP -= (OP[3] & 0x3e) << 1;
270166e63ce3Schristos
270266e63ce3Schristos EP = SP;
270366e63ce3Schristos
270466e63ce3Schristos trace_output (OP_PUSHPOP1);
270566e63ce3Schristos
270666e63ce3Schristos return 4;
270766e63ce3Schristos }
270866e63ce3Schristos
270966e63ce3Schristos /* mul reg1, reg2, reg3 */
271066e63ce3Schristos int
OP_22007E0(void)271166e63ce3Schristos OP_22007E0 (void)
271266e63ce3Schristos {
271366e63ce3Schristos trace_input ("mul", OP_REG_REG_REG, 0);
271466e63ce3Schristos
271566e63ce3Schristos Multiply64 (1, State.regs[ OP[0] ]);
271666e63ce3Schristos
271766e63ce3Schristos trace_output (OP_REG_REG_REG);
271866e63ce3Schristos
271966e63ce3Schristos return 4;
272066e63ce3Schristos }
272166e63ce3Schristos
272266e63ce3Schristos /* popmh list18 */
272366e63ce3Schristos int
OP_307F0(void)272466e63ce3Schristos OP_307F0 (void)
272566e63ce3Schristos {
272666e63ce3Schristos int i;
272766e63ce3Schristos
272866e63ce3Schristos trace_input ("popmh", OP_PUSHPOP2, 0);
272966e63ce3Schristos
273066e63ce3Schristos if (OP[3] & (1 << 19))
273166e63ce3Schristos {
273266e63ce3Schristos if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0))
273366e63ce3Schristos {
273466e63ce3Schristos FEPSW = load_mem ( SP & ~ 3, 4);
273566e63ce3Schristos FEPC = load_mem ((SP + 4) & ~ 3, 4);
273666e63ce3Schristos }
273766e63ce3Schristos else
273866e63ce3Schristos {
273966e63ce3Schristos EIPSW = load_mem ( SP & ~ 3, 4);
274066e63ce3Schristos EIPC = load_mem ((SP + 4) & ~ 3, 4);
274166e63ce3Schristos }
274266e63ce3Schristos
274366e63ce3Schristos SP += 8;
274466e63ce3Schristos }
274566e63ce3Schristos
274666e63ce3Schristos /* Load the registers with lower number registers being retrieved from higher addresses. */
274766e63ce3Schristos for (i = 16; i--;)
274866e63ce3Schristos if ((OP[3] & (1 << type2_regs[ i ])))
274966e63ce3Schristos {
275066e63ce3Schristos State.regs[ i + 16 ] = load_mem (SP & ~ 3, 4);
275166e63ce3Schristos SP += 4;
275266e63ce3Schristos }
275366e63ce3Schristos
275466e63ce3Schristos trace_output (OP_PUSHPOP2);
275566e63ce3Schristos
275666e63ce3Schristos return 4;
275766e63ce3Schristos }
275866e63ce3Schristos
275966e63ce3Schristos /* popml lsit18 */
276066e63ce3Schristos int
OP_107F0(void)276166e63ce3Schristos OP_107F0 (void)
276266e63ce3Schristos {
276366e63ce3Schristos int i;
276466e63ce3Schristos
276566e63ce3Schristos trace_input ("popml", OP_PUSHPOP3, 0);
276666e63ce3Schristos
276766e63ce3Schristos if (OP[3] & (1 << 19))
276866e63ce3Schristos {
276966e63ce3Schristos if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0))
277066e63ce3Schristos {
277166e63ce3Schristos FEPSW = load_mem ( SP & ~ 3, 4);
277266e63ce3Schristos FEPC = load_mem ((SP + 4) & ~ 3, 4);
277366e63ce3Schristos }
277466e63ce3Schristos else
277566e63ce3Schristos {
277666e63ce3Schristos EIPSW = load_mem ( SP & ~ 3, 4);
277766e63ce3Schristos EIPC = load_mem ((SP + 4) & ~ 3, 4);
277866e63ce3Schristos }
277966e63ce3Schristos
278066e63ce3Schristos SP += 8;
278166e63ce3Schristos }
278266e63ce3Schristos
278366e63ce3Schristos if (OP[3] & (1 << 3))
278466e63ce3Schristos {
278566e63ce3Schristos PSW = load_mem (SP & ~ 3, 4);
278666e63ce3Schristos SP += 4;
278766e63ce3Schristos }
278866e63ce3Schristos
278966e63ce3Schristos /* Load the registers with lower number registers being retrieved from higher addresses. */
279066e63ce3Schristos for (i = 15; i--;)
279166e63ce3Schristos if ((OP[3] & (1 << type3_regs[ i ])))
279266e63ce3Schristos {
279366e63ce3Schristos State.regs[ i + 1 ] = load_mem (SP & ~ 3, 4);
279466e63ce3Schristos SP += 4;
279566e63ce3Schristos }
279666e63ce3Schristos
279766e63ce3Schristos trace_output (OP_PUSHPOP2);
279866e63ce3Schristos
279966e63ce3Schristos return 4;
280066e63ce3Schristos }
280166e63ce3Schristos
280266e63ce3Schristos /* pushmh list18 */
280366e63ce3Schristos int
OP_307E0(void)280466e63ce3Schristos OP_307E0 (void)
280566e63ce3Schristos {
280666e63ce3Schristos int i;
280766e63ce3Schristos
280866e63ce3Schristos trace_input ("pushmh", OP_PUSHPOP2, 0);
280966e63ce3Schristos
281066e63ce3Schristos /* Store the registers with lower number registers being placed at higher addresses. */
281166e63ce3Schristos for (i = 0; i < 16; i++)
281266e63ce3Schristos if ((OP[3] & (1 << type2_regs[ i ])))
281366e63ce3Schristos {
281466e63ce3Schristos SP -= 4;
281566e63ce3Schristos store_mem (SP & ~ 3, 4, State.regs[ i + 16 ]);
281666e63ce3Schristos }
281766e63ce3Schristos
281866e63ce3Schristos if (OP[3] & (1 << 19))
281966e63ce3Schristos {
282066e63ce3Schristos SP -= 8;
282166e63ce3Schristos
282266e63ce3Schristos if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0))
282366e63ce3Schristos {
282466e63ce3Schristos store_mem ((SP + 4) & ~ 3, 4, FEPC);
282566e63ce3Schristos store_mem ( SP & ~ 3, 4, FEPSW);
282666e63ce3Schristos }
282766e63ce3Schristos else
282866e63ce3Schristos {
282966e63ce3Schristos store_mem ((SP + 4) & ~ 3, 4, EIPC);
283066e63ce3Schristos store_mem ( SP & ~ 3, 4, EIPSW);
283166e63ce3Schristos }
283266e63ce3Schristos }
283366e63ce3Schristos
283466e63ce3Schristos trace_output (OP_PUSHPOP2);
283566e63ce3Schristos
283666e63ce3Schristos return 4;
283766e63ce3Schristos }
283866e63ce3Schristos
283948596154Schristos /* V850E2R FPU functions */
284048596154Schristos /*
284148596154Schristos sim_fpu_status_invalid_snan = 1, -V--- (sim spec.)
284248596154Schristos sim_fpu_status_invalid_qnan = 2, ----- (sim spec.)
284348596154Schristos sim_fpu_status_invalid_isi = 4, (inf - inf) -V---
284448596154Schristos sim_fpu_status_invalid_idi = 8, (inf / inf) -V---
284548596154Schristos sim_fpu_status_invalid_zdz = 16, (0 / 0) -V---
284648596154Schristos sim_fpu_status_invalid_imz = 32, (inf * 0) -V---
284748596154Schristos sim_fpu_status_invalid_cvi = 64, convert to integer -V---
284848596154Schristos sim_fpu_status_invalid_div0 = 128, (X / 0) --Z--
284948596154Schristos sim_fpu_status_invalid_cmp = 256, compare ----- (sim spec.)
285048596154Schristos sim_fpu_status_invalid_sqrt = 512, -V---
285148596154Schristos sim_fpu_status_rounded = 1024, I----
285248596154Schristos sim_fpu_status_inexact = 2048, I---- (sim spec.)
285348596154Schristos sim_fpu_status_overflow = 4096, I--O-
285448596154Schristos sim_fpu_status_underflow = 8192, I---U
285548596154Schristos sim_fpu_status_denorm = 16384, ----U (sim spec.)
285648596154Schristos */
285748596154Schristos
2858ed6a76a9Schristos void
update_fpsr(SIM_DESC sd,sim_fpu_status status,unsigned int mask,unsigned int double_op_p)2859ed6a76a9Schristos update_fpsr (SIM_DESC sd, sim_fpu_status status, unsigned int mask, unsigned int double_op_p)
286048596154Schristos {
286148596154Schristos unsigned int fpsr = FPSR & mask;
286248596154Schristos
286348596154Schristos unsigned int flags = 0;
286448596154Schristos
286548596154Schristos if (fpsr & FPSR_XEI
286648596154Schristos && ((status & (sim_fpu_status_rounded
286748596154Schristos | sim_fpu_status_overflow
286848596154Schristos | sim_fpu_status_inexact))
286948596154Schristos || (status & sim_fpu_status_underflow
287048596154Schristos && (fpsr & (FPSR_XEU | FPSR_XEI)) == 0
287148596154Schristos && fpsr & FPSR_FS)))
287248596154Schristos {
287348596154Schristos flags |= FPSR_XCI | FPSR_XPI;
287448596154Schristos }
287548596154Schristos
287648596154Schristos if (fpsr & FPSR_XEV
287748596154Schristos && (status & (sim_fpu_status_invalid_isi
287848596154Schristos | sim_fpu_status_invalid_imz
287948596154Schristos | sim_fpu_status_invalid_zdz
288048596154Schristos | sim_fpu_status_invalid_idi
288148596154Schristos | sim_fpu_status_invalid_cvi
288248596154Schristos | sim_fpu_status_invalid_sqrt
288348596154Schristos | sim_fpu_status_invalid_snan)))
288448596154Schristos {
288548596154Schristos flags |= FPSR_XCV | FPSR_XPV;
288648596154Schristos }
288748596154Schristos
288848596154Schristos if (fpsr & FPSR_XEZ
288948596154Schristos && (status & sim_fpu_status_invalid_div0))
289048596154Schristos {
289148596154Schristos flags |= FPSR_XCV | FPSR_XPV;
289248596154Schristos }
289348596154Schristos
289448596154Schristos if (fpsr & FPSR_XEO
289548596154Schristos && (status & sim_fpu_status_overflow))
289648596154Schristos {
289748596154Schristos flags |= FPSR_XCO | FPSR_XPO;
289848596154Schristos }
289948596154Schristos
290048596154Schristos if (((fpsr & FPSR_XEU) || (fpsr & FPSR_FS) == 0)
290148596154Schristos && (status & (sim_fpu_status_underflow
290248596154Schristos | sim_fpu_status_denorm)))
290348596154Schristos {
290448596154Schristos flags |= FPSR_XCU | FPSR_XPU;
290548596154Schristos }
290648596154Schristos
290748596154Schristos if (flags)
290848596154Schristos {
290948596154Schristos FPSR &= ~FPSR_XC;
291048596154Schristos FPSR |= flags;
291148596154Schristos
291248596154Schristos SignalExceptionFPE (sd, double_op_p);
291348596154Schristos }
291448596154Schristos }
291548596154Schristos
2916ed6a76a9Schristos /* Exception. */
291748596154Schristos
2918ed6a76a9Schristos void
SignalException(SIM_DESC sd)2919ed6a76a9Schristos SignalException (SIM_DESC sd)
292048596154Schristos {
292148596154Schristos if (MPM & MPM_AUE)
292248596154Schristos {
292348596154Schristos PSW = PSW & ~(PSW_NPV | PSW_DMP | PSW_IMP);
292448596154Schristos }
292548596154Schristos }
292648596154Schristos
2927ed6a76a9Schristos void
SignalExceptionFPE(SIM_DESC sd,unsigned int double_op_p)2928ed6a76a9Schristos SignalExceptionFPE (SIM_DESC sd, unsigned int double_op_p)
292948596154Schristos {
293048596154Schristos if (((PSW & (PSW_NP|PSW_ID)) == 0)
293148596154Schristos || !(FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM)))
293248596154Schristos {
293348596154Schristos EIPC = PC;
293448596154Schristos EIPSW = PSW;
293548596154Schristos EIIC = (FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM))
293648596154Schristos ? 0x71 : 0x72;
293748596154Schristos PSW |= (PSW_EP | PSW_ID);
293848596154Schristos PC = 0x70;
293948596154Schristos
294048596154Schristos SignalException (sd);
294148596154Schristos }
294248596154Schristos }
294348596154Schristos
2944ed6a76a9Schristos void
check_invalid_snan(SIM_DESC sd,sim_fpu_status status,unsigned int double_op_p)2945ed6a76a9Schristos check_invalid_snan (SIM_DESC sd, sim_fpu_status status, unsigned int double_op_p)
294648596154Schristos {
294748596154Schristos if ((FPSR & FPSR_XEI)
294848596154Schristos && (status & sim_fpu_status_invalid_snan))
294948596154Schristos {
295048596154Schristos FPSR &= ~FPSR_XC;
295148596154Schristos FPSR |= FPSR_XCV;
295248596154Schristos FPSR |= FPSR_XPV;
295348596154Schristos SignalExceptionFPE (sd, double_op_p);
295448596154Schristos }
295548596154Schristos }
295648596154Schristos
2957ed6a76a9Schristos int
v850_float_compare(SIM_DESC sd,int cmp,sim_fpu wop1,sim_fpu wop2,int double_op_p)2958ed6a76a9Schristos v850_float_compare (SIM_DESC sd, int cmp, sim_fpu wop1, sim_fpu wop2, int double_op_p)
295948596154Schristos {
296048596154Schristos int result = -1;
296148596154Schristos
296248596154Schristos if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
296348596154Schristos {
296448596154Schristos if (cmp & 0x8)
296548596154Schristos {
296648596154Schristos if (FPSR & FPSR_XEV)
296748596154Schristos {
296848596154Schristos FPSR |= FPSR_XCV | FPSR_XPV;
296948596154Schristos SignalExceptionFPE (sd, double_op_p);
297048596154Schristos }
297148596154Schristos }
297248596154Schristos
297348596154Schristos switch (cmp)
297448596154Schristos {
297548596154Schristos case FPU_CMP_F:
297648596154Schristos result = 0;
297748596154Schristos break;
297848596154Schristos case FPU_CMP_UN:
297948596154Schristos result = 1;
298048596154Schristos break;
298148596154Schristos case FPU_CMP_EQ:
298248596154Schristos result = 0;
298348596154Schristos break;
298448596154Schristos case FPU_CMP_UEQ:
298548596154Schristos result = 1;
298648596154Schristos break;
298748596154Schristos case FPU_CMP_OLT:
298848596154Schristos result = 0;
298948596154Schristos break;
299048596154Schristos case FPU_CMP_ULT:
299148596154Schristos result = 1;
299248596154Schristos break;
299348596154Schristos case FPU_CMP_OLE:
299448596154Schristos result = 0;
299548596154Schristos break;
299648596154Schristos case FPU_CMP_ULE:
299748596154Schristos result = 1;
299848596154Schristos break;
299948596154Schristos case FPU_CMP_SF:
300048596154Schristos result = 0;
300148596154Schristos break;
300248596154Schristos case FPU_CMP_NGLE:
300348596154Schristos result = 1;
300448596154Schristos break;
300548596154Schristos case FPU_CMP_SEQ:
300648596154Schristos result = 0;
300748596154Schristos break;
300848596154Schristos case FPU_CMP_NGL:
300948596154Schristos result = 1;
301048596154Schristos break;
301148596154Schristos case FPU_CMP_LT:
301248596154Schristos result = 0;
301348596154Schristos break;
301448596154Schristos case FPU_CMP_NGE:
301548596154Schristos result = 1;
301648596154Schristos break;
301748596154Schristos case FPU_CMP_LE:
301848596154Schristos result = 0;
301948596154Schristos break;
302048596154Schristos case FPU_CMP_NGT:
302148596154Schristos result = 1;
302248596154Schristos break;
302348596154Schristos default:
302448596154Schristos abort ();
302548596154Schristos }
302648596154Schristos }
302748596154Schristos else if (sim_fpu_is_infinity (&wop1) && sim_fpu_is_infinity (&wop2)
302848596154Schristos && sim_fpu_sign (&wop1) == sim_fpu_sign (&wop2))
302948596154Schristos {
303048596154Schristos switch (cmp)
303148596154Schristos {
303248596154Schristos case FPU_CMP_F:
303348596154Schristos result = 0;
303448596154Schristos break;
303548596154Schristos case FPU_CMP_UN:
303648596154Schristos result = 0;
303748596154Schristos break;
303848596154Schristos case FPU_CMP_EQ:
303948596154Schristos result = 1;
304048596154Schristos break;
304148596154Schristos case FPU_CMP_UEQ:
304248596154Schristos result = 1;
304348596154Schristos break;
304448596154Schristos case FPU_CMP_OLT:
304548596154Schristos result = 0;
304648596154Schristos break;
304748596154Schristos case FPU_CMP_ULT:
304848596154Schristos result = 0;
304948596154Schristos break;
305048596154Schristos case FPU_CMP_OLE:
305148596154Schristos result = 1;
305248596154Schristos break;
305348596154Schristos case FPU_CMP_ULE:
305448596154Schristos result = 1;
305548596154Schristos break;
305648596154Schristos case FPU_CMP_SF:
305748596154Schristos result = 0;
305848596154Schristos break;
305948596154Schristos case FPU_CMP_NGLE:
306048596154Schristos result = 0;
306148596154Schristos break;
306248596154Schristos case FPU_CMP_SEQ:
306348596154Schristos result = 1;
306448596154Schristos break;
306548596154Schristos case FPU_CMP_NGL:
306648596154Schristos result = 1;
306748596154Schristos break;
306848596154Schristos case FPU_CMP_LT:
306948596154Schristos result = 0;
307048596154Schristos break;
307148596154Schristos case FPU_CMP_NGE:
307248596154Schristos result = 0;
307348596154Schristos break;
307448596154Schristos case FPU_CMP_LE:
307548596154Schristos result = 1;
307648596154Schristos break;
307748596154Schristos case FPU_CMP_NGT:
307848596154Schristos result = 1;
307948596154Schristos break;
308048596154Schristos default:
308148596154Schristos abort ();
308248596154Schristos }
308348596154Schristos }
308448596154Schristos else
308548596154Schristos {
308648596154Schristos int gt = 0,lt = 0,eq = 0, status;
308748596154Schristos
308848596154Schristos status = sim_fpu_cmp (&wop1, &wop2);
308948596154Schristos
3090ed6a76a9Schristos switch (status)
3091ed6a76a9Schristos {
309248596154Schristos case SIM_FPU_IS_SNAN:
309348596154Schristos case SIM_FPU_IS_QNAN:
309448596154Schristos abort ();
309548596154Schristos break;
309648596154Schristos
309748596154Schristos case SIM_FPU_IS_NINF:
309848596154Schristos lt = 1;
309948596154Schristos break;
310048596154Schristos case SIM_FPU_IS_PINF:
310148596154Schristos gt = 1;
310248596154Schristos break;
310348596154Schristos case SIM_FPU_IS_NNUMBER:
310448596154Schristos lt = 1;
310548596154Schristos break;
310648596154Schristos case SIM_FPU_IS_PNUMBER:
310748596154Schristos gt = 1;
310848596154Schristos break;
310948596154Schristos case SIM_FPU_IS_NDENORM:
311048596154Schristos lt = 1;
311148596154Schristos break;
311248596154Schristos case SIM_FPU_IS_PDENORM:
311348596154Schristos gt = 1;
311448596154Schristos break;
311548596154Schristos case SIM_FPU_IS_NZERO:
311648596154Schristos case SIM_FPU_IS_PZERO:
311748596154Schristos eq = 1;
311848596154Schristos break;
311948596154Schristos }
312048596154Schristos
312148596154Schristos switch (cmp)
312248596154Schristos {
312348596154Schristos case FPU_CMP_F:
312448596154Schristos result = 0;
312548596154Schristos break;
312648596154Schristos case FPU_CMP_UN:
312748596154Schristos result = 0;
312848596154Schristos break;
312948596154Schristos case FPU_CMP_EQ:
313048596154Schristos result = eq;
313148596154Schristos break;
313248596154Schristos case FPU_CMP_UEQ:
313348596154Schristos result = eq;
313448596154Schristos break;
313548596154Schristos case FPU_CMP_OLT:
313648596154Schristos result = lt;
313748596154Schristos break;
313848596154Schristos case FPU_CMP_ULT:
313948596154Schristos result = lt;
314048596154Schristos break;
314148596154Schristos case FPU_CMP_OLE:
314248596154Schristos result = lt || eq;
314348596154Schristos break;
314448596154Schristos case FPU_CMP_ULE:
314548596154Schristos result = lt || eq;
314648596154Schristos break;
314748596154Schristos case FPU_CMP_SF:
314848596154Schristos result = 0;
314948596154Schristos break;
315048596154Schristos case FPU_CMP_NGLE:
315148596154Schristos result = 0;
315248596154Schristos break;
315348596154Schristos case FPU_CMP_SEQ:
315448596154Schristos result = eq;
315548596154Schristos break;
315648596154Schristos case FPU_CMP_NGL:
315748596154Schristos result = eq;
315848596154Schristos break;
315948596154Schristos case FPU_CMP_LT:
316048596154Schristos result = lt;
316148596154Schristos break;
316248596154Schristos case FPU_CMP_NGE:
316348596154Schristos result = lt;
316448596154Schristos break;
316548596154Schristos case FPU_CMP_LE:
316648596154Schristos result = lt || eq;
316748596154Schristos break;
316848596154Schristos case FPU_CMP_NGT:
316948596154Schristos result = lt || eq;
317048596154Schristos break;
317148596154Schristos }
317248596154Schristos }
317348596154Schristos
317448596154Schristos ASSERT (result != -1);
317548596154Schristos return result;
317648596154Schristos }
317748596154Schristos
3178ed6a76a9Schristos void
v850_div(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p,unsigned int * op3p)3179ed6a76a9Schristos v850_div (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p)
318048596154Schristos {
318148596154Schristos signed long int quotient;
318248596154Schristos signed long int remainder;
318348596154Schristos signed long int divide_by;
318448596154Schristos signed long int divide_this;
318548596154Schristos bfd_boolean overflow = FALSE;
318648596154Schristos
318748596154Schristos /* Compute the result. */
318848596154Schristos divide_by = op0;
318948596154Schristos divide_this = op1;
319048596154Schristos
319148596154Schristos if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
319248596154Schristos {
319348596154Schristos overflow = TRUE;
319448596154Schristos divide_by = 1;
319548596154Schristos }
319648596154Schristos
319748596154Schristos quotient = divide_this / divide_by;
319848596154Schristos remainder = divide_this % divide_by;
319948596154Schristos
320048596154Schristos /* Set condition codes. */
320148596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
320248596154Schristos
320348596154Schristos if (overflow) PSW |= PSW_OV;
320448596154Schristos if (quotient == 0) PSW |= PSW_Z;
320548596154Schristos if (quotient < 0) PSW |= PSW_S;
320648596154Schristos
320748596154Schristos *op2p = quotient;
320848596154Schristos *op3p = remainder;
320948596154Schristos }
321048596154Schristos
3211ed6a76a9Schristos void
v850_divu(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p,unsigned int * op3p)3212ed6a76a9Schristos v850_divu (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p)
321348596154Schristos {
321448596154Schristos unsigned long int quotient;
321548596154Schristos unsigned long int remainder;
321648596154Schristos unsigned long int divide_by;
321748596154Schristos unsigned long int divide_this;
321848596154Schristos bfd_boolean overflow = FALSE;
321948596154Schristos
322048596154Schristos /* Compute the result. */
322148596154Schristos
322248596154Schristos divide_by = op0;
322348596154Schristos divide_this = op1;
322448596154Schristos
322548596154Schristos if (divide_by == 0)
322648596154Schristos {
322748596154Schristos overflow = TRUE;
322848596154Schristos divide_by = 1;
322948596154Schristos }
323048596154Schristos
323148596154Schristos quotient = divide_this / divide_by;
323248596154Schristos remainder = divide_this % divide_by;
323348596154Schristos
323448596154Schristos /* Set condition codes. */
323548596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV);
323648596154Schristos
323748596154Schristos if (overflow) PSW |= PSW_OV;
323848596154Schristos if (quotient == 0) PSW |= PSW_Z;
323948596154Schristos if (quotient & 0x80000000) PSW |= PSW_S;
324048596154Schristos
324148596154Schristos *op2p = quotient;
324248596154Schristos *op3p = remainder;
324348596154Schristos }
324448596154Schristos
3245ed6a76a9Schristos void
v850_sar(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p)3246ed6a76a9Schristos v850_sar (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p)
324748596154Schristos {
324848596154Schristos unsigned int result, z, s, cy;
324948596154Schristos
325048596154Schristos op0 &= 0x1f;
325148596154Schristos result = (signed)op1 >> op0;
325248596154Schristos
325348596154Schristos /* Compute the condition codes. */
325448596154Schristos z = (result == 0);
325548596154Schristos s = (result & 0x80000000);
325648596154Schristos cy = (op1 & (1 << (op0 - 1)));
325748596154Schristos
325848596154Schristos /* Store the result and condition codes. */
325948596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
326048596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
326148596154Schristos | (cy ? PSW_CY : 0));
326248596154Schristos
326348596154Schristos *op2p = result;
326448596154Schristos }
326548596154Schristos
3266ed6a76a9Schristos void
v850_shl(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p)3267ed6a76a9Schristos v850_shl (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p)
326848596154Schristos {
326948596154Schristos unsigned int result, z, s, cy;
327048596154Schristos
327148596154Schristos op0 &= 0x1f;
327248596154Schristos result = op1 << op0;
327348596154Schristos
327448596154Schristos /* Compute the condition codes. */
327548596154Schristos z = (result == 0);
327648596154Schristos s = (result & 0x80000000);
327748596154Schristos cy = (op1 & (1 << (32 - op0)));
327848596154Schristos
327948596154Schristos /* Store the result and condition codes. */
328048596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
328148596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
328248596154Schristos | (cy ? PSW_CY : 0));
328348596154Schristos
328448596154Schristos *op2p = result;
328548596154Schristos }
328648596154Schristos
328748596154Schristos void
v850_rotl(SIM_DESC sd,unsigned int amount,unsigned int src,unsigned int * dest)328848596154Schristos v850_rotl (SIM_DESC sd, unsigned int amount, unsigned int src, unsigned int * dest)
328948596154Schristos {
329048596154Schristos unsigned int result, z, s, cy;
329148596154Schristos
329248596154Schristos amount &= 0x1f;
329348596154Schristos result = src << amount;
329448596154Schristos result |= src >> (32 - amount);
329548596154Schristos
329648596154Schristos /* Compute the condition codes. */
329748596154Schristos z = (result == 0);
329848596154Schristos s = (result & 0x80000000);
329948596154Schristos cy = ! (result & 1);
330048596154Schristos
330148596154Schristos /* Store the result and condition codes. */
330248596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
330348596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
330448596154Schristos | (cy ? PSW_CY : 0));
330548596154Schristos
330648596154Schristos * dest = result;
330748596154Schristos }
330848596154Schristos
330948596154Schristos void
v850_bins(SIM_DESC sd,unsigned int source,unsigned int lsb,unsigned int msb,unsigned int * dest)331048596154Schristos v850_bins (SIM_DESC sd, unsigned int source, unsigned int lsb, unsigned int msb,
331148596154Schristos unsigned int * dest)
331248596154Schristos {
331348596154Schristos unsigned int mask;
331448596154Schristos unsigned int result, pos, width;
331548596154Schristos unsigned int z, s;
331648596154Schristos
331748596154Schristos pos = lsb;
331848596154Schristos width = (msb - lsb) + 1;
331948596154Schristos
3320*c03b94e9Schristos mask = ~ (-(1 << width));
332148596154Schristos source &= mask;
332248596154Schristos mask <<= pos;
332348596154Schristos result = (* dest) & ~ mask;
332448596154Schristos result |= source << pos;
332548596154Schristos
332648596154Schristos /* Compute the condition codes. */
332748596154Schristos z = (result == 0);
332848596154Schristos s = result & 0x80000000;
332948596154Schristos
333048596154Schristos /* Store the result and condition codes. */
333148596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV );
333248596154Schristos PSW |= (z ? PSW_Z : 0) | (s ? PSW_S : 0);
333348596154Schristos
333448596154Schristos * dest = result;
333548596154Schristos }
333648596154Schristos
3337ed6a76a9Schristos void
v850_shr(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p)3338ed6a76a9Schristos v850_shr (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p)
333948596154Schristos {
334048596154Schristos unsigned int result, z, s, cy;
334148596154Schristos
334248596154Schristos op0 &= 0x1f;
334348596154Schristos result = op1 >> op0;
334448596154Schristos
334548596154Schristos /* Compute the condition codes. */
334648596154Schristos z = (result == 0);
334748596154Schristos s = (result & 0x80000000);
334848596154Schristos cy = (op1 & (1 << (op0 - 1)));
334948596154Schristos
335048596154Schristos /* Store the result and condition codes. */
335148596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY);
335248596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
335348596154Schristos | (cy ? PSW_CY : 0));
335448596154Schristos
335548596154Schristos *op2p = result;
335648596154Schristos }
335748596154Schristos
3358ed6a76a9Schristos void
v850_satadd(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p)3359ed6a76a9Schristos v850_satadd (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p)
336048596154Schristos {
336148596154Schristos unsigned int result, z, s, cy, ov, sat;
336248596154Schristos
336348596154Schristos result = op0 + op1;
336448596154Schristos
336548596154Schristos /* Compute the condition codes. */
336648596154Schristos z = (result == 0);
336748596154Schristos s = (result & 0x80000000);
336848596154Schristos cy = (result < op0 || result < op1);
336948596154Schristos ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
337048596154Schristos && (op0 & 0x80000000) != (result & 0x80000000));
337148596154Schristos sat = ov;
337248596154Schristos
337348596154Schristos /* Store the result and condition codes. */
337448596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
337548596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
337648596154Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
337748596154Schristos | (sat ? PSW_SAT : 0));
337848596154Schristos
337948596154Schristos /* Handle saturated results. */
338048596154Schristos if (sat && s)
338148596154Schristos {
338248596154Schristos result = 0x7fffffff;
338348596154Schristos PSW &= ~PSW_S;
338448596154Schristos }
338548596154Schristos else if (sat)
338648596154Schristos {
338748596154Schristos result = 0x80000000;
338848596154Schristos PSW |= PSW_S;
338948596154Schristos }
339048596154Schristos
339148596154Schristos *op2p = result;
339248596154Schristos }
339348596154Schristos
3394ed6a76a9Schristos void
v850_satsub(SIM_DESC sd,unsigned int op0,unsigned int op1,unsigned int * op2p)3395ed6a76a9Schristos v850_satsub (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p)
339648596154Schristos {
339748596154Schristos unsigned int result, z, s, cy, ov, sat;
339848596154Schristos
339948596154Schristos /* Compute the result. */
340048596154Schristos result = op1 - op0;
340148596154Schristos
340248596154Schristos /* Compute the condition codes. */
340348596154Schristos z = (result == 0);
340448596154Schristos s = (result & 0x80000000);
340548596154Schristos cy = (op1 < op0);
340648596154Schristos ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
340748596154Schristos && (op1 & 0x80000000) != (result & 0x80000000));
340848596154Schristos sat = ov;
340948596154Schristos
341048596154Schristos /* Store the result and condition codes. */
341148596154Schristos PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
341248596154Schristos PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
341348596154Schristos | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
341448596154Schristos | (sat ? PSW_SAT : 0));
341548596154Schristos
341648596154Schristos /* Handle saturated results. */
341748596154Schristos if (sat && s)
341848596154Schristos {
341948596154Schristos result = 0x7fffffff;
342048596154Schristos PSW &= ~PSW_S;
342148596154Schristos }
342248596154Schristos else if (sat)
342348596154Schristos {
342448596154Schristos result = 0x80000000;
342548596154Schristos PSW |= PSW_S;
342648596154Schristos }
342748596154Schristos
342848596154Schristos *op2p = result;
342948596154Schristos }
343048596154Schristos
343148596154Schristos unsigned32
load_data_mem(SIM_DESC sd,SIM_ADDR addr,int len)3432ed6a76a9Schristos load_data_mem (SIM_DESC sd,
3433ed6a76a9Schristos SIM_ADDR addr,
3434ed6a76a9Schristos int len)
343548596154Schristos {
343648596154Schristos uint32 data;
343748596154Schristos
343848596154Schristos switch (len)
343948596154Schristos {
344048596154Schristos case 1:
344148596154Schristos data = sim_core_read_unaligned_1 (STATE_CPU (sd, 0),
344248596154Schristos PC, read_map, addr);
344348596154Schristos break;
344448596154Schristos case 2:
344548596154Schristos data = sim_core_read_unaligned_2 (STATE_CPU (sd, 0),
344648596154Schristos PC, read_map, addr);
344748596154Schristos break;
344848596154Schristos case 4:
344948596154Schristos data = sim_core_read_unaligned_4 (STATE_CPU (sd, 0),
345048596154Schristos PC, read_map, addr);
345148596154Schristos break;
345248596154Schristos default:
345348596154Schristos abort ();
345448596154Schristos }
345548596154Schristos return data;
345648596154Schristos }
345748596154Schristos
345848596154Schristos void
store_data_mem(SIM_DESC sd,SIM_ADDR addr,int len,unsigned32 data)3459ed6a76a9Schristos store_data_mem (SIM_DESC sd,
3460ed6a76a9Schristos SIM_ADDR addr,
3461ed6a76a9Schristos int len,
3462ed6a76a9Schristos unsigned32 data)
346348596154Schristos {
346448596154Schristos switch (len)
346548596154Schristos {
346648596154Schristos case 1:
346748596154Schristos store_mem (addr, 1, data);
346848596154Schristos break;
346948596154Schristos case 2:
347048596154Schristos store_mem (addr, 2, data);
347148596154Schristos break;
347248596154Schristos case 4:
347348596154Schristos store_mem (addr, 4, data);
347448596154Schristos break;
347548596154Schristos default:
347648596154Schristos abort ();
347748596154Schristos }
347848596154Schristos }
347948596154Schristos
3480ed6a76a9Schristos int
mpu_load_mem_test(SIM_DESC sd,unsigned int addr,int size,int base_reg)3481ed6a76a9Schristos mpu_load_mem_test (SIM_DESC sd, unsigned int addr, int size, int base_reg)
348248596154Schristos {
348348596154Schristos int result = 1;
348448596154Schristos
348548596154Schristos if (PSW & PSW_DMP)
348648596154Schristos {
348748596154Schristos if (IPE0 && addr >= IPA2ADDR (IPA0L) && addr <= IPA2ADDR (IPA0L) && IPR0)
348848596154Schristos {
348948596154Schristos /* text area */
349048596154Schristos }
349148596154Schristos else if (IPE1 && addr >= IPA2ADDR (IPA1L) && addr <= IPA2ADDR (IPA1L) && IPR1)
349248596154Schristos {
349348596154Schristos /* text area */
349448596154Schristos }
349548596154Schristos else if (IPE2 && addr >= IPA2ADDR (IPA2L) && addr <= IPA2ADDR (IPA2L) && IPR2)
349648596154Schristos {
349748596154Schristos /* text area */
349848596154Schristos }
349948596154Schristos else if (IPE3 && addr >= IPA2ADDR (IPA3L) && addr <= IPA2ADDR (IPA3L) && IPR3)
350048596154Schristos {
350148596154Schristos /* text area */
350248596154Schristos }
350348596154Schristos else if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM))
350448596154Schristos {
350548596154Schristos /* preifarallel area */
350648596154Schristos }
350748596154Schristos else if (addr >= PPA2ADDR (SPAL) && addr <= DPA2ADDR (SPAU))
350848596154Schristos {
350948596154Schristos /* stack area */
351048596154Schristos }
351148596154Schristos else if (DPE0 && addr >= DPA2ADDR (DPA0L) && addr <= DPA2ADDR (DPA0L) && DPR0
351248596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
351348596154Schristos {
351448596154Schristos /* data area */
351548596154Schristos }
351648596154Schristos else if (DPE1 && addr >= DPA2ADDR (DPA1L) && addr <= DPA2ADDR (DPA1L) && DPR1
351748596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
351848596154Schristos {
351948596154Schristos /* data area */
352048596154Schristos }
352148596154Schristos else if (DPE2 && addr >= DPA2ADDR (DPA2L) && addr <= DPA2ADDR (DPA2L) && DPR2
352248596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
352348596154Schristos {
352448596154Schristos /* data area */
352548596154Schristos }
352648596154Schristos else if (DPE3 && addr >= DPA2ADDR (DPA3L) && addr <= DPA2ADDR (DPA3L) && DPR3
352748596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
352848596154Schristos {
352948596154Schristos /* data area */
353048596154Schristos }
353148596154Schristos else
353248596154Schristos {
353348596154Schristos VMECR &= ~(VMECR_VMW | VMECR_VMX);
353448596154Schristos VMECR |= VMECR_VMR;
353548596154Schristos VMADR = addr;
353648596154Schristos VMTID = TID;
353748596154Schristos FEIC = 0x431;
353848596154Schristos
353948596154Schristos PC = 0x30;
354048596154Schristos
354148596154Schristos SignalException (sd);
354248596154Schristos result = 0;
354348596154Schristos }
354448596154Schristos }
354548596154Schristos
354648596154Schristos return result;
354748596154Schristos }
354848596154Schristos
3549ed6a76a9Schristos int
mpu_store_mem_test(SIM_DESC sd,unsigned int addr,int size,int base_reg)3550ed6a76a9Schristos mpu_store_mem_test (SIM_DESC sd, unsigned int addr, int size, int base_reg)
355148596154Schristos {
355248596154Schristos int result = 1;
355348596154Schristos
355448596154Schristos if (PSW & PSW_DMP)
355548596154Schristos {
355648596154Schristos if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM))
355748596154Schristos {
355848596154Schristos /* preifarallel area */
355948596154Schristos }
356048596154Schristos else if (addr >= PPA2ADDR (SPAL) && addr <= DPA2ADDR (SPAU))
356148596154Schristos {
356248596154Schristos /* stack area */
356348596154Schristos }
356448596154Schristos else if (DPE0 && addr >= DPA2ADDR (DPA0L) && addr <= DPA2ADDR (DPA0L) && DPW0
356548596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
356648596154Schristos {
356748596154Schristos /* data area */
356848596154Schristos }
356948596154Schristos else if (DPE1 && addr >= DPA2ADDR (DPA1L) && addr <= DPA2ADDR (DPA1L) && DPW1
357048596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
357148596154Schristos {
357248596154Schristos /* data area */
357348596154Schristos }
357448596154Schristos else if (DPE2 && addr >= DPA2ADDR (DPA2L) && addr <= DPA2ADDR (DPA2L) && DPW2
357548596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
357648596154Schristos {
357748596154Schristos /* data area */
357848596154Schristos }
357948596154Schristos else if (DPE3 && addr >= DPA2ADDR (DPA3L) && addr <= DPA2ADDR (DPA3L) && DPW3
358048596154Schristos && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1))
358148596154Schristos {
358248596154Schristos /* data area */
358348596154Schristos }
358448596154Schristos else
358548596154Schristos {
358648596154Schristos if (addr >= PPA2ADDR (PPA & ~PPM) && addr <= DPA2ADDR (PPA | PPM))
358748596154Schristos {
358848596154Schristos FEIC = 0x432;
358948596154Schristos VPTID = TID;
359048596154Schristos VPADR = PC;
359148596154Schristos #ifdef NOT_YET
359248596154Schristos VIP_PP;
359348596154Schristos VPECR;
359448596154Schristos #endif
359548596154Schristos }
359648596154Schristos else
359748596154Schristos {
359848596154Schristos FEIC = 0x431;
359948596154Schristos VMTID = TID;
360048596154Schristos VMADR = VMECR;
360148596154Schristos VMECR &= ~(VMECR_VMW | VMECR_VMX);
360248596154Schristos VMECR |= VMECR_VMR;
360348596154Schristos PC = 0x30;
360448596154Schristos }
360548596154Schristos result = 0;
360648596154Schristos }
360748596154Schristos }
360848596154Schristos
360948596154Schristos return result;
361048596154Schristos }
361148596154Schristos
3612