Thu Aug 29 13:53:29 1996 Jeffrey A Law (law@cygnus.com)
+ * interp.c (hash): Update to be more accurate.
+ (lookup_hash): Call hash rather than computing the hash
+ code here.
+ (do_format_1_2): Handle format 1 and format 2 instructions.
+ Get operands correctly and call the target function.
+ (do_format_6): Get operands correctly and call the target
+ function.
+ (do_formats_9_10): Rough cut so shift ops will work.
+ (sim_resume): Tweak to deal with format 1 and format 2
+ handling in a single funtion. Don't update the PC
+ for format 3 insns. Fix typos.
+ * simops.c: Slightly reorganize. Add condition code handling
+ to "add", "addi", "and", "andi", "or", "ori", "xor", "xori"
+ and "not" instructions.
+ * v850_sim.h (reg_t): Registers are 32bits.
+ (_state): The V850 has 32 general registers. Add a 32bit
+ psw and pc register too. Add accessor macros
+
+ * Makefile.in, interp.c, v850_sim.h: Bring over endianness
+ changes from the d10v simulator.
+
* simops.c: Add shift support.
* simops.c: Add multiply & divide support. Abort for system
AR = @AR@
AR_FLAGS = rc
CC = @CC@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ @DEFS@
MAKEINFO = makeinfo
RANLIB = @RANLIB@
CC_FOR_BUILD = @CC_FOR_BUILD@
hash(insn)
long insn;
{
- /* XXX This isn't right for 32bit opcodes, hell it isn't even
- right for 16bit opcodes! */
- if (insn & 0x0600)
- return ((insn & 0x3F000000) >> 24);
- else
- return((insn & 0x07E0) >> 5);
+ if ((insn & 0x30) == 0
+ || (insn & 0x38) == 0x10)
+ return (insn & 0x07e0) >> 5;
+ if ((insn & 0x3c) == 0x18
+ || (insn & 0x3c) == 0x1c
+ || (insn & 0x3c) == 0x20
+ || (insn & 0x3c) == 0x24
+ || (insn & 0x3c) == 0x28
+ || (insn & 0x3c) == 0x23)
+ return (insn & 0x07c0) >> 6;
+ if ((insn & 0x38) == 0x30)
+ return (insn & 0x07e0) >> 5;
+ /* What about sub-op field? XXX */
+ if ((insn & 0x38) == 0x38)
+ return (insn & 0x07e0) >> 5;
+ if ((insn & 0x3e) == 0x3c)
+ return (insn & 0x07c0) >> 6;
+ if ((insn & 0x3f) == 0x3e)
+ return (insn & 0xc7e0) >> 5;
+ /* Not really correct. XXX */
+ return insn & 0xffffffff;
+
}
static struct hash_entry *
{
struct hash_entry *h;
- if (ins & 0x0f00)
- h = &hash_table[(ins & 0x3F000000) >> 24];
- else
- h = &hash_table[(ins & 0x07E0) >> 5];
+ h = &hash_table[hash(ins)];
while ( (ins & h->mask) != h->opcode)
{
}
uint32
-get_longword_swap (x)
- uint16 x;
+get_longword (x)
+ uint8 *x;
{
- uint8 *a = (uint8 *)(x + State.imem);
- return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + (a[3]);
+ uint8 *a = x;
+ return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
+}
+
+int64
+get_longlong (x)
+ uint8 *x;
+{
+ uint8 *a = x;
+ return ((int64)a[0]<<56) + ((int64)a[1]<<48) + ((int64)a[2]<<40) + ((int64)a[3]<<32) +
+ ((int64)a[4]<< 24) + ((int64)a[5]<<16) + ((int64)a[6]<<8) + (int64)a[7];
}
uint16
-get_word_swap (x)
- uint16 x;
+get_word (x)
+ uint8 *x;
{
- uint8 *a = (uint8 *)(x + State.imem);
- return (a[0]<<8) + a[1];
+ uint8 *a = x;
+ return ((uint16)a[0]<<8) + a[1];
}
+
void
-write_word_swap (addr, data)
- uint16 addr, data;
+write_word (addr, data)
+ uint8 *addr;
+ uint16 data;
{
- uint8 *a = (uint8 *)(addr + State.imem);
+ uint8 *a = addr;
a[0] = data >> 8;
a[1] = data & 0xff;
}
+void
+write_longword (addr, data)
+ uint8 *addr;
+ uint32 data;
+{
+ addr[0] = (data >> 24) & 0xff;
+ addr[1] = (data >> 16) & 0xff;
+ addr[2] = (data >> 8) & 0xff;
+ addr[3] = data & 0xff;
+}
+
+void
+write_longlong (addr, data)
+ uint8 *addr;
+ int64 data;
+{
+ uint8 *a = addr;
+ a[0] = data >> 56;
+ a[1] = (data >> 48) & 0xff;
+ a[2] = (data >> 40) & 0xff;
+ a[3] = (data >> 32) & 0xff;
+ a[4] = (data >> 24) & 0xff;
+ a[5] = (data >> 16) & 0xff;
+ a[6] = (data >> 8) & 0xff;
+ a[7] = data & 0xff;
+}
+
static void
-do_format_1 (insn)
- uint32 insn;
+get_operands (struct simops *s, uint32 ins)
{
- printf("format 1 0x%x\n", insn >> 16);
+ int i, shift, bits, flags;
+ uint32 mask;
+ for (i=0; i < s->numops; i++)
+ {
+ shift = s->operands[3*i];
+ bits = s->operands[3*i+1];
+ flags = s->operands[3*i+2];
+ mask = 0x7FFFFFFF >> (31 - bits);
+ OP[i] = (ins >> shift) & mask;
+ }
}
static void
-do_format_2 (insn)
+do_format_1_2 (insn)
uint32 insn;
{
- printf("format 2 0x%x\n", insn >> 16);
+ struct hash_entry *h;
+ printf("format 1 or 2 0x%x\n", insn);
+
+ h = lookup_hash (insn);
+ OP[0] = insn & 0x1f;
+ OP[1] = (insn >> 11) & 0x1f;
+ (h->ops->func) ();
}
static void
do_format_3 (insn)
uint32 insn;
{
- printf("format 3 0x%x\n", insn >> 16);
+ printf("format 3 0x%x\n", insn);
}
static void
do_format_4 (insn)
uint32 insn;
{
- printf("format 4 0x%x\n", insn >> 16);
+ printf("format 4 0x%x\n", insn);
}
static void
do_format_6 (insn)
uint32 insn;
{
+ struct hash_entry *h;
printf("format 6 0x%x\n", insn);
+
+ h = lookup_hash (insn);
+ OP[0] = (insn >> 16) & 0xffff;
+ OP[1] = insn & 0x1f;
+ OP[2] = (insn >> 11) & 0x1f;
+ (h->ops->func) ();
}
static void
do_formats_9_10 (insn)
uint32 insn;
{
+ struct hash_entry *h;
printf("formats 9 and 10 0x%x\n", insn);
+
+ h = lookup_hash (insn);
+ OP[0] = insn & 0x1f;
+ OP[1] = (insn >> 11) & 0x1f;
+ (h->ops->func) ();
}
void
{
inst = RLW (PC);
oldpc = PC;
- opcode = (inst & 0x07e00000) >> 21;
- if ((opcode & 0x30) == 0)
- {
- do_format_1 (inst >> 16);
- PC += 2;
- }
- else if ((opcode & 0x38) == 0x10)
+ opcode = (inst & 0x07e0) >> 5;
+ if ((opcode & 0x30) == 0
+ || (opcode & 0x38) == 0x10)
{
- do_format_2 (inst >> 16);
+ do_format_1_2 (inst & 0xffff);
PC += 2;
}
else if ((opcode & 0x3C) == 0x18
|| (opcode & 0x3C) == 0x24
|| (opcode & 0x3C) == 0x28)
{
- do_format_4 (inst >> 16);
+ do_format_4 (inst & 0xffff);
PC += 2;
}
- else if ((opcode& 0x3C) == 0x23)
+ else if ((opcode & 0x3C) == 0x23)
{
- do_format_3 (inst >> 16);
- PC += 2;
+ do_format_3 (inst & 0xffff);
+ /* No PC update, it's done in the instruction. */
}
else if ((opcode & 0x38) == 0x30)
{
do_format_5 (inst);
PC += 4;
}
- else if ((opcode & 0x3E) == 0x3C)
+ else if ((opcode & 0x3F) == 0x3E)
{
do_format_8 (inst);
PC += 4;
}
-/* add reg, reg
-
- XXX condition codes. */
+/* add reg, reg */
void
OP_1C0 ()
{
- State.regs[OP[1]] += State.regs[OP[0]];
-}
+ unsigned int op0, op1, result, z, s, cy, ov;
-/* add sign_extend(imm5), reg
+ /* Compute the result. */
+ op0 = State.regs[OP[0]];
+ op1 = State.regs[OP[1]];
+ result = op0 + op1;
- XXX condition codes. */
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+ cy = (result < op0 || result < op1);
+ ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
+ && (op0 & 0x80000000) != (result & 0x80000000));
+
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
+ | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
+}
+
+/* add sign_extend(imm5), reg */
void
OP_240 ()
{
- int value = OP[0];
-
- value = (value << 27) >> 27;
+ unsigned int op0, op1, result, z, s, cy, ov;
+ int temp;
- State.regs[OP[1]] += value;
-}
+ /* Compute the result. */
+ temp = (OP[0] & 0x1f);
+ temp = (temp << 27) >> 27;
+ op0 = temp;
+ op1 = State.regs[OP[1]];
+ result = op0 + op1;
+
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+ cy = (result < op0 || result < op1);
+ ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
+ && (op0 & 0x80000000) != (result & 0x80000000));
-/* addi sign_extend(imm16), reg, reg
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
+ | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
+}
- XXX condition codes. */
+/* addi sign_extend(imm16), reg, reg */
void
OP_600 ()
{
- int value = OP[0];
-
- value = (value << 16) >> 16;
-
- State.regs[OP[2]] = State.regs[OP[1]] + value;
+ unsigned int op0, op1, result, z, s, cy, ov;
+ int temp;
+
+ /* Compute the result. */
+ temp = (OP[0] & 0xffff);
+ temp = (temp << 16) >> 16;
+ op0 = temp;
+ op1 = State.regs[OP[1]];
+ result = op0 + op1;
+
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+ cy = (result < op0 || result < op1);
+ ov = ((op0 & 0x80000000) == (op1 & 0x80000000)
+ && (op0 & 0x80000000) != (result & 0x80000000));
+
+ /* Store the result and condition codes. */
+ State.regs[OP[2]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
+ | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
}
/* sub reg1, reg2
{
}
-/* not reg1, reg2
-
- XXX condition codes */
-void
-OP_20 ()
-{
- State.regs[OP[1]] = ~State.regs[OP[0]];
-}
-
/* sar zero_extend(imm5),reg1
XXX condition codes. */
{
}
-/* or reg, reg
-
- XXX condition codes. */
+/* or reg, reg */
void
OP_100 ()
{
- State.regs[OP[1]] |= State.regs[OP[0]];
-}
+ unsigned int op0, op1, result, z, s, cy, ov;
-/* ori zero_extend(imm16), reg, reg
+ /* Compute the result. */
+ op0 = State.regs[OP[0]];
+ op1 = State.regs[OP[1]];
+ result = op0 | op1;
- XXX condition codes */
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
+}
+
+/* ori zero_extend(imm16), reg, reg */
void
OP_680 ()
{
- int value = OP[0];
-
- value &= 0xffff;
+ unsigned int op0, op1, result, z, s, cy, ov;
- State.regs[OP[2]] = State.regs[OP[1]] | value;
-}
+ op0 = OP[0] & 0xffff;
+ op1 = State.regs[OP[1]];
+ result = op0 | op1;
-/* and reg, reg
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
- XXX condition codes. */
+ /* Store the result and condition codes. */
+ State.regs[OP[2]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
+ State.psw |= (z ? PSW_Z : 0);
+}
+
+/* and reg, reg */
void
OP_140 ()
{
- State.regs[OP[1]] &= State.regs[OP[0]];
-}
+ unsigned int op0, op1, result, z, s, cy, ov;
-/* andi zero_extend(imm16), reg, reg
+ /* Compute the result. */
+ op0 = State.regs[OP[0]];
+ op1 = State.regs[OP[1]];
+ result = op0 & op1;
- XXX condition codes. */
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
+}
+
+/* andi zero_extend(imm16), reg, reg */
void
OP_6C0 ()
{
- int value = OP[0];
-
- value &= 0xffff;
+ unsigned int op0, op1, result, z, s, cy, ov;
- State.regs[OP[2]] = State.regs[OP[1]] & value;
-}
+ op0 = OP[0] & 0xffff;
+ op1 = State.regs[OP[1]];
+ result = op0 & op1;
-/* xor reg, reg
+ /* Compute the condition codes. */
+ z = (result == 0);
- XXX condition codes. */
+ /* Store the result and condition codes. */
+ State.regs[OP[2]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= (z ? PSW_Z : 0);
+}
+
+/* xor reg, reg */
void
OP_120 ()
{
- State.regs[OP[1]] ^= State.regs[OP[0]];
-}
+ unsigned int op0, op1, result, z, s, cy, ov;
-/* xori zero_extend(imm16), reg, reg
+ /* Compute the result. */
+ op0 = State.regs[OP[0]];
+ op1 = State.regs[OP[1]];
+ result = op0 ^ op1;
- XXX condition codes. */
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
+}
+
+/* xori zero_extend(imm16), reg, reg */
void
OP_6A0 ()
{
- int value = OP[0];
-
- value &= 0xffff;
+ unsigned int op0, op1, result, z, s, cy, ov;
+
+ op0 = OP[0] & 0xffff;
+ op1 = State.regs[OP[1]];
+ result = op0 ^ op1;
+
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
+
+ /* Store the result and condition codes. */
+ State.regs[OP[2]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
+ State.psw |= (z ? PSW_Z : 0);
+}
+
+/* not reg1, reg2 */
+void
+OP_20 ()
+{
+ unsigned int op0, result, z, s, cy, ov;
+
+ /* Compute the result. */
+ op0 = State.regs[OP[0]];
+ result = ~op0;
+
+ /* Compute the condition codes. */
+ z = (result == 0);
+ s = (result & 0x80000000);
- State.regs[OP[2]] = State.regs[OP[1]] ^ value;
+ /* Store the result and condition codes. */
+ State.regs[OP[1]] = result;
+ State.psw &= ~(PSW_Z | PSW_S | PSW_OV);
+ State.psw |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0));
}
void
typedef signed long long int64;
/* FIXME: V850 defines */
-typedef uint16 reg_t;
+typedef uint32 reg_t;
struct simops
{
struct _state
{
- reg_t regs[16]; /* general-purpose registers */
- reg_t cregs[16]; /* control registers */
- int64 a[2]; /* accumulators */
- uint8 SM;
- uint8 EA;
- uint8 DB;
- uint8 IE;
- uint8 RP;
- uint8 MD;
- uint8 FX;
- uint8 ST;
- uint8 F0;
- uint8 F1;
- uint8 C;
- uint8 exe;
+ reg_t regs[32]; /* general-purpose registers */
+ reg_t pc;
+ reg_t psw;
uint8 *imem;
uint8 *dmem;
int exception;
extern uint16 OP[4];
extern struct simops Simops[];
-#define PC (State.cregs[2])
-#define PSW (State.cregs[0])
-#define BPSW (State.cregs[1])
-#define BPC (State.cregs[3])
-#define RPT_C (State.cregs[7])
-#define RPT_S (State.cregs[8])
-#define RPT_E (State.cregs[9])
-#define MOD_S (State.cregs[10])
-#define MOD_E (State.cregs[11])
-#define IBA (State.cregs[14])
+#define PC (State.pc)
+#define PSW (State.psw)
+
+#define PSW_NP 0x80
+#define PSW_EP 0x40
+#define PSW_ID 0x20
+#define PSW_SAT 0x10
+#define PSW_CY 0x8
+#define PSW_OV 0x4
+#define PSW_S 0x2
+#define PSW_Z 0x1
#define SEXT3(x) ((((x)&0x7)^(~3))+4)
#ifdef WORDS_BIGENDIAN
-#define RW(x) (*((uint16 *)((x)+State.imem)))
-#define RLW(x) (*((uint32 *)((x)+State.imem)))
-#define SW(addr,data) RW(addr)=data
+#define RW(x) (*((uint16 *)((x)+State.imem)))
+#define RLW(x) (*((uint32 *)((x)+State.imem)))
+#define SW(addr,data) RW(addr)=data
+#define READ_16(x) (*((int16 *)(x)))
+#define WRITE_16(addr,data) (*(int16 *)(addr)=data)
+#define READ_64(x) (*((int64 *)(x)))
+#define WRITE_64(addr,data) (*(int64 *)(addr)=data)
#else
-uint32 get_longword_swap PARAMS ((uint16 x));
-uint16 get_word_swap PARAMS ((uint16 x));
-void write_word_swap PARAMS ((uint16 addr, uint16 data));
-#define SW(addr,data) write_word_swap(addr,data)
-#define RW(x) get_word_swap(x)
-#define RLW(x) get_longword_swap(x)
+uint32 get_longword PARAMS ((uint8 *));
+uint16 get_word PARAMS ((uint8 *));
+int64 get_longlong PARAMS ((uint8 *));
+void write_word PARAMS ((uint8 *addr, uint16 data));
+void write_longlong PARAMS ((uint8 *addr, int64 data));
+
+#define SW(addr,data) write_word((long)(addr)+State.imem,data)
+#define RW(x) get_word((long)(x)+State.imem)
+#define RLW(x) get_longword((long)(x)+State.imem)
+#define READ_16(x) get_word(x)
+#define WRITE_16(addr,data) write_word(addr,data)
+#define READ_64(x) get_longlong(x)
+#define WRITE_64(addr,data) write_longlong(addr,data)
#endif /* not WORDS_BIGENDIAN */