spinsim/pasmsim2.c

4713 lines
148 KiB
C
Executable File

/*******************************************************************************
' Author: Dave Hein
' Version 0.21
' Copyright (c) 2010 - 2015
' See end of file for terms of use.
'******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "interp.h"
#include "spinsim.h"
#define NUM_ICACHE 1
#define ADDR_MASK 0xfffff
#define IGNORE_WZ_WC
#define PRINT_RAM_ACCESS
//#define PRINT_STREAM_FIFO
#define REG_IJMP3 0x1f0
#define REG_IRET3 0x1f1
#define REG_IJMP2 0x1f2
#define REG_IRET2 0x1f3
#define REG_IJMP1 0x1f4
#define REG_IRET1 0x1f5
#define REG_PA 0x1f6
#define REG_PB 0x1f7
#define REG_PTRA 0x1f8
#define REG_PTRB 0x1f9
#define REG_DIRA 0x1fa
#define REG_DIRB 0x1fb
#define REG_OUTA 0x1fc
#define REG_OUTB 0x1fd
#define REG_PINA 0x1fe
#define REG_PINB 0x1ff
extern char *hubram;
extern int32_t memsize;
extern char lockstate[16];
extern char lockalloc[16];
extern PasmVarsT PasmVars[16];
extern int32_t pasmspin;
extern int32_t cycleaccurate;
extern int32_t loopcount;
extern int32_t pin_val_a;
extern int32_t pin_val_b;
extern SerialT serial_in;
extern SerialT serial_out;
extern int32_t nohubslots;
extern FILE *tracefile;
extern int32_t kludge;
static int wrl_flags0 = 0;
static int wrl_flags1 = 0;
static int rdl_flags0 = 0;
static int rdl_flags1 = 0;
char *GetOpname2(unsigned int, int *, int *, int *);
static void NotImplemented(int instruction)
{
int dummy;
char *opname = GetOpname2(instruction, &dummy, &dummy, &dummy);
printf("%s%s not implemented - %8.8x%s", NEW_LINE, opname, instruction, NEW_LINE);
spinsim_exit(1);
}
static int32_t getpinval(int32_t val)
{
int pin_num = val & 63;
if (pin_num < 32) return (pin_val_a >> pin_num) & 1;
return (pin_val_b >> (pin_num - 32)) & 1;
}
static int32_t parity(int32_t val)
{
val ^= val >> 16;
val ^= val >> 8;
val ^= val >> 4;
val ^= val >> 2;
val ^= val >> 1;
return val & 1;
}
static int32_t _abs(int32_t val)
{
return val < 0 ? -val : val;
}
static uint32_t sqrt64(uint64_t y)
{
uint64_t x, t1;
x = 0;
t1 = 1;
//t1 <<= 60;
t1 <<= 62;
while (t1)
{
x |= t1;
if (x <= y)
{
y -= x;
x += t1;
}
else
x -= t1;
x >>= 1;
t1 >>= 2;
}
return (uint32_t)x;
}
static int32_t seuss(int32_t value, int32_t forward)
{
uint32_t i, x;
uint8_t bitnum[32] = {
11, 5, 18, 24, 27, 19, 20, 30, 28, 26, 21, 25, 3, 8, 7, 23,
13, 12, 16, 2, 15, 1, 9, 31, 0, 29, 17, 10, 14, 4, 6, 22};
if (forward)
{
x = 0x354dae51;
for (i = 0; i < 32; i++)
{
if (value & (1 << i))
x ^= (1 << bitnum[i]);
}
}
else
{
x = 0xeb55032d;
for (i = 0; i < 32; i++)
{
if (value & (1 << bitnum[i]))
x ^= (1 << i);
}
}
return x;
}
#if 0
static int32_t CheckWaitPin(PasmVarsT *pasmvars, int32_t instruct, int32_t value1, int32_t value2)
{
int32_t match, pin_values;
int32_t portnum = (instruct >> 24) & 3;
if (portnum == 0)
pin_values = pin_val;
else
pin_values = 0xffffffff;
if (instruct & 0x04000000)
match = ((pin_values & value2) != value1); // waitpne
else
match = ((pin_values & value2) == value1); // waitpne
return match;
}
#endif
static void CheckWaitIntState(PasmVarsT *pasmvars)
{
//printf("\nCheckWaitIntState: intflags = %8.8x\n", pasmvars->intflags);
// Check if interrupts disabled or INT1 active
if (pasmvars->intstate & 3) return;
// Check INT1
if (pasmvars->intenable1)
{
int bitmask = (1 << pasmvars->intenable1);
if (pasmvars->intflags & bitmask)
{
pasmvars->intflags |= 1;
//printf("INT1\n");
return;
}
}
// Check if interrupts disabled or INT1 or INT2 active
if (pasmvars->intstate & 7) return;
// Check INT2
if (pasmvars->intenable2)
{
int bitmask = (1 << pasmvars->intenable2);
if (pasmvars->intflags & bitmask)
{
//printf("INT2\n");
pasmvars->intflags |= 1;
return;
}
}
// Check if interrupts disabled or INT1, INT2 or INT3 active
if (pasmvars->intstate & 15) return;
// Check INT3
if (pasmvars->intenable3)
{
int bitmask = (1 << pasmvars->intenable3);
if (pasmvars->intflags & bitmask)
{
//printf("INT3\n");
pasmvars->intflags |= 1;
return;
}
}
}
static int32_t stream_fifo_level(PasmVarsT *pasmvars)
{
return (pasmvars->str_fifo_windex - pasmvars->str_fifo_rindex) & 15;
}
#define INSTR_MASK1 0x0fe001ff
#define INSTR_MASK2 0x0fe3e1ff
#define INSTR_LOCKNEW 0x0d600004
#define INSTR_LOCKSET 0x0d600007
#define INSTR_QLOG 0x0d60000e
#define INSTR_QEXP 0x0d60000f
#define INSTR_RFBYTE 0x0d600010
#define INSTR_RFWORD 0x0d600011
#define INSTR_RFLONG 0x0d600012
#define INSTR_WFBYTE 0x0d600015
#define INSTR_WFWORD 0x0d600016
#define INSTR_WFLONG 0x0d600017
#define INSTR_GETQX 0x0d600018
#define INSTR_GETQY 0x0d600019
#define INSTR_WAITX 0x0d60001f
#define INSTR_WAITXXX 0x0d602024
#define OPCODE_WMLONG 0x53
#define OPCODE_RDBYTE 0x56
#define OPCODE_RDWORD 0x57
#define OPCODE_RDLONG 0x58
#define OPCODE_CALLD 0x59
#define OPCODE_CALLPB 0x5e
#define OPCODE_JINT 0x5f
#define OPCODE_WRBYTE 0x62
#define OPCODE_WRWORD 0x62
#define OPCODE_WRLONG 0x63
#define OPCODE_QMUL 0x68
#define OPCODE_QVECTOR 0x6a
static int32_t CheckWaitFlag2(PasmVarsT *pasmvars, int instruct, int value1, int value2, int streamflag)
{
int32_t hubcycles;
int32_t waitmode = 0;
int32_t waitflag = pasmvars->waitflag;
int32_t opcode = (instruct >> 21) & 127;
int32_t czi = (instruct >> 18) & 7;
int32_t hubop = 0;
int32_t instruct1 = (instruct & INSTR_MASK1);
int32_t instruct2 = (instruct & INSTR_MASK2);
int32_t temp;
//int32_t srcaddr = instruct & 0x1ff;
//printf("CheckWaitFlag2: waitflag = %d, instruct = %8.8x\n", waitflag, instruct);
if (waitflag)
{
if (pasmvars->waitmode == WAIT_CACHE)
{
printf("We shouldn't be here!%s", NEW_LINE);
return 0;
}
if (pasmvars->waitmode == WAIT_CORDIC)
{
if (instruct1 == INSTR_GETQX) // getqx
{
if (pasmvars->qxposted) waitflag = 0;
}
else if (instruct1 == INSTR_GETQY) // getqy
{
if (pasmvars->qyposted) waitflag = 0;
}
pasmvars->waitflag = waitflag;
if (waitflag == 0) pasmvars->waitmode = 0;
return waitflag;
}
if (pasmvars->waitmode != WAIT_FLAG)
{
waitflag--;
if (waitflag == 0)
{
if (pasmvars->waitmode == WAIT_HUB && streamflag)
waitflag = 16;
else
pasmvars->waitmode = 0;
}
pasmvars->waitflag = waitflag;
return waitflag;
}
}
if (pasmvars->rwrep)
{
if (!streamflag) return 0;
//printf("Better wait\n");
pasmvars->waitmode = WAIT_HUB;
pasmvars->waitflag = 16;
return pasmvars->waitflag;
}
if (nohubslots)
hubcycles = 0;
else
hubcycles = (pasmvars->cogid + (value2 >> 2) - loopcount) & 15;
if (instruct1 == INSTR_GETQX) // getqx
{
if (!pasmvars->qxposted && pasmvars->cordic_count)
{
waitflag = 1;
waitmode = WAIT_CORDIC;
}
}
else if (instruct1 == INSTR_GETQY) // getqy
{
if (!pasmvars->qyposted && pasmvars->cordic_count)
{
waitflag = 1;
waitmode = WAIT_CORDIC;
}
}
else if (instruct2 == INSTR_WAITXXX) // waitxxx
{
if ((instruct & 0x3ffff) == 0x02024) // waitint
CheckWaitIntState(pasmvars);
temp = 1 << ((instruct >> 9) & 15);
if (pasmvars->intflags & temp)
{
waitmode = 0;
waitflag = 0;
}
else
{
waitmode = WAIT_FLAG;
waitflag = 1;
}
}
else if (instruct1 == INSTR_WAITX) // waitx
{
waitmode = WAIT_CNT;
waitflag = value1;
}
else if (opcode >= OPCODE_RDBYTE && opcode <= OPCODE_RDLONG) // rdxxxx
{
hubop = 1;
waitmode = WAIT_HUB;
waitflag = hubcycles + 2;
}
else if (opcode == OPCODE_WRBYTE || (opcode == OPCODE_WRLONG && (czi&4) == 0) || (opcode == OPCODE_WMLONG && (czi>>1) == 3)) // wrxxxx
{
hubop = 1;
waitmode = WAIT_HUB;
waitflag = hubcycles + 2;
}
else if ((opcode >= OPCODE_QMUL && opcode <= OPCODE_QVECTOR) || instruct1 == INSTR_QLOG || instruct1 == INSTR_QEXP) // qxxxx
{
hubop = 1;
waitmode = WAIT_HUB;
waitflag = ((pasmvars->cogid - loopcount) & 15) + 1;
}
else if (instruct1 >= INSTR_LOCKNEW && instruct1 <= INSTR_LOCKSET) // lockxxx
{
hubop = 1;
waitmode = WAIT_HUB;
waitflag = ((pasmvars->cogid - loopcount) & 15) + 1;
}
else if (instruct1 >= INSTR_RFBYTE && instruct1 <= INSTR_RFLONG) // rfxxxx
{
if (stream_fifo_level(pasmvars) < 2)
{
waitmode = WAIT_CACHE;
waitflag = 1;
}
else
waitflag = 0;
}
else if (instruct1 >= INSTR_WFBYTE && instruct1 <= INSTR_WFLONG) // wfxxxx
{
if (stream_fifo_level(pasmvars) >= 15)
{
waitmode = WAIT_CACHE;
waitflag = 1;
}
else
waitflag = 0;
}
else
waitflag = 0;
pasmvars->waitflag = waitflag;
pasmvars->waitmode = waitmode;
return hubop;
}
// Compute the hub RAM address from the pointer instruction - 1SUPIIIII
static int32_t GetPointer(PasmVarsT *pasmvars, int32_t ptrinst, int32_t size)
{
int32_t address = 0; // Set to zero to avoid compiler warning
int32_t offset = (ptrinst << 27) >> (27 - size);
//printf("GetPointer: ptrinst = %x, case = %d, size = %d, offset = %d\n",
//ptrinst, (ptrinst >> 5) & 7, size, offset);
switch ((ptrinst >> 5) & 7)
{
case 0: // ptra[offset]
address = (pasmvars->ptra + offset) & ADDR_MASK;
break;
case 1: // ptra
address = pasmvars->ptra;
break;
case 2: // ptra[++offset]
address = (pasmvars->ptra + offset) & ADDR_MASK;
//pasmvars->ptra = address;
pasmvars->ptra0 = address;
break;
case 3: // ptra[offset++]
address = pasmvars->ptra;
//pasmvars->ptra = (pasmvars->ptra + offset) & ADDR_MASK;
pasmvars->ptra0 = (pasmvars->ptra + offset) & ADDR_MASK;
break;
case 4: // ptrb[offset]
address = (pasmvars->ptrb + offset) & ADDR_MASK;
break;
case 5: // ptrb
address = pasmvars->ptrb;
break;
case 6: // ptrb[++offset]
address = (pasmvars->ptrb + offset) & ADDR_MASK;
//pasmvars->ptrb = address;
pasmvars->ptrb0 = address;
break;
case 7: // ptrb[offset++]
address = pasmvars->ptrb;
//pasmvars->ptrb = (pasmvars->ptrb + offset) & ADDR_MASK;
pasmvars->ptrb0 = (pasmvars->ptrb + offset) & ADDR_MASK;
break;
}
return address;
}
void UpdatePins2(void)
{
int32_t i;
int32_t mask1;
int32_t val;
int32_t mask;
val = mask = 0;
for (i = 0; i < 16; i++)
{
if (PasmVars[i].state)
{
mask1 = PasmVars[i].mem[REG_DIRA]; // dira
val |= mask1 & PasmVars[i].mem[REG_OUTA]; // outa
mask |= mask1;
}
}
pin_val_a = (~mask) | val;
val = mask = 0;
for (i = 0; i < 16; i++)
{
if (PasmVars[i].state)
{
mask1 = PasmVars[i].mem[REG_DIRB]; // dirb
val |= mask1 & PasmVars[i].mem[REG_OUTB]; // outb
mask |= mask1;
}
}
pin_val_b = (~mask) | val;
//printf("UpdatePins2: %8.8x %8.8x\n", pin_val_b, pin_val_a);
}
static void SaveRegisters(PasmVarsT *pasmvars)
{
pasmvars->ptra0 = pasmvars->ptra;
pasmvars->ptrb0 = pasmvars->ptrb;
}
static void UpdateRegisters(PasmVarsT *pasmvars)
{
pasmvars->ptra = pasmvars->ptra0;
pasmvars->ptrb = pasmvars->ptrb0;
}
static void start_fast_mode(PasmVarsT *pasmvars, int32_t addr0, int32_t addr1, int32_t mode)
{
pasmvars->str_fifo_mode = mode;
pasmvars->str_fifo_tail_addr = addr0;
pasmvars->str_fifo_head_addr = addr0;
pasmvars->str_fifo_rindex = pasmvars->str_fifo_windex;
pasmvars->str_fifo_addr0 = addr0;
pasmvars->str_fifo_addr1 = addr1;
pasmvars->str_fifo_work_flag = 0;
}
static void check_hubexec_mode(PasmVarsT *pasmvars)
{
if (pasmvars->pc & 0xffc00)
{
start_fast_mode(pasmvars, pasmvars->pc, pasmvars->pc, 3);
pasmvars->waitmode = WAIT_CACHE;
pasmvars->waitflag = 1;
}
else if (pasmvars->str_fifo_mode == 3)
pasmvars->str_fifo_mode = 0;
}
#if 0
static int32_t CheckForHubExecWait(PasmVarsT *pasmvars)
{
if (stream_fifo_level(pasmvars) == 0 || pasmvars->str_fifo_tail_addr != pasmvars->pc || pasmvars->str_fifo_mode != 3)
{
check_hubexec_mode(pasmvars);
#if 0
start_fast_mode(pasmvars, pasmvars->pc, pasmvars->pc, 3);
pasmvars->waitmode = WAIT_CACHE;
pasmvars->waitflag = 1;
#endif
return 1;
}
return 0;
}
#endif
static int32_t check_read_stream_fifo_level(PasmVarsT *pasmvars, char *ptr)
{
if (stream_fifo_level(pasmvars) == 0)
{
printf("%s: ERROR! level = %d, addr = %8.8x%s", ptr,
stream_fifo_level(pasmvars), pasmvars->str_fifo_tail_addr, NEW_LINE);
return 1;
}
return 0;
}
static int32_t read_stream_fifo(PasmVarsT *pasmvars, int target_addr)
{
int32_t index;
if (check_read_stream_fifo_level(pasmvars, "read_stream_fifo")) return 0;
if (target_addr >= 0 && pasmvars->str_fifo_tail_addr != target_addr)
{
printf("read_stream_fifo: ERROR! level = %d, addr = %8.8x, target = %8.8x%s",
stream_fifo_level(pasmvars), pasmvars->str_fifo_tail_addr, target_addr, NEW_LINE);
return 0;
}
index = pasmvars->str_fifo_rindex;
pasmvars->str_fifo_rindex = (index + 1) & 15;
pasmvars->str_fifo_tail_addr += 4;
if (pasmvars->str_fifo_tail_addr == pasmvars->str_fifo_addr1)
pasmvars->str_fifo_tail_addr = pasmvars->str_fifo_addr0;
return pasmvars->str_fifo_buffer[index];
}
static int32_t read_stream_fifo_byte(PasmVarsT *pasmvars)
{
int bytenum = pasmvars->str_fifo_tail_addr & 3;
int index = pasmvars->str_fifo_rindex;
uint8_t *bufptr = (uint8_t *)&pasmvars->str_fifo_buffer[index];
if (check_read_stream_fifo_level(pasmvars, "read_stream_fifo_byte")) return 0;
if (bytenum == 3) pasmvars->str_fifo_rindex = (index + 1) & 15;
pasmvars->str_fifo_tail_addr++;
if (pasmvars->str_fifo_tail_addr == pasmvars->str_fifo_addr1)
pasmvars->str_fifo_tail_addr = pasmvars->str_fifo_addr0;
return bufptr[bytenum];
}
static int32_t read_stream_fifo_word(PasmVarsT *pasmvars)
{
int value;
value = read_stream_fifo_byte(pasmvars);
value |= read_stream_fifo_byte(pasmvars) << 8;
return value;
}
static int32_t read_stream_fifo_long(PasmVarsT *pasmvars)
{
int value;
if (pasmvars->str_fifo_tail_addr & 3)
{
value = read_stream_fifo_word(pasmvars);
value |= read_stream_fifo_word(pasmvars) << 16;
}
else
value = read_stream_fifo(pasmvars, -1);
return value;
}
static void write_stream_fifo(PasmVarsT *pasmvars, int value)
{
int32_t index;
if (stream_fifo_level(pasmvars) >= 15)
{
printf("write_stream_fifo: ERROR! level = %d, addr = %8.8x%s",
stream_fifo_level(pasmvars), pasmvars->str_fifo_head_addr, NEW_LINE);
return;
}
index = pasmvars->str_fifo_windex;
pasmvars->str_fifo_buffer[index] = value;
pasmvars->str_fifo_windex = (index + 1) & 15;
pasmvars->str_fifo_head_addr += 4;
if (pasmvars->str_fifo_head_addr == pasmvars->str_fifo_addr1)
pasmvars->str_fifo_head_addr = pasmvars->str_fifo_addr0;
}
static void write_stream_fifo_byte(PasmVarsT *pasmvars, int value)
{
int bytenum = pasmvars->str_fifo_head_addr & 3;
int shift = bytenum * 8;
int mask = 255 << shift;
int work_word;
if (stream_fifo_level(pasmvars) >= 15)
{
printf("write_stream_fifo_byte: ERROR! level = %d, addr = %8.8x%s",
stream_fifo_level(pasmvars), pasmvars->str_fifo_head_addr, NEW_LINE);
return;
}
if (!pasmvars->str_fifo_work_flag)
work_word = LONG(pasmvars->str_fifo_head_addr);
else
work_word = pasmvars->str_fifo_work_word;
work_word = (work_word & ~mask) | ((value << shift) & mask);
//printf("work_word = %8.8x, shift = %x, mask = %8.8x, addr = %8.8x\n",
//work_word, shift, mask, pasmvars->str_fifo_head_addr);
pasmvars->str_fifo_head_addr++;
if (pasmvars->str_fifo_head_addr == pasmvars->str_fifo_addr1)
pasmvars->str_fifo_head_addr = pasmvars->str_fifo_addr0;
if (bytenum == 3)
{
int index = pasmvars->str_fifo_windex;
pasmvars->str_fifo_buffer[index] = work_word;
pasmvars->str_fifo_windex = (index + 1) & 15;
pasmvars->str_fifo_work_flag = 0;
}
else
{
pasmvars->str_fifo_work_word = work_word;
pasmvars->str_fifo_work_flag = 1;
}
}
static void write_stream_fifo_word(PasmVarsT *pasmvars, int value)
{
write_stream_fifo_byte(pasmvars, value);
write_stream_fifo_byte(pasmvars, value >> 8);
}
static void write_stream_fifo_long(PasmVarsT *pasmvars, int value)
{
if (pasmvars->str_fifo_head_addr & 3)
{
write_stream_fifo_byte(pasmvars, value);
write_stream_fifo_byte(pasmvars, value >> 16);
}
else
{
write_stream_fifo(pasmvars, value);
}
}
static int32_t CheckStreamFifo(PasmVarsT *pasmvars)
{
int addr, index, value, level;
if (pasmvars->str_fifo_mode == 0) return 0;
level = stream_fifo_level(pasmvars);
if (pasmvars->str_fifo_mode == 1 || pasmvars->str_fifo_mode == 3)
{
if (level >= 10) return 0;
index = pasmvars->str_fifo_windex;
addr = pasmvars->str_fifo_head_addr;
value = LONG(addr);
if ((pasmvars->cogid + (addr >> 2) - loopcount) & 15) return 0;
if (pasmvars->printflag == 0xf)
printf("Cog %2d: %8.8x fifo[%d] = hram[%x] = %8.8x%s",
pasmvars->cogid, loopcount, level, addr, value, NEW_LINE);
write_stream_fifo(pasmvars, value);
}
else if (pasmvars->str_fifo_mode == 2)
{
if (level == 0 && pasmvars->str_fifo_work_flag == 0) return 0;
addr = pasmvars->str_fifo_tail_addr;
if ((pasmvars->cogid + (addr >> 2) - loopcount) & 15) return 0;
if (level)
{
index = pasmvars->str_fifo_rindex;
value = pasmvars->str_fifo_buffer[index];
if (pasmvars->printflag == 0xf)
printf("Cog %2d: %8.8x hram[%x] = fifo[%d] = %8.8x%s",
pasmvars->cogid, loopcount, addr, level, value, NEW_LINE);
LONG(addr) = read_stream_fifo(pasmvars, -1);
}
else
{
value = pasmvars->str_fifo_work_word;
if (pasmvars->printflag == 0xf)
printf("Cog %2d: %8.8x hram[%x] = workword = %8.8x%s",
pasmvars->cogid, loopcount, addr, value, NEW_LINE);
LONG(addr) = pasmvars->str_fifo_work_word;
pasmvars->str_fifo_work_flag = 0;
}
}
return 1;
}
#if 0
static void CheckSerialPorts(PasmVarsT *pasmvars)
{
int addr, value1, value2;
if (pasmvars->serina.mode)
SerialReceive(&pasmvars->serina, pin_val);
if (pasmvars->serinb.mode)
SerialReceive(&pasmvars->serinb, pin_val);
if (pasmvars->serouta.mode)
{
addr = ((pasmvars->serouta.pin_num >> 5) & 3) + REG_OUTA;
value1 = pasmvars->mem[addr];
value2 = SerialSend(&pasmvars->serouta, value1);
if (value1 != value2)
{
pasmvars->mem[addr] = value2;
UpdatePins2();
}
}
if (pasmvars->seroutb.mode)
{
addr = ((pasmvars->seroutb.pin_num >> 5) & 3) + REG_OUTA;
value1 = pasmvars->mem[addr];
value2 = SerialSend(&pasmvars->seroutb, value1);
if (value1 != value2)
{
pasmvars->mem[addr] = value2;
UpdatePins2();
}
}
}
#endif
void UpdateRWlongFlags(void)
{
rdl_flags1 = rdl_flags0;
wrl_flags1 = wrl_flags0;
rdl_flags0 = 0;
wrl_flags0 = 0;
}
static void CheckInterruptFlags(PasmVarsT *pasmvars)
{
int count = GetCnt();
//if (count == pasmvars->cntreg1) { pasmvars->intflags |= (1 << 1); printf("\nCT1 FLAG SET\n"); printf("intflags = %8.8x\n", pasmvars->intflags); }
if (count == pasmvars->cntreg1) pasmvars->intflags |= (1 << 1);
if (count == pasmvars->cntreg2) pasmvars->intflags |= (1 << 2);
if (count == pasmvars->cntreg3) pasmvars->intflags |= (1 << 3);
if (pasmvars->pinpatmode)
{
switch (pasmvars->pinpatmode)
{
case 1:
if ((pin_val_a & pasmvars->pinpatmask) == pasmvars->pinpattern)
{
pasmvars->intflags |= (1 << 4);
pasmvars->pinpatmode = 0;
}
break;
case 2:
if ((pin_val_a & pasmvars->pinpatmask) != pasmvars->pinpattern)
{
pasmvars->intflags |= (1 << 4);
pasmvars->pinpatmode = 0;
}
break;
case 3:
if ((pin_val_b & pasmvars->pinpatmask) == pasmvars->pinpattern)
{
pasmvars->intflags |= (1 << 4);
pasmvars->pinpatmode = 0;
}
break;
case 4:
if ((pin_val_b & pasmvars->pinpatmask) != pasmvars->pinpattern)
{
pasmvars->intflags |= (1 << 4);
pasmvars->pinpatmode = 0;
}
break;
default:
pasmvars->pinpatmode = 0;
break;
}
}
if (pasmvars->pinedge & 0xc0)
{
int pin_prev = (pasmvars->pinedge >> 8) & 1;
if (pin_prev != getpinval(pasmvars->pinedge))
{
int pin_mode = (pasmvars->pinedge >> 6) & 3;
#ifdef DEBUG_STUFF
printf("\nPIN EDGE EVENT: mode = %d, prev = %d, curr = %d\n", pin_mode, pin_prev, getpinval(pasmvars->pinedge));
#endif
if (pin_mode == 3 || (pin_mode == 1 && !pin_prev) || (pin_mode == 2 && pin_prev))
{
//pasmvars->pinedge = 0;
pasmvars->intflags |= (1 << 5);
}
pasmvars->pinedge ^= 0x100;
}
}
if (pasmvars->rdl_mask & rdl_flags1)
{
//pasmvars->rdl_mask = 0;
pasmvars->intflags |= (1 << 6);
#ifdef DEBUG_STUFF
printf("\nSet RDL flag bit. mask = %8.8x flags = %8.8x\n", pasmvars->rdl_mask, rdl_flags1);
#endif
}
if (pasmvars->wrl_mask & wrl_flags1)
{
//pasmvars->wrl_mask = 0;
pasmvars->intflags |= (1 << 7);
#ifdef DEBUG_STUFF
printf("\nSet WRL flag bit. mask = %8.8x flags = %8.8x\n", pasmvars->wrl_mask, wrl_flags1);
#endif
}
if (pasmvars->lockedge & 0x30)
{
int lock_num = (pasmvars->lockedge & 15);
int lock_prev = (pasmvars->lockedge >> 6) & 1;
if (lock_prev != lockstate[lock_num])
{
int lock_mode = (pasmvars->lockedge >> 4) & 3;
#ifdef DEBUG_STUFF
printf("\nLOCK EDGE EVENT: mode = %d, prev = %d, curr = %d\n",
lock_mode, lock_prev, lockstate[lock_num]);
#endif
if (lock_mode == 3 || (lock_mode == 1 && !lock_prev) || (lock_mode == 2 && lock_prev))
{
pasmvars->intflags |= (1 << 8);
}
pasmvars->lockedge ^= 0x40;
}
}
}
static int CheckForInterrupt(PasmVarsT *pasmvars)
{
// Defer interrupt if invalidated instruction in pipeline
if (pasmvars->pc1 & INVALIDATE_INSTR) return 0;
// Defer interrupt if AUGS or AUGD is pending
if (pasmvars->augsflag || pasmvars->augdflag) return 0;
// Defer interrupt if memflag is set
if (pasmvars->memflag) return 0;
// Check if interrupts disabled or INT1 active
if (pasmvars->intstate & 3) return 0;
// Check INT1
if (pasmvars->intenable1)
{
int bitmask = (1 << pasmvars->intenable1);
if (pasmvars->intflags & bitmask)
{
pasmvars->intflags &= ~bitmask;
pasmvars->intflags |= 1;
pasmvars->instruct2 = 0xfabbebf4;
pasmvars->intstate |= 2;
#ifdef DEBUG_STUFF
printf("%d: INT1 %8.8x\n", pasmvars->cogid, bitmask);
#endif
return 1;
}
}
// Check if interrupts disabled or INT1 or INT2 active
if (pasmvars->intstate & 7) return 0;
// Check INT2
if (pasmvars->intenable2)
{
int bitmask = (1 << pasmvars->intenable2);
if (pasmvars->intflags & bitmask)
{
pasmvars->intflags &= ~bitmask;
pasmvars->intflags |= 1;
pasmvars->instruct2 = 0xfabbe7f2;
pasmvars->intstate |= 4;
#ifdef DEBUG_STUFF
printf("%d: INT2 %8.8x\n", pasmvars->cogid, bitmask);
#endif
return 1;
}
}
// Check if interrupts disabled or INT1, INT2 or INT3 active
if (pasmvars->intstate & 15) return 0;
// Check INT3
if (pasmvars->intenable3)
{
int bitmask = (1 << pasmvars->intenable3);
if (pasmvars->intflags & bitmask)
{
pasmvars->intflags &= ~bitmask;
pasmvars->intflags |= 1;
pasmvars->instruct2 = 0xfabbe3f0;
pasmvars->intstate |= 8;
#ifdef DEBUG_STUFF
printf("%d: INT3 %8.8x\n", pasmvars->cogid, bitmask);
#endif
return 1;
}
}
return 0;
}
static int32_t read_unaligned_word(int32_t addr)
{
uint16_t value;
memcpy(&value, &hubram[MAP_ADDR(addr)], 2);
return value;
}
static int32_t read_unaligned_long(int32_t addr)
{
int32_t value;
memcpy(&value, &hubram[MAP_ADDR(addr)], 4);
return value;
}
static void write_unaligned_word(int32_t addr, int32_t value)
{
memcpy(&hubram[MAP_ADDR(addr)], &value, 2);
}
static void write_unaligned_long(int32_t addr, int32_t value)
{
memcpy(&hubram[MAP_ADDR(addr)], &value, 4);
}
static int32_t start_cordic(PasmVarsT *pasmvars)
{
int32_t cordic_depth = pasmvars->cordic_depth++;
if (cordic_depth >= 3)
{
printf("%sERROR: CORDIC overflow! - %d%s", NEW_LINE, cordic_depth, NEW_LINE);
cordic_depth = 2;
}
if (!cordic_depth)
{
pasmvars->qxposted = 0;
pasmvars->qyposted = 0;
pasmvars->cordic_count = 38;
}
return cordic_depth;
}
static int32_t ProcessAltiIncrement(int32_t value1, int32_t value2)
{
int32_t temp, mask;
int32_t rrr = (value2 >> 6) & 7;
int32_t ddd = (value2 >> 3) & 7;
int32_t sss = value2 & 7;
if (rrr & 2)
{
temp = (value2 >> 15) & 7;
mask = (1 << (9 - temp)) - 1;
temp = value1 >> 19;
temp += ((rrr&1)<<1) - 1;
temp &= mask;
value1 = (value1 & ~(mask << 19)) | (temp << 19);
}
if (ddd & 2)
{
temp = (value2 >> 12) & 7;
mask = (1 << (9 - temp)) - 1;
temp = value1 >> 9;
temp += ((ddd&1)<<1) - 1;
temp &= mask;
value1 = (value1 & ~(mask << 9)) | (temp << 9);
}
if (sss & 2)
{
temp = (value2 >> 9) & 7;
mask = (1 << (9 - temp)) - 1;
temp = value1;
temp += ((sss&1)<<1) - 1;
temp &= mask;
value1 = (value1 & ~mask) | temp;
}
return value1;
}
#if 0
static void ProcessAltiFetch(PasmVarsT *pasmvars)
{
int32_t instruct = pasmvars->instruct2;
int32_t value = pasmvars->altivalue;
int32_t rrr = (pasmvars->altiflag >> 6) & 7;
int32_t ddd = (pasmvars->altiflag >> 3) & 7;
int32_t sss = pasmvars->altiflag & 7;
switch (rrr)
{
case 1:
pasmvars->altrflag = 1;
pasmvars->altrvalue = -1;
break;
case 4:
case 6:
case 7:
pasmvars->altrflag = 1;
pasmvars->altrvalue = (instruct >> 19) & 0x1ff;
break;
case 5:
instruct = (instruct & 0x3ffff) | (value & ~0x3ffff);
break;
}
switch (ddd)
{
case 1:
instruct = (instruct & ~0x3fe00) | ((value << 9) & 0x3fe00);
break;
case 4:
case 5:
case 6:
case 7:
instruct = (instruct & ~0x3fe00) | (value & 0x3fe00);
break;
}
switch (sss)
{
case 1:
instruct = (instruct & ~0x1ff) | ((value >> 9) & 0x1ff);
break;
case 4:
case 5:
case 6:
case 7:
instruct = (instruct & ~0x1ff) | (value & 0x1ff);
break;
}
pasmvars->instruct2 = instruct;
pasmvars->altiflag = 0;
}
#endif
int32_t pointer_shift(int32_t instruct)
{
int32_t opcode = (instruct >> 21) & 127;
int32_t czi = (instruct >> 18) & 7;
if (opcode == OPCODE_WMLONG && (czi >> 1) == 3) return 2; // wmlong
if (opcode == OPCODE_RDBYTE) return 0; // rdbyte
if (opcode == OPCODE_RDWORD) return 1; // rdword
if (opcode == OPCODE_RDLONG) return 2; // rdlong
if (opcode == OPCODE_WRBYTE && (czi >> 2) == 0) return 0; // wrbyte
if (opcode == OPCODE_WRWORD && (czi >> 2) == 1) return 1; // wrword
if (opcode == OPCODE_WRLONG && (czi >> 2) == 0) return 2; // wrlong
return -1;
}
int32_t ModifyFlag(int cflag, int zflag, int func)
{
int retval;
switch (func & 15)
{
case 0:
retval = 0;
break;
case 1:
retval = (cflag ^ 1) & (zflag ^ 1);
break;
case 2:
retval = (cflag ^ 1) & zflag;
break;
case 3:
retval = (cflag ^ 1);
break;
case 4:
retval = cflag & (zflag ^ 1);
break;
case 5:
retval = (zflag ^ 1);
break;
case 6:
retval = (cflag != zflag);
break;
case 7:
retval = (cflag ^ 1) | (zflag ^ 1);
break;
case 8:
retval = cflag & zflag;
break;
case 9:
retval = (cflag == zflag);
break;
case 10:
retval = zflag;
break;
case 11:
retval = (cflag ^ 1) | zflag;
break;
case 12:
retval = cflag;
break;
case 13:
retval = cflag | (zflag ^ 1);
break;
case 14:
retval = cflag | zflag;
break;
case 15:
retval = 1;
break;
}
return retval;
}
int32_t GetMixVal(int32_t mode, int32_t var, int32_t sbyte, int32_t dbyte)
{
int32_t rval;
switch (mode & 7)
{
case 0:
rval = 0;
break;
case 1:
rval = 0xff;
break;
case 2:
rval = var & 255;
break;
case 3:
rval = (~var) & 255;
break;
case 4:
rval = sbyte & 255;
break;
case 5:
rval = (~sbyte) & 255;
break;
case 6:
rval = dbyte & 255;
break;
case 7:
rval = (~dbyte) & 255;
break;
}
return rval;
}
void CheckSkip(PasmVarsT *pasmvars)
{
int i;
if (pasmvars->skip_mode & 1)
{
for (i = 0; i < 7; i++)
{
if (!(pasmvars->skip_mode & 1)) break;
pasmvars->pc++;
pasmvars->skip_mode >>= 1;
}
if (pasmvars->skip_mode & 1)
pasmvars->skip_mask |= 2;
}
pasmvars->skip_mode >>= 1;
}
int32_t ExecutePasmInstruction2(PasmVarsT *pasmvars)
{
int32_t cflag = pasmvars->cflag;
int32_t zflag = pasmvars->zflag;
int32_t instruct, pc, cond;
int32_t opcode, value2, value1, czi;
int32_t srcaddr, dstaddr, rsltaddr;
int32_t result = 0;
int32_t i, temp, write_czr, sflag = 0, dflag = 0, psflag = 0;
int32_t rflag = 0;
int32_t returnflag = 0;
int32_t breakflag = 0;
int32_t streamflag = 0;
int32_t pc_incr;
int32_t memflag = pasmvars->memflag;
int32_t post_ret = 0;
int32_t alt_instr = 0;
#if 0
// Check serial ports
CheckSerialPorts(pasmvars);
#endif
// Check interrupt flags
CheckInterruptFlags(pasmvars);
// Check if cordic engine working
if (pasmvars->cordic_count)
{
//printf("\ncordic_count = %d, cordic_depth = %d\n", pasmvars->cordic_count, pasmvars->cordic_depth);
pasmvars->cordic_count--;
if (!pasmvars->cordic_count)
{
if (--pasmvars->cordic_depth)
pasmvars->cordic_count = 16;
pasmvars->qxreg = pasmvars->qxqueue[0];
pasmvars->qyreg = pasmvars->qyqueue[0];
pasmvars->qxposted = 1;
pasmvars->qyposted = 1;
for (i = 0; i < pasmvars->cordic_depth; i++)
{
pasmvars->qxqueue[i] = pasmvars->qxqueue[i+1];
pasmvars->qyqueue[i] = pasmvars->qyqueue[i+1];
}
}
}
// Check if streaming FIFO needs filling
streamflag = CheckStreamFifo(pasmvars);
// Check if we can skip further processing if not printing, not waiting
// for a pin state and wait flag is greater than 1.
if (pasmvars->waitflag > 1 && !pasmvars->printflag && pasmvars->waitmode != WAIT_PIN)
{
pasmvars->waitflag--;
return 0;
}
// Check for cache wait
if (pasmvars->waitflag && pasmvars->waitmode == WAIT_CACHE)
{
if (stream_fifo_level(pasmvars) >= 2)
{
pasmvars->waitflag = 0;
pasmvars->waitmode = 0;
}
else
{
if (pasmvars->printflag)
DebugPasmInstruction2(pasmvars);
return 0;
}
}
// Fetch a new instruction and update the pipeline
if (!pasmvars->waitflag && pasmvars->phase == 0) // && !pasmvars->rwrep)
{
if (CheckForInterrupt(pasmvars))
{
if (pasmvars->pc2 & 0xffc00)
pasmvars->pc2 = (pasmvars->pc1 - 4);
else
pasmvars->pc2 = (pasmvars->pc1 - 1);
if (pasmvars->printflag) DebugPasmInstruction2(pasmvars);
pasmvars->phase = 1;
return 0;
}
//if (pasmvars->pc >= 0x400 && CheckForHubExecWait(pasmvars)) return 0;
pasmvars->instruct2 = pasmvars->instruct1;
#if 0
// Modify instruction if previous instruction was ALTI
if (pasmvars->altiflag) ProcessAltiFetch(pasmvars);
#endif
// Update instruction pipeline and fetch new instruction
if (pasmvars->pc < 0x200)
{
//pasmvars->str_fifo_tail_addr = 0;
CheckSkip(pasmvars);
pasmvars->instruct1 = pasmvars->mem[pasmvars->pc];
}
else if (pasmvars->pc < 0x400)
{
//pasmvars->str_fifo_tail_addr = 0;
CheckSkip(pasmvars);
pasmvars->instruct1 = pasmvars->lut[pasmvars->pc - 0x200];
}
else
#if 0
pasmvars->instruct1 = read_stream_fifo(pasmvars, pasmvars->pc);
#else
pasmvars->instruct1 = read_stream_fifo_long(pasmvars);
#endif
// Update PC pipeline and increment PC
pasmvars->pc2 = pasmvars->pc1;
pasmvars->pc1 = pasmvars->pc;
if (pasmvars->repcnt && pasmvars->pc >= pasmvars->reptop)
{
if (!pasmvars->repforever) pasmvars->repcnt--;
pasmvars->pc = pasmvars->repbot;
check_hubexec_mode(pasmvars);
}
else
{
if (pasmvars->pc & 0xffc00)
pasmvars->pc = (pasmvars->pc + 4) & ADDR_MASK;
else
pasmvars->pc = (pasmvars->pc + 1) & ADDR_MASK;
}
if (pasmvars->printflag) { /*printf(" XXX ");*/ DebugPasmInstruction2(pasmvars); }
pasmvars->phase = 1;
return 0;
}
// Get the instruction and pc
instruct = pasmvars->instruct2;
if (pasmvars->altiflag)
{
//static int change_count = 0;
//printf("altiflag set. Changing instruction from %08x", instruct);
instruct = (instruct & 0x0003ffff) | (pasmvars->altivalue << 18);
//printf(" to %08x\n", instruct);
//if (++change_count > 100) spinsim_exit(1);
}
pc = pasmvars->pc2;
if (pc & 0xffc00)
pc_incr = 4;
else
pc_incr = 1;
// Return if instruction has been invalidated or skip bit is set and not printing
if ((pc & INVALIDATE_INSTR) || (pasmvars->skip_mask & 1))
{
if (!pasmvars->printflag)
{
pasmvars->skip_mask >>= 1;
pasmvars->phase = 0; // Change phase to fetch mode
return 0;
}
returnflag = 1;
}
// Extract bit fields from the instruction
opcode = (instruct >> 21) & 127;
czi = (instruct >> 18) & 7;
cond = (instruct >> 28) & 15;
dstaddr = (instruct >> 9) & 511;
srcaddr = instruct & 511;
rsltaddr = dstaddr;
// Check for post return
if (cond == 0 && instruct != 0)
{
cond = 15;
post_ret = 1;
}
// Replace the source, destination or result address if an alternate is set
if (pasmvars->altsflag)
srcaddr = pasmvars->altsvalue;
if (pasmvars->altdflag)
dstaddr = pasmvars->altdvalue;
if (pasmvars->altrflag)
rsltaddr = pasmvars->altrvalue;
// Decode the immediate flags for the source and destination fields
if ((czi & 1) && opcode <= 0x6a)
{
if (!pasmvars->augsflag && (instruct & 0x100) && ((opcode >= OPCODE_RDBYTE &&
opcode <= OPCODE_RDLONG) || opcode == OPCODE_WRBYTE || (opcode == OPCODE_WRLONG && !(czi&4))
|| (opcode == OPCODE_WMLONG && (czi>>1) == 3)))
sflag = 3;
else if ((opcode >= OPCODE_CALLD && opcode <= OPCODE_CALLPB) || (opcode == OPCODE_JINT && !(czi&4)))
sflag = 2;
else
sflag = 1;
}
dflag = ((czi & 1) && (opcode == 0x6b)) ||
((czi & 2) && (opcode == 0x5d || opcode == 0x5e || (opcode == 0x5f && (czi & 4)) || (opcode >= 0x60 && opcode <= 0x6a)));
// Check for extended address instructions
if (opcode >= 0x6c)
{
if (opcode < 0x78)
{
srcaddr = instruct & 0xfffff;
sflag = (czi >> 2) + 1;
if (opcode >= 0x70)
rsltaddr = 0x1f6 + (opcode & 3);
}
else
{
srcaddr = instruct & 0x7fffff;
sflag = 1;
}
}
// Determine if ptra or ptrb are referenced
psflag = (sflag == 3);
// Determine if instruction uses relative address
rflag = (sflag == 2);
// Save ptra, ptrb, inda and indb
SaveRegisters(pasmvars);
// Return if condition code is not met
if (!((cond >> ((cflag << 1) | zflag)) & 1))
{
if (!pasmvars->printflag)
{
pasmvars->skip_mask >>= 1;
pasmvars->phase = 0; // Change phase to fetch mode
return 0;
}
returnflag = 1;
}
// Set the flag that controls writing the result, zero flag and carry flag
write_czr = czi | 1; // Assume writing result
// Get value1 from the destination field
if (dflag)
{
if (pasmvars->augdflag)
value1 = (pasmvars->augdvalue << 9) | dstaddr;
else
value1 = dstaddr;
}
else if (dstaddr == REG_PINA)
value1 = pin_val_a;
else if (dstaddr == REG_PINB)
value1 = pin_val_b;
else if (dstaddr == REG_PTRA)
value1 = pasmvars->ptra;
else if (dstaddr == REG_PTRB)
value1 = pasmvars->ptrb;
else if (memflag == 2)
value1 = pasmvars->lut[dstaddr+pasmvars->rwrep];
else
value1 = pasmvars->mem[dstaddr+pasmvars->rwrep];
// Get value2 from the source field
//printf("psflag = %d, sflag = %d, srcaddr = %d\n", psflag, sflag, srcaddr);
if (pasmvars->altsvflag)
value2 = pasmvars->altsvvalue;
else if (psflag)
value2 = GetPointer(pasmvars, srcaddr, pointer_shift(instruct));
else if (sflag)
{
if (pasmvars->augsflag)
value2 = (pasmvars->augsvalue << 9) | srcaddr;
else if (rflag)
value2 = (srcaddr << 23) >> 23;
else
value2 = srcaddr;
}
else if (srcaddr == REG_PINA)
value2 = pin_val_a;
else if (srcaddr == REG_PINB)
value2 = pin_val_b;
else if (srcaddr == REG_PTRA)
value2 = pasmvars->ptra;
else if (srcaddr == REG_PTRB)
value2 = pasmvars->ptrb;
else
value2 = pasmvars->mem[srcaddr];
//if (pasmvars->waitmode == WAIT_FLAG) printf("Trace 1 - waitflag = %d\n", pasmvars->waitflag);
// Check the wait flag if the return flag is not set
if (returnflag)
{
if (pasmvars->waitmode == WAIT_FLAG) printf("Trace 1a - waitflag = %d\n", pasmvars->waitflag);
if (pasmvars->waitflag)
{
pasmvars->waitflag--;
if (!pasmvars->waitflag) pasmvars->waitmode = 0;
}
}
else
CheckWaitFlag2(pasmvars, instruct, value1, value2, streamflag);
//if (pasmvars->waitmode == WAIT_FLAG) printf("Trace 2 - waitflag = %d\n", pasmvars->waitflag);
// Print instruction if printflag set
if (pasmvars->printflag) DebugPasmInstruction2(pasmvars);
// Return if returnflag or waitflag is set
if (returnflag || pasmvars->waitflag)
{
if (returnflag)
{
pasmvars->skip_mask >>= 1;
pasmvars->phase = 0; // Change phase to fetch mode
}
return 0;
}
// Check sflag and dflag and reset augsflag and augdflag if needed
if (!memflag)
{
if (sflag) pasmvars->augsflag = 0;
if (dflag) pasmvars->augdflag = 0;
}
// Check for breakpoint
if (pc == pasmvars->breakpnt)
{
if (!pasmvars->printflag) pasmvars->printflag = 15;
DebugPasmInstruction2(pasmvars);
breakflag = 1;
}
// Update ptra, ptrb, inda and indb
UpdateRegisters(pasmvars);
// Decode the opcode and execute the instruction
// Set the variables result, zflag and cflag.
// Clear bits within write_czr to prevent writing variables.
switch(opcode >> 3) // Decode the four most significant bits
{
case 0: // rotate and shift
value2 &= 0x1f; // Get five LSB's
switch (opcode)
{
case 0: // ror
result = (((uint32_t)value1) >> value2) | (value1 << (32 - value2));
if (value2)
value1 >>= (value2 - 1);
cflag = value1 & 1;
break;
case 1: // rol
result = (((uint32_t)value1) >> (32 - value2)) | (value1 << value2);
if (value2)
value1 <<= (value2 - 1);
cflag = (value1 >> 31) & 1;
break;
case 2: // shr
result = (((uint32_t)value1) >> value2);
if (value2)
value1 >>= (value2 - 1);
cflag = value1 & 1;
break;
case 3: // shl
result = (value1 << value2);
if (value2)
value1 <<= (value2 - 1);
cflag = (value1 >> 31) & 1;
break;
case 4: // rcr
if (value2)
{
result = (cflag << 31) | (((uint32_t)value1) >> 1);
result >>= (value2 - 1);
}
else
result = value1;
if (value2)
value1 >>= (value2 - 1);
cflag = value1 & 1;
break;
case 5: // rcl
result = cflag ? (1 << value2) - 1 : 0;
result |= (value1 << value2);
if (value2)
value1 <<= (value2 - 1);
cflag = (value1 >> 31) & 1;
break;
case 6: // sar
result = value1 >> value2;
if (value2)
value1 >>= (value2 - 1);
cflag = value1 & 1;
break;
case 7: // sal
result = (value1 << value2);
if (value1 & 1) result |= (1 << value2) - 1;
if (value2)
value1 <<= (value2 - 1);
cflag = (value1 >> 31) & 1;
break;
}
zflag = (result == 0);
break;
case 1: // addxx, subxx
switch (opcode & 7)
{
int64_t d_result;
case 0: // add
result = value1 + value2;
cflag = (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
zflag = (result == 0);
break;
case 1: // addx
result = value1 + value2 + cflag;
cflag = (((value1 & value2) | ((value1 | value2) & (~result))) >> 31) & 1;
zflag = (result == 0) & zflag;
break;
case 2: // adds
#ifdef OLD_SIGNED_CFLAG
result = value1 + value2;
cflag = (((~(value1 ^ value2)) & (value1 ^ result)) >> 31) & 1;
#else
d_result = (int64_t)value1 + (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
zflag = (result == 0);
if (kludge) cflag = 0;
break;
case 3: // addsx
#ifdef OLD_SIGNED_CFLAG
result = value1 + value2 + cflag;
cflag = ((value1 ^ value2) & 0x80000000) ? ((result >> 31) & 1) : ((value1 >> 31) & 1);
#else
d_result = (int64_t)value1 + (int64_t)value2 + (int64_t)cflag;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
zflag = (result == 0) & zflag;
if (kludge) cflag = 0;
break;
case 4: // sub
result = value1 - value2;
//printf("result = %d, value1 = %d, value2 = %d\n", result, value1, value2);
cflag = ((uint32_t)value1) < ((uint32_t)value2);
zflag = (result == 0);
break;
case 5: // subx
result = value1 - value2 - cflag;
if (value2 != 0xffffffff || !cflag)
cflag = ((uint32_t)value1) < ((uint32_t)(value2 + cflag));
zflag = (result == 0) & zflag;
break;
case 6: // subs
#ifdef OLD_SIGNED_CFLAG
result = value1 - value2;
cflag = (((value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = (int64_t)value1 - (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
zflag = (result == 0);
if (kludge) cflag = 0;
break;
case 7: // subsx
#ifdef OLD_SIGNED_CFLAG
result = value1 - value2 - cflag;
cflag = (((value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = (int64_t)value1 - (int64_t)value2 - (int64_t)cflag;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
zflag = (result == 0) & zflag;
if (kludge) cflag = 0;
break;
}
break;
case 2: // cmpxx, subr, cmpsub
switch (opcode & 7)
{
case 0: // cmp
//printf("\ncmp $%x $%x\n", value1, value2);
result = value1 - value2;
zflag = (result == 0);
cflag = ((uint32_t)value1) < ((uint32_t)value2);
write_czr &= 6;
break;
case 1: // cmpx
result = value1 - value2 - cflag;
if (value2 != 0xffffffff || !cflag)
cflag = ((uint32_t)value1) < ((uint32_t)(value2 + cflag));
zflag = (result == 0) & zflag;
write_czr &= 6;
break;
case 2: // cmps
//printf("\ncmps $%x $%x\n", value1, value2);
result = value1 - value2;
zflag = (result == 0);
cflag = value1 < value2;
write_czr &= 6;
break;
case 3: // cmpsx
result = value1 - value2 - cflag;
cflag = value1 < ((int64_t)value2 + cflag);
zflag = (result == 0) & zflag;
write_czr &= 6;
break;
case 4: // cmpr
result = value2 - value1;
zflag = (result == 0);
cflag = ((uint32_t)value2) < ((uint32_t)value1);
write_czr &= 6;
break;
case 5: // cmpm
result = value1 - value2;
zflag = (result == 0);
cflag = (result >> 31) & 1;
write_czr &= 6;
break;
case 6: // subr
result = value2 - value1;
cflag = ((uint32_t)value2) < ((uint32_t)value1);
zflag = (result == 0);
break;
case 7: // cmpsub
cflag = (((uint32_t)value1) >= ((uint32_t)value2));
result = cflag ? value1 - value2 : value1;
zflag = (result == 0);
break;
}
break;
case 3: // fge, fle, fges, fles, sumxx
switch (opcode & 7)
{
int64_t d_result;
case 0: // fge
cflag = (((uint32_t)value1) < ((uint32_t)value2));
result = cflag ? value2 : value1;
break;
case 1: // fle
cflag = (((uint32_t)value1) > ((uint32_t)value2));
result = cflag ? value2 : value1;
break;
case 2: // fges
cflag = (value1 < value2);
result = cflag ? value2 : value1;
break;
case 3: // fles
cflag = (value1 > value2);
result = cflag ? value2 : value1;
break;
case 4: // sumc
#ifdef OLD_SIGNED_CFLAG
result = cflag ? value1 - value2 : value1 + value2;
cflag = (~cflag) << 31;
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = cflag ? (int64_t)value1 - (int64_t)value2 : (int64_t)value1 + (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
if (kludge) cflag = 0;
break;
case 5: // sumnc
#ifdef OLD_SIGNED_CFLAG
result = cflag ? value1 + value2 : value1 - value2;
cflag = cflag << 31;
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = cflag ? (int64_t)value1 + (int64_t)value2 : (int64_t)value1 - (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
if (kludge) cflag = 0;
break;
case 6: // sumz
#ifdef OLD_SIGNED_CFLAG
result = zflag ? value1 - value2 : value1 + value2;
cflag = (~zflag) << 31;
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = zflag ? (int64_t)value1 - (int64_t)value2 : (int64_t)value1 + (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
if (kludge) cflag = 0;
break;
case 7: // sumnz
#ifdef OLD_SIGNED_CFLAG
result = zflag ? value1 + value2 : value1 - value2;
cflag = zflag << 31;
cflag = (((cflag ^ value1 ^ value2) & (value1 ^ result)) >> 31) & 1;
#else
d_result = zflag ? (int64_t)value1 + (int64_t)value2 : (int64_t)value1 - (int64_t)value2;
result = (int32_t)d_result;
cflag = (int32_t)(d_result >> 32) & 1;
#endif
if (kludge) cflag = 0;
break;
}
zflag = (result == 0);
break;
case 4: // testb, testbn, bitl, bith, bitc, bitnc, bitz, bitnz, bitrnd, bitnot
//temp = (value2 >> 5) & 7;
value2 = (value2 & 0x1f);
//cflag = (value1 >> value2) & 1;
temp = ((czi >> 1) ^ (czi >> 2)) & 1;
switch (opcode & 7)
{
case 0: // bitl, testb
value2 &= 31;
cflag = zflag = (value1 >> value2) & 1;
if (temp) // testb
write_czr &= 6;
else // bitl
{
write_czr |= 1;
result = value1 & ~(1 << value2);
}
break;
case 1: // bith, testbn
value2 &= 31;
if (temp) // testbn
{
write_czr &= 6;
cflag = zflag = !((value1 >> value2) & 1);
}
else // bith
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = value1 | (1 << value2);
}
break;
case 2: // bitc, testb
value2 &= 31;
if (temp) // testb
{
write_czr &= 6;
cflag &= (value1 >> value2) & 1;
zflag &= (value1 >> value2) & 1;
}
else // bitc
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = (value1 & ~(1 << value2)) | (pasmvars->cflag << value2);
}
break;
case 3: // bitnc, testbn
value2 &= 31;
if (temp) // testbn
{
write_czr &= 6;
cflag &= !((value1 >> value2) & 1);
zflag &= !((value1 >> value2) & 1);
}
else // bitnc
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = (value1 & ~(1 << value2)) | ((!pasmvars->cflag) << value2);
}
break;
case 4: // bitz, testb
value2 &= 31;
if (temp) //testb
{
write_czr &= 6;
cflag |= (value1 >> value2) & 1;
zflag |= (value1 >> value2) & 1;
}
else // bitz
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = (value1 & ~(1 << value2)) | (pasmvars->zflag << value2);
}
break;
case 5: // bitnz, testbn
value2 &= 31;
if (temp) // testbn
{
write_czr &= 6;
cflag |= !((value1 >> value2) & 1);
zflag |= !((value1 >> value2) & 1);
}
else // bitnz
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = (value1 & ~(1 << value2)) | ((!pasmvars->zflag) << value2);
}
break;
case 6: // bitrnd, testb
value2 &= 31;
if (temp) // testb
{
write_czr &= 6;
cflag ^= (value1 >> value2) & 1;
zflag ^= (value1 >> value2) & 1;
}
else // bitrnd
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
NotImplemented(instruct);
}
break;
case 7: // bitnot, testbn
value2 &= 31;
if (temp) // testbn
{
write_czr &= 6;
cflag ^= !((value1 >> value2) & 1);
zflag ^= !((value1 >> value2) & 1);
}
else // bitnot
{
write_czr |= 1;
cflag = zflag = (value1 >> value2) & 1;
result = value1 ^ (1 << value2);
}
break;
}
break;
case 5: // and, andn, or, xor, muxxx
switch (opcode & 7)
{
case 0: // and
result = value1 & value2;
break;
case 1: // andn
result = value1 & (~value2);
break;
case 2: // or
result = value1 | value2;
break;
case 3: // xor
result = value1 ^ value2;
break;
case 4: // muxc
result = (value1 & (~value2)) | (value2 & (-cflag));
break;
case 5: // muxnc
result = (value1 & (~value2)) | (value2 & (~(-cflag)));
break;
case 6: // muxz
result = (value1 & (~value2)) | (value2 & (-zflag));
break;
case 7: // muxnz
result = (value1 & (~value2)) | (value2 & (~(-zflag)));
break;
}
zflag = (result == 0);
cflag = parity(result);
break;
case 6: // mov, not abs, negxx
switch (opcode & 7)
{
case 0: // mov
result = value2;
cflag = (value2 >> 31) & 1;
break;
case 1: // not
result = ~value2;
cflag = result < 0;
break;
case 2: // abs
cflag = (value2 >> 31) & 1;
result = _abs(value2);
break;
case 3: // neg
result = -value2;
cflag = result < 0;
break;
case 4: // negc
result = cflag ? -value2 : value2;
cflag = result < 0;
break;
case 5: // negnc
result = cflag ? value2 : -value2;
cflag = result < 0;
break;
case 6: // negz
result = zflag ? -value2 : value2;
cflag = result < 0;
break;
case 7: // negnz
result = zflag ? value2 : -value2;
cflag = result < 0;
break;
}
zflag = (result == 0);
break;
case 7: // incmod, decmod, zerox, signx, encod, ones, test, testn
switch (opcode & 7)
{
case 0: // incmod
cflag = (value1 == value2);
if (cflag)
result = 0;
else
result = value1 + 1;
break;
case 1: // decmod
cflag = (value1 == 0);
if (cflag)
result = value2;
else
result = value1 - 1;
break;
case 2: // zerox
result = value1 & ~(0xfffffffe << (value2 & 31));
break;
case 3: // signx
temp = 31 - (value2 & 31);
result = (value1 << temp) >> temp;
cflag = (result >> 31) & 1;
break;
case 4: // encod
cflag = (value2 != 0);
for (result = 31; result > 0; result--)
{
if (value2 & 0x80000000) break;
value2 <<= 1;
}
if (kludge) cflag = result & 1;
break;
case 5: // ones
result = 0;
for (i = 0; i < 32; i++)
{
result += (value2 & 1);
value2 >>= 1;
}
cflag = (result & 1);
break;
case 6: // test
result = value1 & value2;
cflag = parity(result);
write_czr &= 6;
break;
case 7: // testn
result = value1 & (~value2);
cflag = parity(result);
write_czr &= 6;
break;
}
zflag = (result == 0);
break;
case 8: // setnib, getnib, rolnib, setbyte, getbyte
write_czr = 1;
temp = (instruct >> 17) & 0x1c;
switch(opcode & 7)
{
case 0: // setnib
case 1: // setnib
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 2;
result = (value2 & 15) << temp;
//printf("setnib: shift = %d, value = %08x, value1 = %08x, ", temp, result, value1);
temp = ~(15 << temp);
result |= (value1 & temp);
//printf("result = %08x\n", result);
break;
case 2: // getnib
case 3: // getnib
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 2;
result = (value2 >> temp) & 15;
break;
case 4: // rolnib
case 5: // rolnib
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 2;
result = (value1 << 4) | ((value2 >> temp) & 15);
break;
case 6: // setbyte
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 2;
temp = (temp << 1) & 0x18;
result = (value2 & 0xff) << temp;
temp = ~(0xff << temp);
result |= (value1 & temp);
break;
case 7: // getbyte
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 2;
temp = (temp << 1) & 0x18;
result = (value2 >> temp) & 0xff;
break;
}
break;
case 9: // rolbyte, setword, getword, rolword, altxx, setx, decod, bmaks, muxnits, muxnibs, muxq, movbyts
write_czr = 1;
temp = (instruct >> 16) & 0x18;
switch(opcode&7)
{
case 0: // rolbyte
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 3;
result = (value1 << 8) | ((value2 >> temp) & 255);
break;
case 1: // setword, getword
if (pasmvars->altnflag)
temp = pasmvars->altnvalue << 3;
temp = (temp << 1) & 0x10;
write_czr &= 3;
if (czi & 4) // getword
{
result = (value2 >> temp) & 0xffff;
}
else // setword
{
result = (value2 & 0xffff) << temp;
temp = ~(0xffff << temp);
result |= (value1 & temp);
}
break;
case 2: // rolword, altsn, altgn
write_czr = 1;
switch(czi >> 1)
{
case 0: // rolword
case 1: // rolword
if (pasmvars->altnflag)
temp = pasmvars->altnvalue;
else
temp = (czi & 2);
if (temp)
result = (value1 << 16) | (((unsigned int)value2) >> 16);
else
result = (value1 << 16) | (value2 & 0xffff);
break;
case 2: // altsn
pasmvars->altrflag = pasmvars->altnflag = pasmvars->altdflag = 1;
pasmvars->altnvalue = (value1 & 7);
pasmvars->altrvalue = pasmvars->altdvalue = ((value1 >> 3) + value2) & 511;
result = value1 + ((value2 << (31 - 17)) >> (31 - 8));
//printf("altsn: n = %x, d = %x, r = %x\n", pasmvars->altnvalue, pasmvars->altdvalue, result);
alt_instr = 1;
break;
case 3: // altgn
pasmvars->altnflag = pasmvars->altsflag = 1;
pasmvars->altnvalue = (value1 & 7);
pasmvars->altsvalue = ((value1 >> 3) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
//printf("altgn: n = %x, s = %x, r = %x\n", pasmvars->altnvalue, pasmvars->altsvalue, result);
alt_instr = 1;
break;
}
break;
case 3: // altsb, altgb, altsw, altgw
write_czr = 1;
switch(czi >> 1)
{
case 0: // altsb
pasmvars->altrflag = pasmvars->altnflag = pasmvars->altdflag = 1;
pasmvars->altnvalue = (value1 & 3);
pasmvars->altrvalue = pasmvars->altdvalue = ((value1 >> 2) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
alt_instr = 1;
break;
case 1: // altgb
pasmvars->altnflag = pasmvars->altsflag = 1;
pasmvars->altnvalue = (value1 & 3);
pasmvars->altsvalue = ((value1 >> 2) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
alt_instr = 1;
break;
case 2: // altsw
pasmvars->altrflag = pasmvars->altnflag = pasmvars->altdflag = 1;
pasmvars->altnvalue = (value1 & 1);
pasmvars->altrvalue = pasmvars->altdvalue = ((value1 >> 1) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
alt_instr = 1;
break;
case 3: // altgw
pasmvars->altnflag = pasmvars->altsflag = 1;
pasmvars->altnvalue = (value1 & 1);
pasmvars->altsvalue = ((value1 >> 1) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
alt_instr = 1;
break;
}
break;
case 4: // altr, altd, alts, altb
write_czr = 1;
switch (czi >> 1)
{
case 0: // altr
pasmvars->altrflag = 1;
pasmvars->altrvalue = (value1 + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
#if 0
pasmvars->phase = 0;
return breakflag;
#else
alt_instr = 1;
break;
#endif
case 1: // altd
pasmvars->altdflag = pasmvars->altrflag = 1;
pasmvars->altdvalue = pasmvars->altrvalue = (value1 + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
#if 0
pasmvars->phase = 0;
return breakflag;
#else
alt_instr = 1;
break;
#endif
case 2: // alts
pasmvars->altsflag = 1;
pasmvars->altsvalue = (value1 + value2) & 511;
//printf("\nALTS: %x\n", pasmvars->altsvalue);
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
#if 0
pasmvars->phase = 0;
return breakflag;
#else
alt_instr = 1;
break;
#endif
case 3: // altb
pasmvars->altdflag = pasmvars->altrflag = 1;
pasmvars->altdvalue = pasmvars->altrvalue = ((value1 >> 5) + value2) & 511;
result = value1 + (value2 << ((31 - 17)) >> (31 - 8));
#if 0
pasmvars->phase = 0;
return breakflag;
#else
alt_instr = 1;
break;
#endif
}
break;
case 5: // alti, setr, setd, sets
write_czr = 1;
switch (czi >> 1)
{
case 0: // alti
if (value2 & (1 << 2))
{
pasmvars->altsflag = 1;
pasmvars->altsvalue = value1 & 511;
}
if (value2 & (1 << 5))
{
pasmvars->altrflag = pasmvars->altdflag = 1;
pasmvars->altrvalue = pasmvars->altdvalue = (value1 >> 9) & 511;
}
if (value2 & (1 << 8))
{
if (((value2 >> 6) & 7) == 5)
{
pasmvars->altiflag = 1;
pasmvars->altivalue = (uint32_t)value1 >> 18;
}
else
{
pasmvars->altrflag = 1;
pasmvars->altrvalue = (value1 >> 19) & 511;
}
}
else if (((value2 >> 6) & 7) == 1)
{
pasmvars->altrflag = 1;
pasmvars->altrvalue = -1;
}
result = ProcessAltiIncrement(value1, value2);
#if 0
pasmvars->phase = 0;
return breakflag;
#else
alt_instr = 1;
break;
#endif
case 1: // setr
result = (value1 & 0xf007ffff) | ((value2 & 0x1ff) << 19);
break;
case 2: // setd
result = (value1 & 0xfffc01ff) | ((value2 & 0x1ff) << 9);
break;
case 3: // sets
result = (value1 & 0xfffffe00) | (value2 & 0x1ff);
break;
}
break;
case 6: // decod, bmask, crcbit, crcnib
write_czr = 1;
switch (czi >> 1)
{
case 0: // decod
result = 1 << (value2 & 0x1f);
break;
case 1: // bmask
result = ~(0xfffffffe << (value2 & 0x1f));
break;
case 2: // crcbit
NotImplemented(instruct);
break;
case 3: // crcnib
NotImplemented(instruct);
break;
}
break;
case 7: // muxnits, muxnibs, muxq, movbyts
write_czr = 1;
switch (czi >> 1)
{
case 0: // muxnits
temp = 3;
for (i = 0; i < 16; i++)
{
if (value2 & temp)
value1 = (value1 & ~temp) | (value2 & temp);
temp <<= 2;
}
result = value1;
break;
case 1: // muxnibs
temp = 15;
for (i = 0; i < 8; i++)
{
if (value2 & temp)
value1 = (value1 & ~temp) | (value2 & temp);
temp <<= 4;
}
result = value1;
break;
case 2: // muxq
temp = pasmvars->qreg;
result = (value1 & ~temp) | (value2 & temp);
break;
case 3: // movbyts
{
unsigned char *ptr1 = (unsigned char *)&value1;
unsigned char *ptr2 = (unsigned char *)&result;
ptr2[0] = ptr1[value2 & 3];
ptr2[1] = ptr1[(value2 >> 2) & 3];
ptr2[2] = ptr1[(value2 >> 4) & 3];
ptr2[3] = ptr1[(value2 >> 6) & 3];
}
}
break;
}
zflag = (result == 0);
break;
case 10: // testx, anyb, waitcnt, addctx, wmlong, calld, rdlut
write_czr &= 6;
switch(opcode & 7)
{
case 0: // mul, muls
write_czr = 3;
if (czi&4) // muls
{
value1 = (value1 << 16) >> 16;
value2 = (value2 << 16) >> 16;
result = value1 * value2;
}
else // mul
{
value1 &= 0xffff;
value2 &= 0xffff;
result = value1 * value2;
}
zflag = (result == 0);
break;
case 1: // sca, scas
write_czr &= 2;
if (czi&4) // scas
{
value1 = (value1 << 16) >> 16;
value2 = (value2 << 16) >> 16;
result = (value1 * value2) >> 14;
}
else // sca
{
value1 &= 0xffff;
value2 &= 0xffff;
result = (uint32_t)(value1 * value2) >> 16;
}
alt_instr = 1;
pasmvars->altsvflag = 1;
pasmvars->altsvvalue = result;
zflag = (result == 0);
break;
case 2: // addpix, mulpix, blnpix, mixpix
write_czr = 1;
switch (czi >> 1)
{
int32_t dmix, smix;
case 0: // addpix
for (i = 0; i < 4; i++)
{
temp = (value1 & 255) + (value2 &255);
if (temp > 255) temp = 255;
result = ((uint32_t)result >> 8) | (temp << 24);
value1 >>= 8;
value2 >>= 8;
}
break;
case 1: // mulpix
for (i = 0; i < 4; i++)
{
temp = (value1 & 255) * (value2 & 255);
temp = (temp + 255) >> 8;
result = ((uint32_t)result >> 8) | (temp << 24);
value1 >>= 8;
value2 >>= 8;
}
break;
case 2: // blnpix
smix = (pasmvars->blnpix_var & 255);
dmix = (smix ^ 255);
for (i = 0; i < 4; i++)
{
#if 1
temp = (value1 & 255) * dmix;
temp += (value2 & 255) * smix;
temp = (temp + 255) >> 8;
#else
dmix = 256 - smix;
temp = (value1 & 255) * dmix;
temp += (value2 & 255) * smix;
temp = (temp + 255) >> 8;
if (temp > 255) temp = 255;
#endif
result = ((uint32_t)result >> 8) | (temp << 24);
value1 >>= 8;
value2 >>= 8;
}
break;
case 3: // mixpix
for (i = 0; i < 4; i++)
{
smix = GetMixVal(pasmvars->mixpix_mode, pasmvars->blnpix_var, value2, value1);
dmix = GetMixVal(pasmvars->mixpix_mode >> 3, pasmvars->blnpix_var, value2, value1);
temp = (value1 & 255) * dmix;
temp += (value2 & 255) * smix;
temp = (temp + 255) >> 8;
result = ((uint32_t)result >> 8) | (temp << 24);
value1 >>= 8;
value2 >>= 8;
}
break;
}
break;
case 3: // addct1, addct2, addct3, wmlong
write_czr = 1;
switch (czi >> 1)
{
case 0: // addct1
result = value1 + value2;
pasmvars->cntreg1 = result;
pasmvars->intflags &= ~(1 << 1);
break;
case 1: // addct2
result = value1 + value2;
pasmvars->cntreg2 = result;
pasmvars->intflags &= ~(1 << 2);
break;
case 2: // addct3
result = value1 + value2;
pasmvars->cntreg3 = result;
pasmvars->intflags &= ~(1 << 3);
break;
case 3: // wmlong
if (streamflag) printf("\nSTREAM COLLISION\n");
value2 += pasmvars->rwrep << 2;
write_czr = 0;
if (value2 >= 0xfff80 && value2 < 0xfffc0)
wrl_flags0 |= 1 << ((value2 >> 2) & 15);
result = read_unaligned_long(value2);
if ((value1 & 0xff) != 0xff)
result = (result & ~0xff) | (value1 & 0xff);
if ((value1 & 0xff) != 0xff00)
result = (result & ~0xff00) | (value1 & 0xff00);
if ((value1 & 0xff) != 0xff0000)
result = (result & ~0xff0000) | (value1 & 0xff0000);
if ((value1 & 0xff) != 0xff000000)
result = (result & ~0xff000000) | (value1 & 0xff000000);
write_unaligned_long(value2, result);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", wrl[%x] = %x", value2, value1);
if (memflag)
{
if (pasmvars->qreg & 0x1ff)
{
pasmvars->rwrep++;
pasmvars->qreg--;
}
else
{
pasmvars->rwrep = 0;
pasmvars->memflag = 0;
if (sflag) pasmvars->augsflag = 0;
if (dflag) pasmvars->augdflag = 0;
}
}
break;
}
write_czr |= 1;
break;
case 4: // rqpin, rdpin
NotImplemented(instruct);
break;
case 5: // rdlut
result = pasmvars->lut[value1 & 0x1ff];
zflag = (result == 0);
write_czr |= 1;
break;
case 6: // rdbyte
write_czr |= 1;
if (streamflag) printf("\nSTREAM COLLISION\n");
result = BYTE(value2);
zflag = (result == 0);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdb[%x]", value2);
break;
case 7: // rdword
write_czr |= 1;
if (streamflag) printf("\nSTREAM COLLISION\n");
result = read_unaligned_word(value2);
zflag = (result == 0);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdw[%x]", value2);
break;
}
break;
case 11: // rdlong, calld, ijxx, djxx, tjxx, callpa, callpb, jxxx, jnxxx, setpat
switch(opcode&7)
{
#if 1
case 0: // rdlong
write_czr |= 1;
if (streamflag) printf("\nSTREAM COLLISION\n");
rsltaddr += pasmvars->rwrep;
value2 += pasmvars->rwrep << 2;
if (value2 >= 0xfff80 && value2 < 0xfffc0)
{
#ifdef DEBUG_STUFF
printf("\n%d: RDLONG %8.8x\n", pasmvars->cogid, value2);
#endif
rdl_flags0 |= 1 << ((value2 >> 2) & 15);
}
result = read_unaligned_long(value2);
zflag = (result == 0);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdl[%x]", value2);
#if 0
if (pasmvars->printflag > 1)
fprintf(tracefile, "(%x)", result);
#endif
if (memflag)
{
if (pasmvars->qreg & 0x1ff)
{
pasmvars->rwrep++;
pasmvars->qreg--;
}
else
{
pasmvars->rwrep = 0;
pasmvars->memflag = 0;
if (sflag) pasmvars->augsflag = 0;
if (dflag) pasmvars->augdflag = 0;
}
}
break;
case 1: // calld
write_czr |= 1;
if (pasmvars->printflag > 1) fprintf(tracefile, ", CALLD");
if (write_czr == 7)
{
if (srcaddr == REG_IRET1)
pasmvars->intstate &= ~2;
else if (srcaddr == REG_IRET2)
pasmvars->intstate &= ~4;
else if (srcaddr == REG_IRET3)
pasmvars->intstate &= ~8;
}
if (rflag)
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
}
else
pasmvars->pc = value2 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
result = (pc + pc_incr) | (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
cflag = (result >> 20) & 1;
zflag = (result >> 21) & 1;
check_hubexec_mode(pasmvars);
break;
case 2: // callpa, callpb
if (czi&4)
rsltaddr = REG_PB;
else
rsltaddr = REG_PA;
write_czr = 1;
result = value1;
pasmvars->pc = value1 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
pasmvars->retstack[pasmvars->retptr] = pc;
pasmvars->retptr = (pasmvars->retptr + 1) & 7;
if (pasmvars->retptr == 0)
printf("return stack overflow%s", NEW_LINE);
check_hubexec_mode(pasmvars);
break;
case 3: // djz, djnz, djf, djnf
value1--;
cflag = (value1 == -1);
write_czr = 1;
result = value1;
zflag = (result == 0);
// Determine if we should jump
if (czi & 4) // djf, djnf
{
if (cflag != ((czi >> 1) & 1))
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
}
else // djz, djnz
{
if (zflag != ((czi >> 1) & 1))
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
}
break;
case 4: // ijz, ijnz, tjz, tjnz
if (czi&4) // tjz, tjnz
{
write_czr = 0;
result = value1;
}
else // ijz, ijnz
{
write_czr = 1;
result = value1 + 1;
}
zflag = (result == 0);
cflag = (result == 0);
// Determine if we should jump
if (zflag != ((czi >> 1) & 1))
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
break;
case 5: // tjf, tjnf, tjs, tjns
write_czr = 0;
result = value1;
zflag = (result == 0);
cflag = (result == -1);
// Determine if we should jump
if (czi & 4) // tjs, tjns
{
if (((result >> 31) & 1) != ((czi >> 1) & 1))
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
}
else // tjf, tjnf
{
if (cflag != ((czi >> 1) & 1))
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
}
break;
case 6: // tjv, jint, jnint, ...
write_czr = 0;
if ((czi&6) == 0) // tjv
NotImplemented(instruct);
else if ((czi&6) == 2) // jint, jnint, ....
{
temp = (value1 & 15);
temp = (pasmvars->intflags >> temp) & 1;
if (value1 & 16) temp ^= 1;
if (temp)
{
if (instruct & 0x40000)
pasmvars->pc = value2 & 0xfffff;
else
{
value2 = (value2 << 23) >> 23;
pasmvars->pc = (pc + pc_incr * (1 + value2)) & ADDR_MASK;
}
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
}
}
else // empty
NotImplemented(instruct);
break;
case 7: // setpat
write_czr = 0;
if (czi&4) // setpat
NotImplemented(instruct);
else // empty
NotImplemented(instruct);
break;
#else
case 0: // rdbyte
if (streamflag) printf("\nSTREAM COLLISION\n");
result = BYTE(value2);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdb[%x]", value2);
break;
case 1: // rdword
if (streamflag) printf("\nSTREAM COLLISION\n");
result = read_unaligned_word(value2);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdw[%x]", value2);
break;
case 2: // rdlong
if (streamflag) printf("\nSTREAM COLLISION\n");
rsltaddr += pasmvars->rwrep;
value2 += pasmvars->rwrep << 2;
if (value2 >= 0xfff80 && value2 < 0xfffc0)
{
#ifdef DEBUG_STUFF
printf("\n%d: RDLONG %8.8x\n", pasmvars->cogid, value2);
#endif
rdl_flags0 |= 1 << ((value2 >> 2) & 15);
}
result = read_unaligned_long(value2);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", rdl[%x]", value2);
#if 0
if (pasmvars->printflag > 1)
fprintf(tracefile, "(%x)", result);
#endif
if (memflag)
{
if (pasmvars->qreg & 0x1ff)
{
pasmvars->rwrep++;
pasmvars->qreg--;
}
else
{
pasmvars->rwrep = 0;
pasmvars->memflag = 0;
if (sflag) pasmvars->augsflag = 0;
if (dflag) pasmvars->augdflag = 0;
}
}
break;
case 3: // addpix, mulpix, blnpix, mixpix
switch (czi >> 1)
{
case 0: // addpix
NotImplemented(instruct);
break;
case 1: // mulpix
NotImplemented(instruct);
break;
case 2: // blnpix
NotImplemented(instruct);
break;
case 3: // mixpix
NotImplemented(instruct);
break;
}
break;
case 4:
NotImplemented(instruct);
break;
case 5:
NotImplemented(instruct);
break;
case 6: // setpae, setpan
write_czr &= 6;
pasmvars->pinpatmode = 1 + ((czi >> 2) & 1);
pasmvars->pinpatmask = value1;
pasmvars->pinpattern = value2;
break;
case 7: // setpbe, setpbn
write_czr &= 6;
pasmvars->pinpatmode = 3 + ((czi >> 2) & 1);
pasmvars->pinpatmask = value1;
pasmvars->pinpattern = value2;
break;
#endif
}
zflag = (result == 0);
break;
case 12: // wrpin, wxpin, wypin, wrlut, wrxxxx, rdfast, wrfast, fblock, xinit, xzero, xcont, rep, coginit
switch(opcode & 7)
{
case 0: // wrpin, wxpin
if (czi&4) // wxpin
NotImplemented(instruct);
else // wrpin
NotImplemented(instruct);
break;
case 1: // wypin, wrlut
if (czi&4) // wrlut
{
result = value2;
pasmvars->lut[value1 & 0x1ff] = value2;
temp = pasmvars->cogid ^ 1;
if (PasmVars[temp].share_lut)
PasmVars[temp].lut[value1 & 0x1ff] = value2;
}
else // wypin
NotImplemented(instruct);
break;
case 2: // wrbyte, wrword
if (czi & 4) // wrword
{
if (streamflag) printf("\nSTREAM COLLISION\n");
write_czr = 0;
write_unaligned_word(value2, value1);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", wrw[%x] = %x", value2, value1);
}
else // wrbyte
{
if (streamflag) printf("\nSTREAM COLLISION\n");
write_czr = 0;
BYTE(value2) = value1;
if (pasmvars->printflag > 1)
fprintf(tracefile, ", wrb[%x] = %x", value2, value1);
}
break;
case 3: // wrlong, rdfast
if (czi & 4) // rdfast
{
write_czr = 0;
value1 = (value1 & 0x3fff) << 6;
value2 &= 0xfffff;
start_fast_mode(pasmvars, value2, value2 + value1, 1);
}
else // wrlong
{
value2 += pasmvars->rwrep << 2;
if (streamflag) printf("\nSTREAM COLLISION\n");
write_czr = 0;
if (value2 >= 0xfff80 && value2 < 0xfffc0)
{
#ifdef DEBUG_STUFF
printf("\n%d: WRLONG %8.8x\n", pasmvars->cogid, value2);
#endif
wrl_flags0 |= 1 << ((value2 >> 2) & 15);
}
write_unaligned_long(value2, value1);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", wrl[%x] = %x", value2, value1);
if (memflag)
{
if (pasmvars->qreg & 0x1ff)
{
pasmvars->rwrep++;
pasmvars->qreg--;
}
else
{
pasmvars->rwrep = 0;
pasmvars->memflag = 0;
if (sflag) pasmvars->augsflag = 0;
if (dflag) pasmvars->augdflag = 0;
}
}
}
break;
case 4: // wrfast, fblock
if (czi & 4) // fblock
{
int mode = pasmvars->str_fifo_mode;
write_czr = 0;
value1 = (value1 & 0x3fff) << 6;
value2 &= 0xfffff;
start_fast_mode(pasmvars, value2, value2 + value1, mode);
}
else // wrfast
{
write_czr = 0;
value1 = (value1 & 0x3fff) << 6;
value2 &= 0xfffff;
start_fast_mode(pasmvars, value2, value2 + value1, 2);
}
break;
case 5: // xinit, xzero
if (czi & 4) // xzero
NotImplemented(instruct);
else // xinit
NotImplemented(instruct);
break;
case 6: // xcont, rep
if (czi & 4) // rep
{
pasmvars->repcnt = value2 - 1;
pasmvars->repbot = pasmvars->pc1;
if (value2 == 0) pasmvars->repforever = 1;
if (pasmvars->pc >= 0x400) value1 <<= 2;
pasmvars->reptop = (pasmvars->pc2 + value1) & ADDR_MASK;
write_czr = 0;
}
else // xcont
NotImplemented(instruct);
break;
case 7: // coginit
if (value1 & 0x10)
{
for (result = 0; result < 16; result++)
{
if (!PasmVars[result].state) break;
}
if (result == 16) result = -1;
}
else
result = value1 & 15;
//printf("\ncoginit: cog = %d, value1 = %8.8x, value2 = %8.8x\n", result, value1, value2);
if (result != -1)
{
StartPasmCog2(&PasmVars[result], pasmvars->qreg, (value2 & ADDR_MASK), result, value1 & 0x20);
UpdatePins2();
// Return without saving if we restarted this cog
if (result == pasmvars->cogid) return breakflag;
cflag = 1;
}
else
cflag = 0;
write_czr &= 6;
break;
}
zflag = (result == 0);
break;
case 13: // qxxx, jmp, call, calla, callb, misc
switch(opcode & 7)
{
case 0: // qmul, qdiv
write_czr &= 6;
i = start_cordic(pasmvars);
if (czi & 4) // qdiv
{
uint64_t d_value1 = (uint32_t)value1;
uint64_t d_value2 = (uint32_t)value2;
d_value1 |= (uint64_t)(uint32_t)pasmvars->qreg << 32;
if (value2)
{
uint64_t r_value1 = d_value1 / d_value2;
uint64_t r_value2 = d_value1 % d_value2;
if (r_value1 > 0xffffffffu)
{
pasmvars->qxqueue[i] = 0xffffffff - pasmvars->qreg + value2;
pasmvars->qyqueue[i] = value1 + pasmvars->qreg;
}
else
{
pasmvars->qxqueue[i] = r_value1;
pasmvars->qyqueue[i] = r_value2;
}
}
else
{
pasmvars->qxqueue[i] = 0xffffffff - pasmvars->qreg;
pasmvars->qyqueue[i] = value1;
}
}
else // qmul
{
uint64_t d_value1 = (uint32_t)value1;
uint64_t d_value2 = (uint32_t)value2;
d_value1 *= d_value2;
pasmvars->qxqueue[i] = d_value1 & 0xffffffff;
pasmvars->qyqueue[i] = (d_value1 >> 32) & 0xffffffff;
}
break;
case 1: // qfrac, qsqrt
write_czr &= 6;
i = start_cordic(pasmvars);
if (czi & 4) // qsqrt
{
uint64_t d_value1 = (uint32_t)value2;
d_value1 = (d_value1 << 32) | (uint32_t)value1;
pasmvars->qxqueue[i] = sqrt64(d_value1);
pasmvars->qyqueue[i] = 0;
}
else // qfrac
{
#if 0
if (value2)
{
double x = (double)value1 + ((double)(uint32_t)pasmvars->qreg / 4294967296.0);
double y = (double)value2;
double z = x/y;
z -= floor(z);
pasmvars->qxqueue[i] = z * 4294967296.0;
pasmvars->qyqueue[i] = 0;
}
else
{
pasmvars->qxqueue[i] = 0xffffffff - value1;
pasmvars->qyqueue[i] = pasmvars->qreg;
}
#else
uint64_t d_value1 = (uint32_t)value1;
uint64_t d_value2 = (uint32_t)value2;
d_value1 = (d_value1 << 32) | (uint32_t)pasmvars->qreg;
if (value2)
{
uint64_t r_value1 = d_value1 / d_value2;
uint64_t r_value2 = d_value1 % d_value2;
if (r_value1 > 0xffffffffu)
{
pasmvars->qxqueue[i] = 0xffffffff - value1 + value2;
pasmvars->qyqueue[i] = value1 + pasmvars->qreg;
}
else
{
pasmvars->qxqueue[i] = r_value1;
pasmvars->qyqueue[i] = r_value2;
}
}
else
{
pasmvars->qxqueue[i] = 0xffffffff - value1;
pasmvars->qyqueue[i] = pasmvars->qreg;
}
#endif
}
break;
case 2: // qrotate, qvector
write_czr &= 6;
i = start_cordic(pasmvars);
if (czi & 4) // qvector
{
#if 0
double x = (double)value1;
double y = pasmvars->qreg;
double angle = (double)value2;
#else
double x = (double)value1;
double y = (double)value2;
#endif
double rho, theta;
rho = sqrt(x*x + y*y) + 0.5;
theta = atan2(y, x);
pasmvars->qxqueue[i] = rho;
theta *= 4294967296.0 / (2.0 * 3.14159265359);
if (theta >= 0.0)
theta += 0.5;
else
theta -= 0.5;
pasmvars->qyqueue[i] = theta;
}
else // qrotate
{
double x = (double)value1;
double y = pasmvars->qreg;
double angle = (double)value2;
angle *= 2.0 * 3.14159265359 / 4294967296.0;
pasmvars->qxqueue[i] = cos(angle) * x - sin(angle)*y;
pasmvars->qyqueue[i] = sin(angle) * x + cos(angle)*y;
}
break;
case 3: // misc
srcaddr = instruct & 511; // Ensure alts doesn't modify
//printf("MISC: srcaddr = 0x%x\n", srcaddr);
if (srcaddr == 0x24) srcaddr = (instruct & 0x3ffff);
switch (srcaddr)
{
case 0: // hubset - TODO Need to implement. Ignore for now.
break;
case 1: // cogid
result = pasmvars->cogid;
break;
case 3: // cogstop
for (result = 0; result < 8; result++)
{
if (!PasmVars[result].state) break;
}
cflag = (result == 8);
result = value1 & 7;
zflag = (result == 0);
PasmVars[result].state = 0;
UpdatePins2();
// Return without saving if we stopped this cog
if (result == pasmvars->cogid) return breakflag;
break;
case 4: // locknew
for (result = 0; result < 16; result++)
{
if (!lockalloc[result]) break;
}
if (result == 16)
{
cflag = 1;
result = 15;
}
else
{
cflag = 0;
lockalloc[result] = 1;
}
zflag = (result == 0);
break;
case 5: // lockret
for (result = 0; result < 16; result++)
{
if (!lockalloc[result]) break;
}
cflag = (result == 16);
result = value1 & 15;
zflag = (result == 0);
lockalloc[result] = 0;
break;
case 6: // locktry
result = value1 & 15;
zflag = (result == 0);
if (!lockstate[result])
{
cflag = 1;
lockstate[result] = 0x100 | pasmvars->cogid;
}
else
cflag = 0;
break;
case 7: // lockrel
zflag = 0;
temp = value1 & 15;
result = lockstate[temp] & 15;
cflag = (lockstate[temp] != 0);
if (cflag && result == pasmvars->cogid)
{
cflag = 0;
lockstate[result] = 0;
}
write_czr &= 6;
if ((czi&4) == 0)
write_czr = 0;
else if (czi&1)
write_czr = 4;
else
write_czr = 5;
break;
case 14: // qlog
write_czr &= 6;
i = start_cordic(pasmvars);
{
double x = (double)(unsigned int)value1;
x = log(x)/log(2.0);
x = x * 134217728.0 + 0.5;
if (x >= 4294967296.0)
x = 4294967295.0;
result = (unsigned int)x;
}
pasmvars->qxqueue[i] = result;
pasmvars->qyqueue[i] = 0;
break;
case 15: // qexp
write_czr &= 6;
i = start_cordic(pasmvars);
if (value1 == 0xffffffff)
result = 0xffffffe8;
else
{
double x = (double)(unsigned int)value1;
x = pow(2.0, x / 134217728.0) + 0.5;
result = (unsigned int)x;
}
pasmvars->qxqueue[i] = result;
pasmvars->qyqueue[i] = 0;
break;
case 16: // rfbyte
result = read_stream_fifo_byte(pasmvars);
zflag = (result == 0);
break;
case 17: // rfword
result = read_stream_fifo_word(pasmvars);
zflag = (result == 0);
break;
case 18: // rflong
result = read_stream_fifo_long(pasmvars);
zflag = (result == 0);
break;
case 19: // rfvar
result = temp = 0;
do
{
result |= read_stream_fifo_byte(pasmvars) << temp;
temp += 7;
} while ((temp < 28) && (result & (1 << temp)));
cflag = 0;
zflag = (result == 0);
break;
case 20: // rfvars
result = temp = 0;
do
{
result |= read_stream_fifo_byte(pasmvars) << temp;
temp += 7;
} while ((temp < 28) && (result & (1 << temp)));
temp = 31 - temp;
result = (result << temp) >> temp;
cflag = (result >> 31) & 1;
zflag = (result == 0);
break;
case 21: // wfbyte
write_czr = 0;
write_stream_fifo_byte(pasmvars, value1);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", fifo = %2.2x", value1);
break;
case 22: // wfword
write_czr = 0;
write_stream_fifo_word(pasmvars, value1);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", fifo = %4.4x", value1);
break;
case 23: // wflong
write_czr = 0;
write_stream_fifo_long(pasmvars, value1);
if (pasmvars->printflag > 1)
fprintf(tracefile, ", fifo = %8.8x", value1);
break;
case 24: // getqx
pasmvars->qxposted = 0;
result = pasmvars->qxreg;
break;
case 25: // getqy
pasmvars->qyposted = 0;
result = pasmvars->qyreg;
break;
case 26: // getct
result = GetCnt();
break;
case 27: // getrnd
result = rand();
break;
case 28: // setdacs
NotImplemented(instruct);
break;
case 29: // setxfrq
NotImplemented(instruct);
break;
case 30: // getxacc
NotImplemented(instruct);
break;
case 31: // waitx
write_czr &= 6;
break;
case 32: // setse1
write_czr &= 6;
NotImplemented(instruct);
break;
case 33: // setse2
write_czr &= 6;
NotImplemented(instruct);
break;
case 34: // setse3
write_czr &= 6;
NotImplemented(instruct);
break;
case 35: // setse4
write_czr &= 6;
NotImplemented(instruct);
break;
case 0x0024: // pollint
case 0x0224: // pollct1
case 0x0424: // pollct2
case 0x0624: // pollct3
case 0x0824: // pollse1
case 0x0a24: // pollse2
case 0x0c24: // pollse3
case 0x0e24: // pollse4
case 0x1024: // pollpat
case 0x1224: // pollfbw
case 0x1424: // pollxmt
case 0x1624: // pollxfi
case 0x1824: // pollxro
case 0x1a24: // pollxlr
case 0x1c24: // pollatn
case 0x1e24: // pollqmt
temp = 1 << ((srcaddr >> 9) & 15);
cflag = ((pasmvars->intflags & temp) != 0);
pasmvars->intflags &= ~temp;
write_czr &= 6;
break;
case 0x2024: // waitint
case 0x2224: // waitct1
case 0x2424: // waitct2
case 0x2624: // waitct3
case 0x2824: // waitse1
case 0x2a24: // waitse2
case 0x2c24: // waitse3
case 0x2e24: // waitse4
case 0x3024: // waitpat
case 0x3224: // waitfbw
case 0x3424: // waitxmt
case 0x3624: // waitxfi
case 0x3824: // waitxro
case 0x3a24: // waitxrl
case 0x3c24: // waitatn
temp = 1 << ((srcaddr >> 9) & 15);
pasmvars->intflags &= ~temp;
write_czr &= 6;
break;
case 0x4024: // allowi
pasmvars->intstate &= ~1;
write_czr &= 6;
break;
case 0x4224: // stalli
pasmvars->intstate |= 1;
write_czr &= 6;
break;
case 0x4424: // trgint1
case 0x4624: // trgint2
case 0x4824: // trgint3
NotImplemented(instruct);
break;
case 0x4a24: // nixint1
case 0x4c24: // nixint2
case 0x4e24: // nixint3
NotImplemented(instruct);
break;
case 37: // setint1
pasmvars->intenable1 = value1;
write_czr &= 6;
break;
case 38: // setint2
pasmvars->intenable2 = value1;
write_czr &= 6;
break;
case 39: // setint3
pasmvars->intenable3 = value1;
write_czr &= 6;
break;
case 40: // setq
write_czr &= 6;
pasmvars->qreg = value1;
pasmvars->memflag = 1;
pasmvars->phase = 0;
pasmvars->skip_mask >>= 1;
//printf("qreg = %d\n", value1);
return breakflag;
break;
case 41: // setq2
write_czr &= 6;
pasmvars->qreg = value1;
pasmvars->memflag = 2;
pasmvars->phase = 0;
pasmvars->skip_mask >>= 1;
//printf("qreg = %d\n", value1);
return breakflag;
break;
case 42: // push
pasmvars->retstack[pasmvars->retptr] = value1;
pasmvars->retptr = (pasmvars->retptr + 1) & 7;
if (pasmvars->retptr == 0)
printf("return stack overflow%s", NEW_LINE);
break;
case 43: // pop
pasmvars->retptr = (pasmvars->retptr - 1) & 7;
pasmvars->retstack[pasmvars->retptr] = value1;
if (pasmvars->retptr == 7)
printf("return stack underflow%s", NEW_LINE);
break;
case 44: // jmp
pasmvars->pc = value1 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
write_czr &= 6;
break;
case 45: // call, ret
//if (pasmvars->printflag > 1) fprintf(tracefile, ", CALL or RET %x", result);
if (instruct & 0x40000) // ret
{
pasmvars->retptr = (pasmvars->retptr - 1) & 7;
result = pasmvars->retstack[pasmvars->retptr];
if (pasmvars->retptr == 7)
printf("return stack underflow%s", NEW_LINE);
cflag = (result >> 20) & 1;
zflag = (result >> 21) & 1;
pasmvars->pc = result & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
if (pasmvars->printflag > 1) fprintf(tracefile, ", RET %x", result);
}
else // call
{
pasmvars->pc = value1 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
pasmvars->retstack[pasmvars->retptr] = pc;
pasmvars->retptr = (pasmvars->retptr + 1) & 7;
if (pasmvars->retptr == 0)
printf("return stack overflow%s", NEW_LINE);
}
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 46: // calla, reta
if (instruct & 0x40000) // reta
{
pasmvars->ptra = (pasmvars->ptra - 4) & ADDR_MASK;
result = read_unaligned_long(pasmvars->ptra);
cflag = (result >> 20) & 1;
zflag = (result >> 21) & 1;
pasmvars->pc = result & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
}
else // calla
{
pasmvars->pc = value1 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
write_unaligned_long(pasmvars->ptra, pc);
pasmvars->ptra = (pasmvars->ptra + 4) & ADDR_MASK;
}
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 47: // callb, retb
if (instruct & 0x40000) // retb
{
pasmvars->ptrb = (pasmvars->ptrb - 4) & ADDR_MASK;
result = read_unaligned_long(pasmvars->ptrb);
cflag = (result >> 20) & 1;
zflag = (result >> 21) & 1;
pasmvars->pc = result & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
}
else // callb
{
pasmvars->pc = value1 & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
write_unaligned_long(pasmvars->ptrb, pc);
pasmvars->ptrb = (pasmvars->ptrb + 4) & ADDR_MASK;
}
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 48: // jmprel
write_czr &= 6;
if (pc & 0xfffffc00)
pasmvars->pc = (pc + 4 + value1) & ADDR_MASK;
else
pasmvars->pc = (pc + 1 + (value1 >> 2)) & 0x3ff;
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
break;
case 49: // skip
pasmvars->skip_mode = 0;
pasmvars->skip_mask = value1;
pasmvars->phase = 0; // Change phase to fetch mode
return breakflag;
break;
case 50: // skipf
if (pasmvars->pc < 0x400)
{
pasmvars->skip_mode = (uint32_t)value1 >> 1;
pasmvars->skip_mask = value1 & 1;
}
else
{
pasmvars->skip_mode = 0;
pasmvars->skip_mask = value1;
}
pasmvars->phase = 0; // Change phase to fetch mode
return breakflag;
break;
case 51: // execf
pasmvars->skip_mode = (value1 >> 8) & 0x7ffffe;
pasmvars->skip_mask = 0;
pasmvars->pc = (value1 & 0x3ff);
pasmvars->pc1 |= INVALIDATE_INSTR;
check_hubexec_mode(pasmvars);
pasmvars->phase = 0; // Change phase to fetch mode
return breakflag;
break;
case 52: // getptr
if (pasmvars->str_fifo_mode == 2)
result = pasmvars->str_fifo_tail_addr;
else
result = pasmvars->str_fifo_head_addr;
zflag = (result = 0);
break;
#if 0
case 53: // getint
result = pasmvars->intflags;
result |= (pasmvars->intstate & 2) << 15;
result |= (pasmvars->intstate & 6) << 16;
result |= (pasmvars->intstate & 12) << 17;
result |= (pasmvars->intstate & 8) << 18;
zflag = (result = 0);
break;
#else
case 53: // getbrk, cogbrk
if (czi & 6) // getbrk
NotImplemented(instruct);
else // cogbrk
NotImplemented(instruct);
break;
#endif
case 54: // brk
NotImplemented(instruct);
break;
case 55: // setluts
pasmvars->share_lut = (value1 & 1);
break;
case 56: // setcy
NotImplemented(instruct);
break;
case 57: // setci
NotImplemented(instruct);
break;
case 58: // setcq
NotImplemented(instruct);
break;
case 59: // setcfrq
NotImplemented(instruct);
break;
case 60: // setcmod
NotImplemented(instruct);
break;
case 61: // setpiv
pasmvars->blnpix_var = value1 & 255;
break;
case 62: // setpix
pasmvars->mixpix_mode = value1 & 63;
break;
case 63: // cogatn
for (i = 0; i < 16; i++)
{
if ((value1 & 1) && PasmVars[i].state)
PasmVars[i].intflags |= (1 << 14);
value1 >>= 1;
}
break;
case 64: // dirl, testp
if (((czi>>2) ^ (czi>>1)) & 1) // testp
{
NotImplemented(instruct);
}
else // dirl
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
}
}
break;
case 65: // dirh, testpn
if (((czi>>2) ^ (czi>>1)) & 1) // testpn
{
NotImplemented(instruct);
}
else // dirh
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
}
}
break;
case 66: // dirc, testp
if (((czi>>2) ^ (czi>>1)) & 1) // testp
{
NotImplemented(instruct);
}
else // dirl
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = (pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = (pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
}
break;
case 67: // dirnc, testpn
if (((czi>>2) ^ (czi>>1)) & 1) // testpn
{
NotImplemented(instruct);
}
else // dirh
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = (pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = (pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
}
break;
case 68: // dirz, testp
if (((czi>>2) ^ (czi>>1)) & 1) // testp
{
NotImplemented(instruct);
}
else // dirl
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = (pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = (pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
}
break;
case 69: // dirnz, testpn
if (((czi>>2) ^ (czi>>1)) & 1) // testpn
{
NotImplemented(instruct);
}
else // dirh
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = (pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = (pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
}
break;
case 70: // dirrnd, testp
if (((czi>>2) ^ (czi>>1)) & 1) // testp
{
NotImplemented(instruct);
}
else // dirl
{
NotImplemented(instruct);
}
break;
case 71: // dirnot, testpn
if (((czi>>2) ^ (czi>>1)) & 1) // testpn
{
NotImplemented(instruct);
}
else // dirh
{
if (value1 & 32)
{
rsltaddr = REG_DIRB;
result = pasmvars->mem[REG_DIRB] ^ (1 << (value1 & 31));
}
else
{
rsltaddr = REG_DIRA;
result = pasmvars->mem[REG_DIRA] ^ (1 << (value1 & 31));
}
}
break;
case 72: // outl
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31));
}
break;
case 73: // outh
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_OUTB] | (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_OUTA] | (1 << (value1 & 31));
}
break;
case 74: // outc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
break;
case 75: // outnc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
break;
case 76: // outz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
break;
case 77: // outnz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
break;
case 78: // outrnd
NotImplemented(instruct);
break;
case 79: // outnot
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_OUTB] ^ (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_OUTB] ^ (1 << (value1 & 31));
}
break;
case 80: // fltl
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31));
}
break;
case 81: // flth
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] | (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] | (1 << (value1 & 31));
}
break;
case 82: // fltc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
break;
case 83: // fltnc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
break;
case 84: // fltz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
break;
case 85: // fltnz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
break;
case 86: // fltrnd
NotImplemented(instruct);
break;
case 87: // fltnot
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] ^ (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] & ~(1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] ^ (1 << (value1 & 31));
}
break;
case 88: // drvl
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31));
}
break;
case 89: // drvh
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] | (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] | (1 << (value1 & 31));
}
break;
case 90: // drvc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->cflag << (value1 & 31));
}
break;
case 91: // drvnc
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->cflag ^ 1) << (value1 & 31));
}
break;
case 92: // drvz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | (pasmvars->zflag << (value1 & 31));
}
break;
case 93: // drvnz
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = (pasmvars->mem[REG_OUTB] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = (pasmvars->mem[REG_OUTA] & ~(1 << (value1 & 31))) | ((pasmvars->zflag ^ 1) << (value1 & 31));
}
break;
case 94: // drvrnd
NotImplemented(instruct);
break;
case 95: // drvnot
if (value1 & 32)
{
rsltaddr = REG_OUTB;
result = pasmvars->mem[REG_DIRB] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRB, result);
pasmvars->mem[REG_DIRB] = result;
result = pasmvars->mem[REG_OUTB] ^ (1 << (value1 & 31));
}
else
{
rsltaddr = REG_OUTA;
result = pasmvars->mem[REG_DIRA] | (1 << (value1 & 31));
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cmem[%x] = %x", REG_DIRA, result);
pasmvars->mem[REG_DIRA] = result;
result = pasmvars->mem[REG_OUTA] ^ (1 << (value1 & 31));
}
break;
case 96: // splitb
for (i = 0; i < 8; i++)
{
result = (result << 1) |
((value1 >> 7)&0x1000000) | ((value1 >> 14)&0x10000) |
((value1 >> 21)&0x100) | ((value1 >> 28)&1);
value1 <<= 4;
}
break;
case 97: // mergeb
for (i = 0; i < 8; i++)
{
result = (result << 4) |
((value1 >> 28) & 8) | ((value1 >> 21) & 4) |
((value1 >> 14) & 2) | ((value1 >> 7) & 1);
value1 <<= 1;
}
break;
case 98: // splitw
for (i = 0; i < 16; i++)
{
result = (result << 1) |
((value1 >> 15)&0x10000) | ((value1 >> 30)&1);
value1 <<= 2;
}
break;
case 99: // mergew
for (i = 0; i < 16; i++)
{
result = (result << 2) |
((value1 >> 30) & 2) | ((value1 >> 15) & 1);
value1 <<= 1;
}
break;
case 100: // seussf
result = seuss(value1, 1);
break;
case 101: // seussr
result = seuss(value1, 0);
break;
case 102: // rgbsqz
result = (((value1 >> 27) & 0x1f) << 11) | (((value1 >> 18) & 0x3f) << 5) | ((value1 >> 11) & 0x1f);
break;
case 103: // rgbexp
result = (((value1 >> 11) & 0x1f) << 27) | (((value1 >> 13) & 7) << 24) |
(((value1 >> 5) & 0x3f) << 18) | (((value1 >> 9) & 3) << 16) |
((value1 & 0x1f) << 11) | (((value1 >> 2) & 7) << 8);
break;
case 104: // xoro32
NotImplemented(instruct);
break;
case 105: // rev
for (value2 = 0; value2 < 32; value2++)
{
result = (result << 1) | (value1 & 1);
value1 >>= 1;
}
break;
case 106: // rczr
result = (cflag << 31) | (zflag << 30) | ((uint32_t)value1 >> 2);
zflag = value1 & 1;
cflag = (value1 >> 1) & 1;
break;
case 107: // rczl
result = (value1 << 2) | (cflag << 1) | zflag;
zflag = (value1 >> 30) & 1;
cflag = (value1 >> 31) & 1;
break;
case 108: // wrc
result = cflag;
break;
case 109: // wrnc
result = cflag ^ 1;
break;
case 110: // wrz
result = zflag;
break;
case 111: // wrnz, modcz
if (czi&1) // modcz
{
write_czr &= 6;
temp = ModifyFlag(cflag, zflag, value1 >> 4);
zflag = ModifyFlag(cflag, zflag, value1);
cflag = temp;
}
else // wrnz
result = zflag ^ 1;
break;
default:
NotImplemented(instruct);
break;
}
break;
case 4: // jmp
//printf("jmp %d %x\n", rflag, instruct & ADDR_MASK);
if (rflag)
{
#ifdef OLD_WAY
pasmvars->pc = (pc + pc_incr * (1 + instruct)) & ADDR_MASK;
#else
if (pc & 0xfffffc00)
pasmvars->pc = (pc + 4 + instruct) & ADDR_MASK;
else
pasmvars->pc = (pc + 1 + (instruct >> 2)) & 0x3ff;
#endif
}
else
pasmvars->pc = instruct & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 5: // call
if (rflag)
{
#ifdef OLD_WAY
pasmvars->pc = (pc + pc_incr * (1 + instruct)) & ADDR_MASK;
#else
if (pc & 0xfffffc00)
pasmvars->pc = (pc + 4 + instruct) & ADDR_MASK;
else
pasmvars->pc = (pc + 1 + (instruct >> 2)) & 0x3ff;
#endif
}
else
pasmvars->pc = instruct & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
pasmvars->retstack[pasmvars->retptr] = pc;
pasmvars->retptr = (pasmvars->retptr + 1) & 7;
if (pasmvars->retptr == 0)
printf("return stack overflow%s", NEW_LINE);
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 6: // calla
if (rflag)
{
#ifdef OLD_WAY
pasmvars->pc = (pc + pc_incr * (1 + instruct)) & ADDR_MASK;
#else
if (pc & 0xfffffc00)
pasmvars->pc = (pc + 4 + instruct) & ADDR_MASK;
else
pasmvars->pc = (pc + 1 + (instruct >> 2)) & 0x3ff;
#endif
}
else
pasmvars->pc = instruct & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
write_unaligned_long(pasmvars->ptra, pc);
pasmvars->ptra = (pasmvars->ptra + 4) & ADDR_MASK;
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
case 7: // callb
if (rflag)
{
#ifdef OLD_WAY
pasmvars->pc = (pc + pc_incr * (1 + instruct)) & ADDR_MASK;
#else
if (pc & 0xfffffc00)
pasmvars->pc = (pc + 4 + instruct) & ADDR_MASK;
else
pasmvars->pc = (pc + 1 + (instruct >> 2)) & 0x3ff;
#endif
}
else
pasmvars->pc = instruct & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
pc += pc_incr;
pc |= (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
write_unaligned_long(pasmvars->ptrb, pc);
pasmvars->ptrb = (pasmvars->ptrb + 4) & ADDR_MASK;
write_czr &= 6;
check_hubexec_mode(pasmvars);
break;
}
break;
case 14: // calld, loc
rsltaddr = (opcode & 3) + 0x1f6;
if (opcode & 4) // loc
{
if (czi & 4)
result = (pc + instruct + pc_incr);
else
result = instruct;
result &= ADDR_MASK;
}
else // calld
{
if (czi & 4)
pasmvars->pc = (pc + pc_incr + instruct) & ADDR_MASK;
else
pasmvars->pc = instruct & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
result = (pc + pc_incr) | (pasmvars->zflag << 21) | (pasmvars->cflag << 20);
cflag = (result >> 20) & 1;
zflag = (result >> 21) & 1;
write_czr |= 1;
check_hubexec_mode(pasmvars);
}
break;
case 15: // augs, augd
if (opcode & 4) // augd
{
pasmvars->augdflag = 1;
pasmvars->augdvalue = instruct & 0x007fffff;
}
else // augs
{
pasmvars->augsflag = 1;
pasmvars->augsvalue = instruct & 0x007fffff;
}
write_czr &= 6;
break;
}
// Conditionally update flags and write result
if (write_czr & 2)
{
pasmvars->zflag = zflag;
if (pasmvars->printflag > 1) fprintf(tracefile, ", z = %d", zflag);
}
if (write_czr & 4)
{
pasmvars->cflag = cflag;
if (pasmvars->printflag > 1) fprintf(tracefile, ", c = %d", cflag);
}
if ((write_czr & 1) && rsltaddr != -1)
{
pasmvars->lastd = result;
if (memflag == 2)
{
pasmvars->lut[rsltaddr] = result;
if (pasmvars->printflag > 1)
fprintf(tracefile, ", clut[%x] = %x", rsltaddr, result);
}
else if (rsltaddr == REG_PTRA)
{
pasmvars->ptra = result;
if (pasmvars->printflag > 1)
fprintf(tracefile, ", ptra = %x", result);
}
else if (rsltaddr == REG_PTRB)
{
pasmvars->ptrb = result;
if (pasmvars->printflag > 1)
fprintf(tracefile, ", ptrb = %x", result);
}
else
{
pasmvars->mem[rsltaddr] = result;
if (pasmvars->printflag > 1)
fprintf(tracefile, ", cram[%x] = %x", rsltaddr, result);
}
// Check if we need to update the pins
if (rsltaddr >= REG_DIRA && rsltaddr <= REG_OUTB) UpdatePins2();
}
#if 0
if (pasmvars->waitflag)
{
fprintf(tracefile, "XXXXXXXXXX BAD XXXXXXXXXXXXXXX\n");
pasmvars->waitflag--;
if (!pasmvars->waitflag) pasmvars->waitmode = 0;
}
#endif
// Check for post return
if (post_ret)
{
pasmvars->retptr = (pasmvars->retptr - 1) & 7;
temp = pasmvars->retstack[pasmvars->retptr];
if (pasmvars->retptr == 7)
printf("return stack underflow%s", NEW_LINE);
pasmvars->pc = temp & ADDR_MASK;
pasmvars->pc1 |= INVALIDATE_INSTR;
if (pasmvars->printflag > 1) fprintf(tracefile, ", RET %x", temp);
}
// Clear the alternate register flags
//if (pasmvars->altsflag) printf("\nClear altsflag\n");
if (!alt_instr)
{
pasmvars->altiflag = 0;
pasmvars->altsflag = 0;
pasmvars->altdflag = 0;
pasmvars->altrflag = 0;
pasmvars->altnflag = 0;
pasmvars->altsvflag = 0;
}
if (!pasmvars->rwrep)
{
pasmvars->phase = 0; // Change phase to fetch mode
pasmvars->qreg = 0;
pasmvars->memflag = 0;
pasmvars->skip_mask >>= 1;
}
return breakflag;
}
/*
+------------------------------------------------------------------------------------------------------------------------------+
| TERMS OF USE: MIT License |
+------------------------------------------------------------------------------------------------------------------------------+
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|is furnished to do so, subject to the following conditions: |
| |
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
| |
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
+------------------------------------------------------------------------------------------------------------------------------+
*/