Exemple #1
0
void n8x300_cpu_device::execute_run()
{
	do
	{
		UINT16 opcode;
		UINT8 src = 0;
		UINT8 dst;
		UINT8 rotlen;  // rotate amount or I/O field length
		UINT8 mask;
		UINT16 result;

		/* fetch the opcode */
		debugger_instruction_hook(this, m_genPC);
		opcode = FETCHOP(m_genPC);
		m_PC++;
		m_PC &= 0x1fff;
		m_AR = m_PC;
		m_IR = opcode;
		m_genPC = m_PC << 1;

		switch (OP)
		{
		case 0x00:  // MOVE
			rotlen = ROTLEN;
			if(is_rot(opcode))  // MOVE reg,reg
			{
				src = get_reg(SRC);
				dst = rotate(src,rotlen);
				set_reg(DST,dst);
			}
			else
			{
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
				{  // MOVE reg,IV
					DST_LATCH;
					mask = ((1 << rotlen)-1);
					src = (get_reg(SRC)) << (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(DST_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (src & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (src & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
				else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
				{  // MOVE IV,reg
					SRC_LATCH;
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB);
					else
						src = rotate(m_left_IV,7-SRC_LSB);
					mask = ((1 << rotlen)-1);
					dst = src & mask;
					set_reg(DST,dst);
				}
				else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
				{  // MOVE IV,IV
					SRC_LATCH;
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB);
					else
						src = rotate(m_left_IV,7-SRC_LSB);
					mask = ((1 << rotlen)-1);
					dst = src & mask;
					dst <<= (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(SRC_IS_RIGHT_BANK)  // untouched source IV bits are preserved and sent to destination IV
					{
						dst = (m_right_IV & ~mask) | (dst & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (dst & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
			}
			break;
		case 0x01:  // ADD
			rotlen = ROTLEN;
			if(is_rot(opcode))
			{  // ADD reg,reg
				src = rotate(get_reg(SRC),rotlen);
				result = src + m_AUX;
				set_reg(DST,result & 0xff);
				SET_OVF;
			}
			else
			{
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
				{  // ADD reg,IV
					DST_LATCH;
					result = get_reg(SRC) + m_AUX;
					mask = ((1 << rotlen)-1);
					dst = (result & 0xff) << DST_LSB;
					mask <<= DST_LSB;
					SET_OVF;
					if(DST_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (dst & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (dst & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
				else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
				{  // ADD IV,reg
					SRC_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					result = src + m_AUX;
					SET_OVF;
					set_reg(DST,result & 0xff);
				}
				else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
				{  // ADD IV,IV
					SRC_LATCH;
					DST_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					result = src + m_AUX;
					SET_OVF;
					dst = (result << (7-DST_LSB)) & 0xff;
					mask <<= (7-DST_LSB);
					if(SRC_IS_RIGHT_BANK)  // unused destination IV data is not preserved, is merged with input IV data
					{
						dst = (m_right_IV & ~mask) | (dst & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (dst & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
			}
			break;
		case 0x02:  // AND
			rotlen = ROTLEN;
			if(is_rot(opcode))
			{  // AND reg,reg
				src = rotate(get_reg(SRC),rotlen);
				dst = src & m_AUX;
				set_reg(DST,dst);
			}
			else
			{
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
				{  // AND reg,IV
					DST_LATCH;
					src = get_reg(SRC) & m_AUX;
					mask = ((1 << rotlen)-1);
					src <<= (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(DST_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (src & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (src & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
				else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
				{  // AND IV,reg
					SRC_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					src &= mask;
					dst = src & m_AUX;
					set_reg(DST,dst);
				}
				else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
				{  // AND IV,IV
					SRC_LATCH;
					DST_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					src &= mask;
					dst = src & m_AUX;
					dst <<= (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(SRC_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (src & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (src & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
			}
			break;
		case 0x03:  // XOR
			rotlen = ROTLEN;
			if(is_rot(opcode))
			{  // AND reg,reg
				src = rotate(get_reg(SRC),rotlen);
				dst = src ^ m_AUX;
				set_reg(DST,dst);
			}
			else
			{
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
				{  // AND reg,IV
					DST_LATCH;
					src = get_reg(SRC) ^ m_AUX;
					mask = ((1 << rotlen)-1);
					src <<= (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(DST_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (src & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (src & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
				else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
				{  // AND IV,reg
					SRC_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					src &= mask;
					dst = src ^ m_AUX;
					set_reg(DST,dst);
				}
				else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
				{  // AND IV,IV
					SRC_LATCH;
					DST_LATCH;
					mask = ((1 << rotlen)-1);
					if(SRC_IS_RIGHT_BANK)
						src = rotate(m_right_IV,7-SRC_LSB) & mask;
					else
						src = rotate(m_left_IV,7-SRC_LSB) & mask;
					src &= mask;
					dst = src ^ m_AUX;
					dst <<= (7-DST_LSB);
					mask <<= (7-DST_LSB);
					if(SRC_IS_RIGHT_BANK)
					{
						dst = (m_right_IV & ~mask) | (src & mask);
						m_right_IV = dst;
						WRITEPORT(m_IVR+0x100,m_right_IV);
					}
					else
					{
						dst = (m_left_IV & ~mask) | (src & mask);
						m_left_IV = dst;
						WRITEPORT(m_IVL,m_left_IV);
					}
				}
			}
			break;
		case 0x04:  // XEC  (Execute)
			if(is_src_reg(opcode))
			{
				src = get_reg(SRC);
				src += IMM8;
				SET_AR((m_AR & 0x1f00) | src);
			}
			else
			{
				SRC_LATCH;
				rotlen = ROTLEN;
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				mask = ((1 << rotlen)-1);
				if(SRC_IS_RIGHT_BANK)
					src = rotate(m_right_IV,7-SRC_LSB);
				else
					src = rotate(m_left_IV,7-SRC_LSB);
				src &= mask;
				src += IMM5;
				SET_AR((m_AR & 0x1fe0) | (src & 0x1f));
			}
			break;
		case 0x05:  // NZT  (Non-zero transfer)
			if(is_src_reg(opcode))
			{
				src = get_reg(SRC);
				if(src != 0)
					SET_PC((m_PC & 0x1f00) | IMM8);
			}
			else
			{
				SRC_LATCH;
				rotlen = ROTLEN;
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				mask = ((1 << rotlen)-1);
				if(SRC_IS_RIGHT_BANK)
					src = rotate(m_right_IV,7-SRC_LSB);
				else
					src = rotate(m_left_IV,7-SRC_LSB);
				rotate(src,SRC_LSB);
				src &= mask;
				if(src != 0)
					SET_PC((m_PC & 0x1fe0) | IMM5);
			}
			break;
		case 0x06:  // XMIT (Transmit)
			// the source is actually the destination for this instruction
			if(is_src_reg(opcode))
				set_reg(SRC,IMM8);
			else
			{
				SRC_LATCH;
				rotlen = ROTLEN;
				if(rotlen == 0)
					rotlen = 8;  // 0 = 8-bit I/O field length
				mask = ((1 << rotlen)-1);
				dst = IMM5;
				mask <<= (7-SRC_LSB);
				dst <<= (7-SRC_LSB);
				if(SRC_IS_RIGHT_BANK)
				{
					m_right_IV = (m_right_IV & ~mask) | (dst & mask);
					WRITEPORT(m_IVR+0x100,m_right_IV);
				}
				else
				{
					m_left_IV = (m_left_IV & ~mask) | (dst & mask);
					WRITEPORT(m_IVL,m_left_IV);
				}
			}
			break;
		case 0x07:  // JMP
			SET_PC(ADDR);
			break;
		}
		CYCLES(1);  // all instructions take 1 cycle (250ns)
	} while (m_icount > 0);
}
/*
 * Read one taint op from infd
 * Returns the number of bytes read
 */
int read_taint_op_extended(int infd, struct taint_op* op, int mergenumbers)
{
    int rc;
    taint_op_t taint_op;
    int bytes_read = 0;

    assert(op);
    rc = read(infd, op, sizeof(struct taint_op));
    if (rc != sizeof(struct taint_op)) {
        fprintf(stderr, "read_taint_op: cannot read taint op, got %d, expected %d, errno %d\n",
                rc, sizeof(struct taint_op), errno);
        exit(-1);
    }
    bytes_read += rc;
    taint_op = op->taint_op;

    if (taint_op == TAINTOP_SYSCALL) {
        fprintf(stdout, "SYSCALL %lu, num %lu\n",
                                    op->src, op->dst);
        taint_op_count++;
        return bytes_read;
    }

    if (start) {
        fprintf(stdout, "%lu taint op: %lx %d %d %s\n", taint_op_count, op->ip,
                op->threadid, op->taint_op, taint_op_str(op->taint_op));
        fflush(stdout);
    }

    if (taint_op == TAINT_REP_LBREG2MEM ||
            taint_op == TAINT_REP_UBREG2MEM ||
            taint_op == TAINT_REP_HWREG2MEM ||
            taint_op == TAINT_REP_WREG2MEM ||
            taint_op == TAINT_REP_DWREG2MEM ||
            taint_op == TAINT_REP_QWREG2MEM ||
            taint_op == TAINT_MEM2MEM)
    {
        taint_op_count++;
        return bytes_read;
    }

    if (is_src_reg(taint_op)) {
        int i = 0;
        int size;
        taint_t t;

        size = get_src_size(taint_op);
        assert(size != 0);
        // read size number of taints
        for (i = 0; i < size; i++) {
            rc = read(infd, &t, sizeof(taint_t));
            if (rc != sizeof(taint_t)) {
                fprintf(stderr, "read_taint_op: cannot read src reg taint\n");
                assert(0);
            }
            if (t != 0 && !start) {
                start = 1;
                fprintf(stdout, "%lu taint op: %lx %d %d %s\n", taint_op_count, op->ip,
                        op->threadid, op->taint_op, taint_op_str(op->taint_op));
            }
            if (start) {
                if (t) {
                    struct taint_creation_info tci;
                    fprintf(stdout, " src(%lu) %d: ", op->src, i);
                    if (!mergenumbers) {
                        print_leaf_options(&tci, t, 0,
                                        leaf_node_table,
                                        merge_node_table,
                                        option_info_table,
                                        filename_table);
                    } else {
                        print_merge_numbers(t, merge_node_table,
                                            option_info_table,
                                            filename_table);
                    }
                }
            }
            bytes_read += rc;
        }
    } else if (is_src_mem(taint_op)) {
        int i;
        int size;
        taint_t t;
        size = get_src_size(taint_op);
        assert(size != 0);

        for (i = 0; i < size; i++) {
            rc = read(infd, &t, sizeof(taint_t));
            if (rc != sizeof(taint_t)) {
                fprintf(stderr, "read_taint_op: cannot read src mem taint\n");
            }
            if (t != 0 && !start) {
                start = 1;
                fprintf(stdout, "%lu taint op: %lx %d %d %s\n", taint_op_count, op->ip,
                        op->threadid, op->taint_op, taint_op_str(op->taint_op));
            }
            if (start) {
                if (t) {
                    struct taint_creation_info tci;
                    fprintf(stdout, " src(%#lx) %d: ", op->src + i, i);
                    if (!mergenumbers) {
                        print_leaf_options(&tci, t, 0,
                                        leaf_node_table,
                                        merge_node_table,
                                        option_info_table,
                                        filename_table);
                    } else {
                        print_merge_numbers(t, merge_node_table,
                                            option_info_table,
                                            filename_table);
                    }
                }
            }
            bytes_read += rc;
        }
    } else {
        fprintf(stderr, "what is it %d %s\n", taint_op, taint_op_str(taint_op));
        assert(0);
    }

    if (is_dst_reg(taint_op)) {
        int i = 0;
        int size;
        taint_t t;

        size = get_dst_size(taint_op);
        if (size == 0) {
            fprintf(stderr, "taint_op size is 0?! %d %s\n",
                    taint_op, taint_op_str(taint_op));
        }
        assert(size != 0);
        // read size number of taints
        for (i = 0; i < size; i++) {
            rc = read(infd, &t, sizeof(taint_t));
            if (rc != sizeof(taint_t)) {
                fprintf(stderr, "read_taint_op: cannot read dst reg taint\n");
                assert(0);
            }
            if (start) {
                if (t) {
                    struct taint_creation_info tci;
                    fprintf(stdout, " dst(%lu) %d: ", op->dst, i);
                    if (!mergenumbers) {
                        print_leaf_options(&tci, t, 0,
                                        leaf_node_table,
                                        merge_node_table,
                                        option_info_table,
                                        filename_table);
                    } else {
                        print_merge_numbers(t, merge_node_table,
                                            option_info_table,
                                            filename_table);
                    }
                }
            }

            bytes_read += rc;
        }
    } else if (is_dst_mem(taint_op)) {
        int i;
        int size;
        taint_t t;

        size = get_dst_size(taint_op);
        if (size == 0) {
            fprintf(stderr, "taint_op %d %s\n", taint_op, taint_op_str(taint_op));
            if (taint_op == TAINT_ADD_HWREG2MEM) goto done;
        }
        assert(size != 0);
        for (i = 0; i < size; i++) {
            rc = read(infd, &t, sizeof(taint_t));
            if (rc != sizeof(taint_t)) {
                fprintf(stderr, "read_taint_op: cannot read dst mem taint\n");
            }
            if (start) {
                if (t || taint_op == TAINT_QWREG2MEM) {
                    struct taint_creation_info tci;
                    fprintf(stdout, " dst(%#lx) %d: ", op->dst + i, i);
                    if (!t) fprintf(stdout, "0\n");
                    else {
                        if (!mergenumbers) {
                            print_leaf_options(&tci, t, 0,
                                        leaf_node_table,
                                        merge_node_table,
                                        option_info_table,
                                        filename_table);
                        } else {
                            print_merge_numbers(t, merge_node_table,
                                                option_info_table,
                                                filename_table);
                        }
                    }
                } else {
                    fprintf(stdout, " dst(%#lx) cleared\n", op->dst + i);
                }
            }

            bytes_read += rc;
        }
    } else {
        assert(0);
    }

done:
    taint_op_count++;
    return bytes_read;
}