* sim-main.h: add vif registers
* interp.c: incorporate vif register load/store * sky-pke.[ch]: add register load/store routines * sku-vu.c: P register is float
This commit is contained in:
parent
69d5a56645
commit
c567d0b941
@ -197,6 +197,68 @@ pke_attach(SIM_DESC sd, struct pke_device* me)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read PKE Pseudo-PC into buf in target order */
|
||||||
|
int
|
||||||
|
read_pke_pc (struct pke_device *me, void *buf)
|
||||||
|
{
|
||||||
|
*((int *) buf) = H2T_4( me->fifo_pc );
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read PKE reg into buf in target order */
|
||||||
|
int
|
||||||
|
read_pke_reg (struct pke_device *me, int reg_num, void *buf)
|
||||||
|
{
|
||||||
|
/* handle reads to individual registers; clear `readable' on error */
|
||||||
|
switch (reg_num)
|
||||||
|
{
|
||||||
|
/* handle common case of register reading, side-effect free */
|
||||||
|
/* PKE1-only registers*/
|
||||||
|
case PKE_REG_BASE:
|
||||||
|
case PKE_REG_OFST:
|
||||||
|
case PKE_REG_TOPS:
|
||||||
|
case PKE_REG_TOP:
|
||||||
|
case PKE_REG_DBF:
|
||||||
|
if (me->pke_number == 0)
|
||||||
|
{
|
||||||
|
*((int *) buf) = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
/* PKE0 & PKE1 common registers*/
|
||||||
|
case PKE_REG_STAT:
|
||||||
|
case PKE_REG_ERR:
|
||||||
|
case PKE_REG_MARK:
|
||||||
|
case PKE_REG_CYCLE:
|
||||||
|
case PKE_REG_MODE:
|
||||||
|
case PKE_REG_NUM:
|
||||||
|
case PKE_REG_MASK:
|
||||||
|
case PKE_REG_CODE:
|
||||||
|
case PKE_REG_ITOPS:
|
||||||
|
case PKE_REG_ITOP:
|
||||||
|
case PKE_REG_R0:
|
||||||
|
case PKE_REG_R1:
|
||||||
|
case PKE_REG_R2:
|
||||||
|
case PKE_REG_R3:
|
||||||
|
case PKE_REG_C0:
|
||||||
|
case PKE_REG_C1:
|
||||||
|
case PKE_REG_C2:
|
||||||
|
case PKE_REG_C3:
|
||||||
|
*((int *) buf) = H2T_4(me->regs[reg_num][0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* handle common case of write-only registers */
|
||||||
|
case PKE_REG_FBRST:
|
||||||
|
*((int *) buf) = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(0); /* tests above should prevent this possibility */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Handle a PKE read; return no. of bytes read */
|
/* Handle a PKE read; return no. of bytes read */
|
||||||
@ -231,68 +293,15 @@ pke_io_read_buffer(device *me_,
|
|||||||
/* register bank */
|
/* register bank */
|
||||||
int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
|
int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
|
||||||
int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
|
int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
|
||||||
int readable = 1;
|
|
||||||
quadword result;
|
quadword result;
|
||||||
|
|
||||||
/* clear result */
|
/* clear result */
|
||||||
result[0] = result[1] = result[2] = result[3] = 0;
|
result[0] = result[1] = result[2] = result[3] = 0;
|
||||||
|
|
||||||
/* handle reads to individual registers; clear `readable' on error */
|
read_pke_reg (me, reg_num, result);
|
||||||
switch(reg_num)
|
|
||||||
{
|
|
||||||
/* handle common case of register reading, side-effect free */
|
|
||||||
/* PKE1-only registers*/
|
|
||||||
case PKE_REG_BASE:
|
|
||||||
case PKE_REG_OFST:
|
|
||||||
case PKE_REG_TOPS:
|
|
||||||
case PKE_REG_TOP:
|
|
||||||
case PKE_REG_DBF:
|
|
||||||
if(me->pke_number == 0)
|
|
||||||
readable = 0;
|
|
||||||
/* fall through */
|
|
||||||
/* PKE0 & PKE1 common registers*/
|
|
||||||
case PKE_REG_STAT:
|
|
||||||
case PKE_REG_ERR:
|
|
||||||
case PKE_REG_MARK:
|
|
||||||
case PKE_REG_CYCLE:
|
|
||||||
case PKE_REG_MODE:
|
|
||||||
case PKE_REG_NUM:
|
|
||||||
case PKE_REG_MASK:
|
|
||||||
case PKE_REG_CODE:
|
|
||||||
case PKE_REG_ITOPS:
|
|
||||||
case PKE_REG_ITOP:
|
|
||||||
case PKE_REG_R0:
|
|
||||||
case PKE_REG_R1:
|
|
||||||
case PKE_REG_R2:
|
|
||||||
case PKE_REG_R3:
|
|
||||||
case PKE_REG_C0:
|
|
||||||
case PKE_REG_C1:
|
|
||||||
case PKE_REG_C2:
|
|
||||||
case PKE_REG_C3:
|
|
||||||
result[0] = H2T_4(me->regs[reg_num][0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* handle common case of write-only registers */
|
|
||||||
case PKE_REG_FBRST:
|
|
||||||
readable = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ASSERT(0); /* test above should prevent this possibility */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* perform transfer & return */
|
/* perform transfer & return */
|
||||||
if(readable)
|
|
||||||
{
|
|
||||||
/* copy the bits */
|
|
||||||
memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes);
|
memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes);
|
||||||
/* okay */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* return zero bits */
|
|
||||||
memset(dest, 0, nr_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nr_bytes;
|
return nr_bytes;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@ -311,51 +320,13 @@ pke_io_read_buffer(device *me_,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write PKE reg from buf, which is in target order */
|
||||||
/* Handle a PKE read; return no. of bytes written */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
pke_io_write_buffer(device *me_,
|
write_pke_reg (struct pke_device *me, int reg_num, const void *buf)
|
||||||
const void *src,
|
|
||||||
int space,
|
|
||||||
address_word addr,
|
|
||||||
unsigned nr_bytes,
|
|
||||||
sim_cpu *cpu,
|
|
||||||
sim_cia cia)
|
|
||||||
{
|
{
|
||||||
/* downcast to gather embedding pke_device struct */
|
|
||||||
struct pke_device* me = (struct pke_device*) me_;
|
|
||||||
|
|
||||||
/* find my address ranges */
|
|
||||||
address_word my_reg_start =
|
|
||||||
(me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START;
|
|
||||||
address_word my_fifo_addr =
|
|
||||||
(me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR;
|
|
||||||
|
|
||||||
/* enforce that an access does not span more than one quadword */
|
|
||||||
address_word low = ADDR_TRUNC_QW(addr);
|
|
||||||
address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
|
|
||||||
if(low != high)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* classify address & handle */
|
|
||||||
if((addr >= my_reg_start) && (addr < my_reg_start + PKE_REGISTER_WINDOW_SIZE))
|
|
||||||
{
|
|
||||||
/* register bank */
|
|
||||||
int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
|
|
||||||
int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
|
|
||||||
int writeable = 1;
|
int writeable = 1;
|
||||||
quadword input;
|
|
||||||
|
|
||||||
/* clear input */
|
|
||||||
input[0] = input[1] = input[2] = input[3] = 0;
|
|
||||||
|
|
||||||
/* write user-given bytes into input */
|
|
||||||
memcpy(((unsigned_1*) &input) + reg_byte, src, nr_bytes);
|
|
||||||
|
|
||||||
/* make words host-endian */
|
/* make words host-endian */
|
||||||
input[0] = T2H_4(input[0]);
|
unsigned_4 input = T2H_4( *((unsigned_4 *) buf) );
|
||||||
/* we may ignore other words */
|
|
||||||
|
|
||||||
/* handle writes to individual registers; clear `writeable' on error */
|
/* handle writes to individual registers; clear `writeable' on error */
|
||||||
switch (reg_num)
|
switch (reg_num)
|
||||||
@ -363,7 +334,7 @@ pke_io_write_buffer(device *me_,
|
|||||||
case PKE_REG_FBRST:
|
case PKE_REG_FBRST:
|
||||||
/* Order these tests from least to most overriding, in case
|
/* Order these tests from least to most overriding, in case
|
||||||
multiple bits are set. */
|
multiple bits are set. */
|
||||||
if(BIT_MASK_GET(input[0], PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E))
|
if(BIT_MASK_GET(input, PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E))
|
||||||
{
|
{
|
||||||
/* clear a bunch of status bits */
|
/* clear a bunch of status bits */
|
||||||
PKE_REG_MASK_SET(me, STAT, PSS, 0);
|
PKE_REG_MASK_SET(me, STAT, PSS, 0);
|
||||||
@ -375,15 +346,15 @@ pke_io_write_buffer(device *me_,
|
|||||||
me->flags &= ~PKE_FLAG_PENDING_PSS;
|
me->flags &= ~PKE_FLAG_PENDING_PSS;
|
||||||
/* will allow resumption of possible stalled instruction */
|
/* will allow resumption of possible stalled instruction */
|
||||||
}
|
}
|
||||||
if(BIT_MASK_GET(input[0], PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E))
|
if(BIT_MASK_GET(input, PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E))
|
||||||
{
|
{
|
||||||
me->flags |= PKE_FLAG_PENDING_PSS;
|
me->flags |= PKE_FLAG_PENDING_PSS;
|
||||||
}
|
}
|
||||||
if(BIT_MASK_GET(input[0], PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E))
|
if(BIT_MASK_GET(input, PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E))
|
||||||
{
|
{
|
||||||
PKE_REG_MASK_SET(me, STAT, PFS, 1);
|
PKE_REG_MASK_SET(me, STAT, PFS, 1);
|
||||||
}
|
}
|
||||||
if(BIT_MASK_GET(input[0], PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E))
|
if(BIT_MASK_GET(input, PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E))
|
||||||
{
|
{
|
||||||
pke_reset(me);
|
pke_reset(me);
|
||||||
}
|
}
|
||||||
@ -391,12 +362,12 @@ pke_io_write_buffer(device *me_,
|
|||||||
|
|
||||||
case PKE_REG_ERR:
|
case PKE_REG_ERR:
|
||||||
/* copy bottom three bits */
|
/* copy bottom three bits */
|
||||||
BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input[0], 0, 2));
|
BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input, 0, 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PKE_REG_MARK:
|
case PKE_REG_MARK:
|
||||||
/* copy bottom sixteen bits */
|
/* copy bottom sixteen bits */
|
||||||
PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input[0], 0, 15));
|
PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input, 0, 15));
|
||||||
/* reset MRK bit in STAT */
|
/* reset MRK bit in STAT */
|
||||||
PKE_REG_MASK_SET(me, STAT, MRK, 0);
|
PKE_REG_MASK_SET(me, STAT, MRK, 0);
|
||||||
break;
|
break;
|
||||||
@ -439,9 +410,52 @@ pke_io_write_buffer(device *me_,
|
|||||||
/* perform return */
|
/* perform return */
|
||||||
if(! writeable)
|
if(! writeable)
|
||||||
{
|
{
|
||||||
; /* error */
|
return 0; /* error */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
/* Handle a PKE write; return no. of bytes written */
|
||||||
|
|
||||||
|
int
|
||||||
|
pke_io_write_buffer(device *me_,
|
||||||
|
const void *src,
|
||||||
|
int space,
|
||||||
|
address_word addr,
|
||||||
|
unsigned nr_bytes,
|
||||||
|
sim_cpu *cpu,
|
||||||
|
sim_cia cia)
|
||||||
|
{
|
||||||
|
/* downcast to gather embedding pke_device struct */
|
||||||
|
struct pke_device* me = (struct pke_device*) me_;
|
||||||
|
|
||||||
|
/* find my address ranges */
|
||||||
|
address_word my_reg_start =
|
||||||
|
(me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START;
|
||||||
|
address_word my_fifo_addr =
|
||||||
|
(me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR;
|
||||||
|
|
||||||
|
/* enforce that an access does not span more than one quadword */
|
||||||
|
address_word low = ADDR_TRUNC_QW(addr);
|
||||||
|
address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
|
||||||
|
if(low != high)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* classify address & handle */
|
||||||
|
if((addr >= my_reg_start) && (addr < my_reg_start + PKE_REGISTER_WINDOW_SIZE))
|
||||||
|
{
|
||||||
|
/* register bank */
|
||||||
|
int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
|
||||||
|
int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
|
||||||
|
quadword input;
|
||||||
|
|
||||||
|
/* clear input */
|
||||||
|
input[0] = input[1] = input[2] = input[3] = 0;
|
||||||
|
|
||||||
|
/* write user-given bytes into input */
|
||||||
|
memcpy(((unsigned_1*) &input) + reg_byte, src, nr_bytes);
|
||||||
|
|
||||||
|
write_pke_reg (me, reg_num, input);
|
||||||
return nr_bytes;
|
return nr_bytes;
|
||||||
|
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
@ -412,6 +412,13 @@ struct pke_device
|
|||||||
int qw_pc; /* 0 .. 3: word index of next instruction */
|
int qw_pc; /* 0 .. 3: word index of next instruction */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct pke_device pke0_device;
|
||||||
|
extern struct pke_device pke1_device;
|
||||||
|
|
||||||
|
int read_pke_reg (struct pke_device *device, int regno, void *buf);
|
||||||
|
int write_pke_reg (struct pke_device *device, int regno, const void *buf);
|
||||||
|
int read_pke_pc (struct pke_device *device, void *buf);
|
||||||
|
|
||||||
|
|
||||||
/* Flags for PKE.flags */
|
/* Flags for PKE.flags */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user