OpenCores
URL https://opencores.org/ocsvn/rf68000/rf68000/trunk

Subversion Repositories rf68000

[/] [rf68000/] [trunk/] [rtl/] [cpu/] [rf68000.sv] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
// ============================================================================
//        __
//   \\__/ o\    (C) 2008-2022  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
//      rf68000.sv
//
//
// BSD 3-Clause License
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//                                                                          
// ============================================================================
//
// Uncomment the following to optimize for performance. Increases the core size.
//`define OPT_PERF    1'b1
`define BIG_ENDIAN      1'b1

//`define SUPPORT_RETRY 1'b1
`define SUPPORT_MUL     1'b1
`define SUPPORT_DIV     1'b1
`define SUPPORT_BCD     1'b1
//`define SUPPORT_010   1'b1
`define SUPPORT_BITPAIRS 1'b1

//`define HAS_MMU 1'b1

//`define SUPPORT_TASK  1'b1

//`define SUPPORT_B24   1'b1            // To support 23-bit branch displacements

`define TRUE        1'b1
`define FALSE       1'b0
`define HIGH        1'b1
`define LOW         1'b0

`define RESET_VECTOR    32'h00000400
`define CSR_CORENO    32'hFFFFFFE0
`define CSR_TICK        32'hFFFFFFE4
`define CSR_ICNT                                32'hFFFFFFE8
`define CSR_TASK        32'hFFFFFFFC

//`define SSP_VEC       9'd000
`define RESET_VEC       9'd001
`define BUSERR_VEC      9'd002
`define ADDRERR_VEC     9'd003
`define ILLEGAL_VEC     9'd004
`define DBZ_VEC         9'd005
`define CHK_VEC         9'd006
`define TRAPV_VEC       9'd007
`define PRIV_VEC        9'd008
`define TRACE_VEC       9'd009
`define LINE10_VEC      9'd010
`define LINE15_VEC      9'd011
`define UNINITINT_VEC   9'd015
// Vectors 24-31 for IRQ's
`define SPURIOUS_VEC            9'd024
`define IRQ_VEC         9'd024
// Vectors 32-46 for TRAPQ instruction
`define TRAP_VEC        9'd032
`define DISP_VEC                                9'd063
`define USER64          9'd064
//`define NMI_TRAP        9'h1FE
`define RESET_TASK      9'h000

`define LDB             16'b0001_xxx0xx_xxxxxx
`define LDH             16'b0010_xxx0xx_xxxxxx
`define LDW             16'b0011_xxx0xx_xxxxxx
`define STB             16'b0001_xxx1xx_xxxxxx
`define STH             16'b0010_xxx1xx_xxxxxx
`define STW             16'b0011_xxx1xx_xxxxxx

// DBcc also for Scc
`define DBRA    8'h50
`define DBSR    8'h51
`define DBHI    8'h52
`define DBLS    8'h53
`define DBHS    8'h54
`define DBLO    8'h55
`define DBNE    8'h56
`define DBEQ    8'h57
`define DBVC    8'h58
`define DBVS    8'h59
`define DBPL    8'h5A
`define DBMI    8'h5B
`define DBGE    8'h5C
`define DBLT    8'h5D
`define DBGT    8'h5E
`define DBLE    8'h5F

`define BRA             8'h60
`define BSR             8'h61
`define BHI             8'h62
`define BLS             8'h63
`define BHS             8'h64
`define BLO             8'h65
`define BNE             8'h66
`define BEQ             8'h67
`define BVC             8'h68
`define BVS             8'h69
`define BPL             8'h6A
`define BMI             8'h6B
`define BGE             8'h6C
`define BLT             8'h6D
`define BGT             8'h6E
`define BLE             8'h6F

// 12000 LUTs / 80MHz
// slices
// 1600 FF's
// 2 MULTS
// 8 BRAMs

module rf68000(coreno_i, clken_i, rst_i, rst_o, clk_i, nmi_i, ipl_i, vpa_i,
        lock_o, cyc_o, stb_o, ack_i, err_i, rty_i, we_o, sel_o, fc_o, 
        asid_o, mmus_o, ios_o, iops_o, adr_o, dat_i, dat_o);
typedef enum logic [7:0] {
        IFETCH = 8'd1,
        DECODE,
        RETSTATE,
        FETCH_BYTE,
        FETCH_WORD,
        FETCH_LWORD,
        FETCH_LWORDa,
        STORE_BYTE,
        USTORE_BYTE,
        // 10
        STORE_WORD,
        STORE_LWORD,
        STORE_LWORDa,

        LFETCH_BYTE,
        FETCH_BRDISP,
        FETCH_BRDISPa,
        FETCH_IMM16,
        FETCH_IMM16a,
        FETCH_IMM32,
        FETCH_IMM32a,

        // 20
        FETCH_IMM32b,
        JSR,
        JMP,
        DBRA,
        
        ADDQ,
        ADDQ2,
        ADDI,
        ADDI2,
        ADDI3,
        ADDI4,
        
        // 30
        ADD,
        ADD1,
        
        DIV1,
        DIV2,

        STORE_IN_DEST,
        SHIFT,
        SHIFT1,
        BIT,
        BIT1,
        BIT2,
        
        // 40
        RTD1,
        RTD2,
        
        RTE1,
        RTE2,
        RTE3,
        RTE4,
        RTE5,
        RTE6,
        RTE7,
        RTE8,
        
        // 50
        RTE9,
        RTE10,
        RTE11,

        RTS1,
        RTS2,
        
        LINK,
        LINK1,
        LINK2,
        UNLNK,
        UNLNK2,
        
        // 60
        JMP_VECTOR,
        JMP_VECTOR2,
        JMP_VECTOR3,
        
        NEG,
        NEGX,
        NEGX1,
        NOT,
        TAS,
        LEA,
        LEA2,
        
        //70
        EXG1,

        CMP,
        CMP1,
        CMPA,
        CMPM,
        CMPM1,  // defunct

        AND,
        AND1,
        EOR,
        ANDI_CCR,
        
        // 80
        ANDI_CCR2,
        ANDI_SR,
        ANDI_SRX,
        EORI_CCR,
        EORI_CCR2,
        EORI_SR,
        EORI_SRX,
        ORI_CCR,
        ORI_CCR2,
        ORI_SR,

        //90
        ORI_SRX,
        FETCH_NOP_BYTE,
        FETCH_NOP_WORD,
        FETCH_NOP_LWORD,
        FETCH_IMM8,
        FETCH_IMM8a,
        FETCH_D32,
        FETCH_D32a,
        FETCH_D32b,
        FETCH_D16,
        
        //100
        FETCH_D16a,
        FETCH_NDX,
        FETCH_NDXa,
        
        MOVE2CCR,
        MOVE2SR,
        MOVE2SRX,

        TRAP,
        TRAP3,
        TRAP3a,
        TRAP3b,
        
        //110
        TRAP4,
        TRAP5,
        TRAP6,
        TRAP7,
        TRAP7a,
        TRAP8,
        TRAP9,
        TRAP10,
        TRAP20,
        TRAP21,
        
        // 120
        TRAP22,
        TRAP23,
        TRAP24,
        TRAP25,
        TRAP26,
        INTA,
        
        RETRY,
        RETRY2,

        TST,
        MUL,
        
        // 130
        MUL1,
        STOP,
        STOP1,
        RESET,
        RESET2,
        RESET3,
        RESET4,
        RESET5,
        PEA1,
        PEA2,
        
        // 140
        PEA3,
        BCD,
        BCD0,
        BCD1,
        BCD2,
        BCD3,
        BCD4,
        OR,
        
        INT,
        INT2,
        INT3,

        // 150
        INT4,

        MOVEM_Xn2D,
        MOVEM_Xn2D2,
        MOVEM_Xn2D3,
        MOVEM_Xn2D4,
        MOVEM_s2Xn,
        MOVEM_s2Xn2,
        MOVEM_s2Xn3,
        
        TASK1,
        THREAD2,

        // 160
        TASK3,
        TASK4,
        
        LDT1,
        LDT2,
        LDT3,
        SDT1,
        SDT2,
        
        SUB,
        SUB1,
        MOVEP,
        MOVEP1,
        MOVEP2,
        MOVEP3,
        CHK,
        
        MOVERc2Rn,
        MOVERn2Rc,
        MOVERn2Rc2,

        MOVES,
        MOVES2,
        MOVES3,
        
        ADDX,
        ADDX2,
        ADDX3,
        SUBX,
        SUBX2,
        SUBX3,

        MULU1,
        MULU2,
        MULU3,
        
        MULS1,
        MULS2,
        MULS3,
        
        BIN2BCD1,
        BIN2BCD2,
        BCD2BIN1,
        BCD2BIN2,
        BCD2BIN3,

        IFETCH2,

        FSDATA2
} state_t;

typedef enum logic [4:0] {
        FU_NONE = 5'd0,
        FU_MUL,
        FU_TST, FU_ADDX, FU_SUBX,
        FU_CMP, FU_ADD, FU_SUB, FU_LOGIC, FU_ADDQ, FU_SUBQ,
        FU_ADDI, FU_ANDI_CCR, FU_ANDI_SR, FU_EORI_CCR,
        FU_ANDI_SRX, FU_EORI_SRX, FU_ORI_SRX, FU_MOVE2SRX,
        FU_EORI_SR, FU_ORI_CCR, FU_ORI_SR, FU_MOVE2CCR,
        FU_MOVE2SR
} flag_update_t;

parameter S = 1'b0;
parameter D = 1'b1;

input [31:0] coreno_i;
input clken_i;
input rst_i;
output reg rst_o;
input clk_i;
input nmi_i;
input vpa_i;
input [2:0] ipl_i;
output lock_o;
reg lock_o;
output cyc_o;
reg cyc_o;
output stb_o;
reg stb_o;
input ack_i;
input err_i;
input rty_i;
output we_o;
reg we_o;
output [3:0] sel_o;
reg [3:0] sel_o;
output [2:0] fc_o;
reg [2:0] fc_o;
output [7:0] asid_o;
output mmus_o;
output ios_o;
output iops_o;
output [31:0] adr_o;
reg [31:0] adr_o;
input [31:0] dat_i;
output [31:0] dat_o;
reg [31:0] dat_o;

reg em;                                                 // emulation mode
reg [15:0] ir;
reg [15:0] ir2;                 // second word for ir
reg ext_ir;
reg [31:0] icnt;
state_t state;
state_t rstate;
state_t state_stk1;
state_t state_stk2;
state_t state_stk3;
state_t state_stk4;
state_t sz_state;
flag_update_t flag_update;
reg [31:0] d0 = 'd0;
reg [31:0] d1 = 'd0;
reg [31:0] d2 = 'd0;
reg [31:0] d3 = 'd0;
reg [31:0] d4 = 'd0;
reg [31:0] d5 = 'd0;
reg [31:0] d6 = 'd0;
reg [31:0] d7 = 'd0;
reg [31:0] a0 = 'd0;
reg [31:0] a1 = 'd0;
reg [31:0] a2 = 'd0;
reg [31:0] a3 = 'd0;
reg [31:0] a4 = 'd0;
reg [31:0] a5 = 'd0;
reg [31:0] a6 = 'd0;
reg [31:0] sp = 'd0;
reg [127:0] fp0 = 'd0;
reg [127:0] fp1 = 'd0;
reg [127:0] fp2 = 'd0;
reg [127:0] fp3 = 'd0;
reg [127:0] fp4 = 'd0;
reg [127:0] fp5 = 'd0;
reg [127:0] fp6 = 'd0;
reg [127:0] fp7 = 'd0;
reg [31:0] d0i;
reg [31:0] d1i;
reg [31:0] d2i;
reg [31:0] d3i;
reg [31:0] d4i;
reg [31:0] d5i;
reg [31:0] d6i;
reg [31:0] d7i;
reg [31:0] a0i;
reg [31:0] a1i;
reg [31:0] a2i;
reg [31:0] a3i;
reg [31:0] a4i;
reg [31:0] a5i;
reg [31:0] a6i;
reg [31:0] spi;
reg [31:0] flagsi;
reg [31:0] pci;
wire [31:0] d0o;
wire [31:0] d1o;
wire [31:0] d2o;
wire [31:0] d3o;
wire [31:0] d4o;
wire [31:0] d5o;
wire [31:0] d6o;
wire [31:0] d7o;
wire [31:0] a0o;
wire [31:0] a1o;
wire [31:0] a2o;
wire [31:0] a3o;
wire [31:0] a4o;
wire [31:0] a5o;
wire [31:0] a6o;
wire [31:0] spo;
wire [31:0] flagso;
wire [31:0] pco;
reg cf,vf,nf,zf,xf,sf,tf;
reg [2:0] im;
reg [2:0] ccr57;
reg [1:0] sr1112;
reg sr14;
wire [15:0] sr = {tf,sr14,sf,sr1112,im,ccr57,xf,nf,zf,vf,cf};
wire [31:0] srx = {sr};
reg [31:0] isr;
reg [3:0] ifmt;
reg [31:0] pc;
reg [31:0] opc;                 // pc for branch references
reg [31:0] ssp,usp;
reg [31:0] disp;
reg [31:0] s,d,dd,imm,immx;
reg [31:0] bit2test;
reg wl;
reg ds;
reg [5:0] cnt;                          // shift count
reg [31:0] ea;                          // effective address
reg [31:0] vector;
reg [7:0] vecno;
reg [3:0] Rt;
wire [1:0] sz = ir[7:6];
reg dsix;
reg [2:0] mmm,mmmx,mmm_save='d0;
reg [2:0] rrr,rrrx;
reg [3:0] rrrr;
wire [2:0] MMM = ir[8:6];
wire [2:0] RRR = ir[11:9];
wire [2:0] QQQ = ir[11:9];
wire [2:0] DDD = ir[11:9];
wire [2:0] AAA = ir[11:9];
reg MMMRRR;
wire Anabit;
wire [31:0] sp_dec = sp - 32'd2;
reg [31:0] rfoAn;
always_comb
case(rrr)
3'd0: rfoAn <= a0;
3'd1: rfoAn <= a1;
3'd2: rfoAn <= a2;
3'd3: rfoAn <= a3;
3'd4: rfoAn <= a4;
3'd5: rfoAn <= a5;
3'd6: rfoAn <= a6;
3'd7: rfoAn <= sp;
endcase
reg [31:0] rfoAna;
always_comb
case(AAA)
3'd0: rfoAna <= a0;
3'd1: rfoAna <= a1;
3'd2: rfoAna <= a2;
3'd3: rfoAna <= a3;
3'd4: rfoAna <= a4;
3'd5: rfoAna <= a5;
3'd6: rfoAna <= a6;
3'd7: rfoAna <= sp;
endcase
//wire [31:0] rfoAn =   rrr==3'b111 ? sp : regfile[{1'b1,rrr}];
reg [31:0] rfoDn;
always_comb
case(DDD)
3'd0:   rfoDn <= d0;
3'd1:   rfoDn <= d1;
3'd2:   rfoDn <= d2;
3'd3:   rfoDn <= d3;
3'd4:   rfoDn <= d4;
3'd5:   rfoDn <= d5;
3'd6:   rfoDn <= d6;
3'd7:   rfoDn <= d7;
endcase
reg [31:0] rfoDnn;
always_comb
case(rrr)
3'd0:   rfoDnn <= d0;
3'd1:   rfoDnn <= d1;
3'd2:   rfoDnn <= d2;
3'd3:   rfoDnn <= d3;
3'd4:   rfoDnn <= d4;
3'd5:   rfoDnn <= d5;
3'd6:   rfoDnn <= d6;
3'd7:   rfoDnn <= d7;
endcase
reg [31:0] rfob;
always_comb
case({mmm[0],rrr})
4'd0:   rfob <= d0;
4'd1:   rfob <= d1;
4'd2:   rfob <= d2;
4'd3:   rfob <= d3;
4'd4:   rfob <= d4;
4'd5:   rfob <= d5;
4'd6:   rfob <= d6;
4'd7:   rfob <= d7;
4'd8:   rfob <= a0;
4'd9:   rfob <= a1;
4'd10:  rfob <= a2;
4'd11:  rfob <= a3;
4'd12:  rfob <= a4;
4'd13:  rfob <= a5;
4'd14:  rfob <= a6;
4'd15:  rfob <= sp;
endcase
reg [31:0] rfoRnn;
always_comb
case(rrrr)
4'd0:   rfoRnn <= d0;
4'd1:   rfoRnn <= d1;
4'd2:   rfoRnn <= d2;
4'd3:   rfoRnn <= d3;
4'd4:   rfoRnn <= d4;
4'd5:   rfoRnn <= d5;
4'd6:   rfoRnn <= d6;
4'd7:   rfoRnn <= d7;
4'd8:   rfoRnn <= a0;
4'd9:   rfoRnn <= a1;
4'd10:  rfoRnn <= a2;
4'd11:  rfoRnn <= a3;
4'd12:  rfoRnn <= a4;
4'd13:  rfoRnn <= a5;
4'd14:  rfoRnn <= a6;
4'd15:  rfoRnn <= sp;
endcase
//wire [31:0] rfoDn = regfile[{1'b0,DDD}];
//wire [31:0] rfoAna = AAA==3'b111 ? sp : regfile[{1'b1,AAA}];
//wire [31:0] rfob = {mmm[0],rrr}==4'b1111 ? sp : regfile[{mmm[0],rrr}];
//wire [31:0] rfoDnn = regfile[{1'b0,rrr}];
//wire [31:0] rfoRnn = rrrr==4'b1111 ? sp : regfile[rrrr];
wire clk_g;
reg rfwrL,rfwrB,rfwrW;
reg rfwrFp;
reg takb;
reg [8:0] resB;
reg [16:0] resW;
reg [32:0] resL;
(* USE_DSP = "no" *)
reg [32:0] resL1,resL2;
reg [32:0] resMS1,resMS2,resMU1,resMU2;
reg [31:0] st_data;
wire [11:0] bcdaddo,bcdsubo,bcdnego;
wire bcdaddoc,bcdsuboc,bcdnegoc;
reg [31:0] bad_addr;
reg [15:0] mac_cycle_type;
reg prev_nmi;
reg pe_nmi;
reg is_nmi;
reg is_irq, is_trace, is_priv, is_illegal;
reg is_adr_err;
reg is_rst;
reg is_bus_err;
reg use_dfc, use_sfc;
reg [4:0] rst_cnt;
reg [2:0] shift_op;
reg rtr;
reg bsr;
reg lea;
reg bcdsub, bcdneg;
reg [31:0] dati_buf;    // input data from bus error
reg [31:0] dato_buf;

// CSR's
reg [31:0] tick;        // FF0
reg [7:0] asid;         // 003
assign asid_o = asid;
reg [31:0] vbr;         // 801
reg [31:0] sfc;         // 000
reg [31:0] dfc;         // 001
reg [31:0] apc;
reg [7:0] cpl;
reg [31:0] tr;
reg [31:0] tcba;
reg [31:0] mmus, ios, iops;
assign mmus_o = adr_o[31:20] == mmus[31:20];
assign iops_o = adr_o[31:16] == iops[31:16];
assign ios_o  = adr_o[31:20] == ios [31:20];

wire [16:0] lfsr_o;
lfsr17 ulfsr1
(
        .rst(rst_i),
        .clk(clk_g),
        .ce(1'b1),
        .cyc(1'b0),
        .o(lfsr_o)
);

/*
reg [31:0] cache_tag [0:7];
reg [15:0] cache_dat [0:7];

task tPushCache;
input [31:0] adr;
input [15:0] dat;
integer n;
begin
        for (n = 1; n < 8; n = n + 1) begin
                cache_tag[n] <= cache_tag[n-1];
                cache_dat[n] <= cache_dat[n-1];
        end
        cache_tag[0] <= adr;
        cache_dat[0] <= dat;
end
endtask

function fnInCache;
input [31:0] adr;
integer n;
begin
        fnInCache = 1'b0;
        for (n = 0; n < 8; n = n + 1) begin
                if (cache_tag[n]==adr) begin
                        fnInCache = 1'b1;               
        end
end
endfunction

task tFindInCache;
input [31:0] adr;
output [15:0] dat;
integer n;
begin
        dat = 16'h4E71; // NOP
        for (n = 0; n < 8; n = n + 1) begin
                if (cache_tag[n]==adr) begin
                        dat = cache_dat[n];
                end
        end
end
endtask
*/

function [31:0] rbo;
input [31:0] w;
rbo = {w[7:0],w[15:8],w[23:16],w[31:24]};
endfunction

wire [7:0] dbin, sbin;
reg [9:0] bcdres;
wire dd_done;
wire [11:0] bcdreso;
BCDToBin ub2b1 (clk_g, d, dbin);
BCDToBin ub2b2 (clk_g, s, sbin);

DDBinToBCD #(.WID(10)) udd1
(
        .rst(rst_i),
        .clk(clk_g),
        .ld(state==BCD3),
        .bin(bcdres),
        .bcd(bcdreso),
        .done(dd_done)
);

reg [31:0] dd32in;
wire [39:0] dd32out;
wire dd32done;
DDBinToBCD #(.WID(32)) udd2
(
        .rst(rst_i),
        .clk(clk_g),
        .ld(state==BIN2BCD1),
        .bin(dd32in),
        .bcd(dd32out),
        .done(dd32done)
);

/*
BCDAdd u1
(
        .ci(xf),
        .a(s[7:0]),
        .b(d[7:0]),
        .o(bcdaddo),
        .c(bcdaddoc)
);


BCDSub u2
(
        .ci(xf),
        .a(d[7:0]),
        .b(s[7:0]),
        .o(bcdsubo),
        .c(bcdsuboc)
);

BCDSub u3
(
        .ci(xf),
        .a(8'h00),
        .b(d[7:0]),
        .o(bcdnego),
        .c(bcdnegoc)
);
*/
// These functions take the MSBs of the operands and results and return an
// overflow status.

// If the signs of the operands are the same, and the sign of the result does
// not match the operands sign.
function fnAddOverflow;
input r;
input a;
input b;
        fnAddOverflow = (r ^ b) & (1'b1 ^ a ^ b);
endfunction

// If the signs of the operands are different and sign of the result does not
// match the first operand.
function fnSubOverflow;
input r;
input a;
input b;
        fnSubOverflow = (r ^ a) & (a ^ b);
endfunction

reg divs;
wire dvdone;
wire dvByZr;
wire dvovf;
wire [31:0] divq;
wire [31:0] divr;

rf68000_divider udiv1
(
        .rst(rst_i),
        .clk(clk_g),
        .ld(state==DIV1),
        .abort(1'b0),
        .sgn(divs),
        .sgnus(1'b0),
        .a(d),
        .b(divs? {{16{s[15]}},s[15:0]}:{16'd0,s[15:0]}),
        .qo(divq),
        .ro(divr),
        .dvByZr(dvByZr),
        .ovf(dvovf),
        .done(dvdone),
        .idle()
);

always_comb
case(ir[15:8])
`BRA:   takb = 1'b1;
`BSR:   takb = 1'b0;
`BHI:   takb = !cf & !zf;
`BLS:   takb = cf | zf;
`BHS:   takb = !cf;
`BLO:   takb =  cf;
`BNE:   takb = !zf;
`BEQ:   takb =  zf;
`BVC:   takb = !vf;
`BVS:   takb =  vf;
`BPL:   takb = !nf;
`BMI:   takb =  nf;
`BGE:   takb = (nf & vf)|(!nf & !vf);
`BLT:   takb = (nf & !vf)|(!nf & vf);
`BGT:   takb = (nf & vf & !zf)|(!nf & !vf & zf);
`BLE:   takb = zf | (nf & !vf) | (!nf & vf);
`DBRA:  takb = 1'b1;
`DBSR:  takb = 1'b0;
`DBHI:  takb = !cf & !zf;
`DBLS:  takb = cf | zf;
`DBHS:  takb = !cf;
`DBLO:  takb =  cf;
`DBNE:  takb = !zf;
`DBEQ:  takb =  zf;
`DBVC:  takb = !vf;
`DBVS:  takb =  vf;
`DBPL:  takb = !nf;
`DBMI:  takb =  nf;
`DBGE:  takb = ((nf & vf)|(!nf & !vf));
`DBLT:  takb = ((nf & !vf)|(!nf & vf));
`DBGT:  takb = ((nf & vf & !zf)|(!nf & !vf & zf));
`DBLE:  takb = (zf | (nf & !vf) | (!nf & vf));
default:        takb = 1'b1;
endcase

`ifdef BIG_ENDIAN
wire [15:0] iri = pc[1] ? {dat_i[23:16],dat_i[31:24]} : {dat_i[7:0],dat_i[15:8]};
`else
wire [15:0] iri = pc[1] ? dat_i[31:16] : dat_i[15:0];
`endif

assign clk_g = clk_i;

always_ff @(posedge clk_g)
if (rst_i) begin
        em <= 1'b0;
        lock_o <= 1'b0;
        cyc_o <= 1'b0;
        stb_o <= 1'b0;
        we_o <= 1'b0;
        sel_o <= 4'b0000;
        fc_o <= 3'b000;
        adr_o <= 32'd0;
        dat_o <= 32'd0;
        rfwrB <= 1'b0;
        rfwrW <= 1'b0;
        rfwrL <= 1'b0;
        zf <= 1'b0;
        nf <= 1'b0;
        cf <= 1'b0;
        vf <= 1'b0;
        xf <= 1'b0;
        im <= 3'b111;
        sf <= 1'b1;
        tf <= 1'b0;
        goto (RESET);
        rstate <= RESET;
        prev_nmi <= 1'b0;
        pe_nmi <= 1'b0;
  tick <= 32'd0;
  rst_cnt <= 5'd10;
  rst_o <= 1'b1;
  is_rst <= 1'b1;
        MMMRRR <= 1'b0;
        rtr <= 1'b0;
        bsr <= 1'b0;
        lea <= 1'b0;
        divs <= 1'b0;
        bcdsub <= 1'b0;
        bcdneg <= 1'b0;
        icnt <= 'd0;
        is_bus_err <= 1'b0;
        is_adr_err <= 1'b0;
        is_trace <= 1'b0;
        is_priv <= 1'b0;
        is_illegal <= 1'b0;
        vbr <= 'd0;
        sfc <= 'd0;
        dfc <= 'd0;
        dati_buf <= 'd0;
        dato_buf <= 'd0;
        use_sfc <= 'd0;
        use_dfc <= 'd0;
        ext_ir <= 1'b0;
        ios  <= 32'hFD000000;
        iops <= 32'hFD100000;
        mmus <= 32'hFDC00000;
end
else begin

if (rst_cnt != 5'd0)
    rst_cnt <= rst_cnt - 5'd1;
else
    rst_o <= 1'b0;

tick <= tick + 32'd1;
prev_nmi <= nmi_i;
if (nmi_i & !prev_nmi)
        pe_nmi <= 1'b1;

// Register file update
rfwrB <= 1'b0;
rfwrW <= 1'b0;
rfwrL <= 1'b0;
if (rfwrL) begin
  case(Rt)
  4'd0:   d0 <= resL[31:0];
  4'd1:   d1 <= resL[31:0];
  4'd2:   d2 <= resL[31:0];
  4'd3:   d3 <= resL[31:0];
  4'd4:   d4 <= resL[31:0];
  4'd5:   d5 <= resL[31:0];
  4'd6:   d6 <= resL[31:0];
  4'd7:   d7 <= resL[31:0];
  4'd8:   a0 <= resL[31:0];
  4'd9:   a1 <= resL[31:0];
  4'd10:  a2 <= resL[31:0];
  4'd11:  a3 <= resL[31:0];
  4'd12:  a4 <= resL[31:0];
  4'd13:  a5 <= resL[31:0];
  4'd14:  a6 <= resL[31:0];
  4'd15:  sp <= resL[31:0];
  endcase
end
else if (rfwrW) begin
  case(Rt)
  4'd0:   d0[15:0] <= resW[15:0];
  4'd1:   d1[15:0] <= resW[15:0];
  4'd2:   d2[15:0] <= resW[15:0];
  4'd3:   d3[15:0] <= resW[15:0];
  4'd4:   d4[15:0] <= resW[15:0];
  4'd5:   d5[15:0] <= resW[15:0];
  4'd6:   d6[15:0] <= resW[15:0];
  4'd7:   d7[15:0] <= resW[15:0];
  4'd8:   a0 <= {{16{resW[15]}},resW[15:0]};
  4'd9:   a1 <= {{16{resW[15]}},resW[15:0]};
  4'd10:  a2 <= {{16{resW[15]}},resW[15:0]};
  4'd11:  a3 <= {{16{resW[15]}},resW[15:0]};
  4'd12:  a4 <= {{16{resW[15]}},resW[15:0]};
  4'd13:  a5 <= {{16{resW[15]}},resW[15:0]};
  4'd14:  a6 <= {{16{resW[15]}},resW[15:0]};
  4'd15:  sp <= {{16{resW[15]}},resW[15:0]};
  endcase
end
else if (rfwrB)
  case(Rt)
  4'd0:   d0[7:0] <= resB[7:0];
  4'd1:   d1[7:0] <= resB[7:0];
  4'd2:   d2[7:0] <= resB[7:0];
  4'd3:   d3[7:0] <= resB[7:0];
  4'd4:   d4[7:0] <= resB[7:0];
  4'd5:   d5[7:0] <= resB[7:0];
  4'd6:   d6[7:0] <= resB[7:0];
  4'd7:   d7[7:0] <= resB[7:0];
  default:    ;
  endcase

case(state)

IFETCH:
        begin
                case(flag_update)
                FU_MUL:
                        begin
                                cf <= 1'b0;
                                vf <= 1'b0;
                                nf <= resL[31];
                                zf <= resL[31:0]==32'd0;
                        end
                FU_TST:
                        begin
                                cf <= 1'b0;
                                vf <= 1'b0;
                                case(sz)
                                2'b00:  begin zf <= d[7:0]==8'h00; nf <= d[7]; end
                                2'b01:  begin zf <= d[15:0]==16'h00; nf <= d[15]; end
                                2'b10:  begin zf <= d[31:0]==32'h00; nf <= d[31]; end
                                default:        ;
                                endcase
                        end
                FU_CMP:
                        begin
                                case(sz)
                                2'b00:  begin zf <= resB[ 7:0]== 8'd0; nf <= resB[ 7]; cf <= resB[ 8]; vf <= fnSubOverflow(resB[ 7],d[ 7],s[ 7]); end
                                2'b01:  begin zf <= resW[15:0]==16'd0; nf <= resW[15]; cf <= resW[16]; vf <= fnSubOverflow(resW[15],d[15],s[15]); end
                                2'b10:  begin zf <= resL[31:0]==32'd0; nf <= resL[31]; cf <= resL[32]; vf <= fnSubOverflow(resL[31],d[31],s[31]); end
                                2'b11:  begin zf <= resL[31:0]==32'd0; nf <= resL[31]; cf <= resL[32]; vf <= fnSubOverflow(resL[31],d[31],s[31]); end   // CMPA
                                endcase
                        end
                FU_ADD:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                cf <= resB[8];
                                                nf <= resB[7];
                                                zf <= resB[7:0]==8'h00;
                                                vf <= fnAddOverflow(resB[7],dd[7],s[7]);
                                                xf <= resB[8];
                                        end
                                2'b01:
                                        begin
                                                cf <= resW[16];
                                                nf <= resW[15];
                                                zf <= resW[15:0]==16'h0000;
                                                vf <= fnAddOverflow(resW[15],dd[15],s[15]);
                                                xf <= resW[16];
                                        end
                                2'b10:
                                        begin
                                                cf <= resL[32];
                                                nf <= resL[31];
                                                zf <= resL[31:0]==32'h00000000;
                                                vf <= fnAddOverflow(resL[31],dd[31],s[31]);
                                                xf <= resL[32];
                                        end
                                default:        ;
                                endcase
                        end
                FU_ADDX:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                cf <= resB[8];
                                                nf <= resB[7];
                                                if (resB[7:0]!=8'h00)
                                                        zf <= 1'b0;
                                                vf <= fnAddOverflow(resB[7],dd[7],s[7]);
                                                xf <= resB[8];
                                        end
                                2'b01:
                                        begin
                                                cf <= resW[16];
                                                nf <= resW[15];
                                                if (resW[15:0]!=16'h00)
                                                        zf <= 1'b0;
                                                vf <= fnAddOverflow(resW[15],dd[15],s[15]);
                                                xf <= resW[16];
                                        end
                                2'b10:
                                        begin
                                                cf <= resL[32];
                                                nf <= resL[31];
                                                if (resL[31:0]!=32'h00)
                                                        zf <= 1'b0;
                                                vf <= fnAddOverflow(resL[31],dd[31],s[31]);
                                                xf <= resL[32];
                                        end
                                default:        ;
                                endcase
                        end
                FU_SUBX:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                cf <= resB[8];
                                                nf <= resB[7];
                                                if (resB[7:0]!=8'h00)
                                                        zf <= 1'b0;
                                                vf <= fnSubOverflow(resB[7],dd[7],s[7]);
                                                xf <= resB[8];
                                        end
                                2'b01:
                                        begin
                                                cf <= resW[16];
                                                nf <= resW[15];
                                                if (resW[15:0]!=16'h00)
                                                        zf <= 1'b0;
                                                vf <= fnSubOverflow(resW[15],dd[15],s[15]);
                                                xf <= resW[16];
                                        end
                                2'b10:
                                        begin
                                                cf <= resL[32];
                                                nf <= resL[31];
                                                if (resL[31:0]!=32'h00)
                                                        zf <= 1'b0;
                                                vf <= fnSubOverflow(resL[31],dd[31],s[31]);
                                                xf <= resL[32];
                                        end
                                default:        ;
                                endcase
                        end
                FU_SUB:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                cf <= resB[8];
                                                nf <= resB[7];
                                                zf <= resB[7:0]==8'h00;
                                                vf <= fnSubOverflow(resB[7],dd[7],s[7]);
                                                xf <= resB[8];
                                        end
                                2'b01:
                                        begin
                                                cf <= resW[16];
                                                nf <= resW[15];
                                                zf <= resW[15:0]==16'h0000;
                                                vf <= fnSubOverflow(resW[15],dd[15],s[15]);
                                                xf <= resW[16];
                                        end
                                2'b10:
                                        begin
                                                cf <= resL[32];
                                                nf <= resL[31];
                                                zf <= resL[31:0]==32'h00000000;
                                                vf <= fnSubOverflow(resL[31],dd[31],s[31]);
                                                xf <= resL[32];
                                        end
                                default:        ;
                                endcase
                        end
                FU_LOGIC:
                        begin
                                cf <= 1'b0;
                                vf <= 1'b0;
                                case(sz)
                                2'b00:
                                        begin
                                                nf <= resB[7];
                                                zf <= resB[7:0]==8'h00;
                                        end
                                2'b01:
                                        begin
                                                nf <= resW[15];
                                                zf <= resW[15:0]==16'h0000;
                                        end
                                2'b10:
                                        begin
                                                nf <= resL[31];
                                                zf <= resL[31:0]==32'h00000000;
                                        end
                                default:        ;
                                endcase
                        end
                FU_ADDQ:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                 xf <= resB[8];
                                                 cf <= resB[8];
                                                 vf <= resB[8]!=resB[7];
                                                vf <= fnAddOverflow(resB[7],dd[7],s[7]);
                                                 //zf <= resB[7:0]==8'd0;
                                                 nf <= resB[7];
                                        end
                                2'b01:
                                        begin
                                                 xf <= resW[16];
                                                 cf <= resW[16];
                                                vf <= fnAddOverflow(resW[15],dd[15],s[15]);
                                                 //vf <= resW[16]!=resW[15];
                                                 zf <= resW[15:0]==16'd0;
                                                 nf <= resW[15];
                                        end
                                2'b10:
                                        begin
                                                 xf <= resL[32];
                                                 cf <= resL[32];
                                                vf <= fnAddOverflow(resL[31],dd[31],s[31]);
                                                // vf <= resL[32]!=resL[31];
                                                 zf <= resL[31:0]==32'd0;
                                                 nf <= resL[31];
                                        end
                                endcase
                        end
                FU_SUBQ:
                        begin
                                case(sz)
                                2'b00:
                                        begin
                                                 xf <= resB[8];
                                                 cf <= resB[8];
                                                 vf <= resB[8]!=resB[7];
                                                vf <= fnSubOverflow(resB[7],dd[7],s[7]);
                                                 //zf <= resB[7:0]==8'd0;
                                                 nf <= resB[7];
                                        end
                                2'b01:
                                        begin
                                                 xf <= resW[16];
                                                 cf <= resW[16];
                                                vf <= fnSubOverflow(resW[15],dd[15],s[15]);
                                                 //vf <= resW[16]!=resW[15];
                                                 zf <= resW[15:0]==16'd0;
                                                 nf <= resW[15];
                                        end
                                2'b10:
                                        begin
                                                 xf <= resL[32];
                                                 cf <= resL[32];
                                                vf <= fnSubOverflow(resL[31],dd[31],s[31]);
                                                // vf <= resL[32]!=resL[31];
                                                 zf <= resL[31:0]==32'd0;
                                                 nf <= resL[31];
                                        end
                                endcase
                        end
                FU_ADDI:
                        begin
                                case(ir[11:8])
                                4'h0,4'h2,4'hA:
                                                begin   // ORI,ANDI,EORI
                                                        cf <= 1'b0;
                                                        vf <= 1'b0;
                                                        case(sz)
                                                        2'b00:  zf <= resB[7:0]==8'h00;
                                                        2'b01:  zf <= resW[15:0]==16'h00;
                                                        2'b10:  zf <= resL[31:0]==32'd0;
                                                        endcase
                                                        case(sz)
                                                        2'b00:  nf <= resB[7];
                                                        2'b01:  nf <= resW[15];
                                                        2'b10:  nf <= resL[31];
                                                        endcase
                                                end
                                4'h4:   // SUBI
                                        begin
                                                case(sz)
                                                2'b00:
                                                        begin
                                                                xf <= resB[8];
                                                                cf <= resB[8];
                                                                vf <= fnSubOverflow(resB[7],dd[7],immx[7]);
                                                                //vf <= resB[8]!=resB[7];
                                                                zf <= resB[7:0]==8'd0;
                                                                nf <= resB[7];
                                                        end
                                                2'b01:
                                                        begin
                                                                xf <= resW[16];
                                                                cf <= resW[16];
                                                                vf <= fnSubOverflow(resW[15],dd[15],immx[15]);
                                                                //vf <= resW[16]!=resW[15];
                                                                zf <= resW[15:0]==16'd0;
                                                                nf <= resW[15];
                                                        end
                                                2'b10:
                                                        begin
                                                                xf <= resL[32];
                                                                cf <= resL[32];
                                                                vf <= fnSubOverflow(resL[31],dd[31],immx[31]);
                                                                //vf <= resL[32]!=resL[31];
                                                                zf <= resL[31:0]==32'd0;
                                                                nf <= resL[31];
                                                        end
                                                endcase
                                        end
                                4'h6:   // ADDI
                                        begin
                                                case(sz)
                                                2'b00:
                                                        begin
                                                                xf <= resB[8];
                                                                cf <= resB[8];
                                                                vf <= fnAddOverflow(resB[7],dd[7],immx[7]);
                                                                //vf <= resB[8]!=resB[7];
                                                                zf <= resB[7:0]==8'd0;
                                                                nf <= resB[7];
                                                        end
                                                2'b01:
                                                        begin
                                                                xf <= resW[16];
                                                                cf <= resW[16];
                                                                vf <= fnAddOverflow(resW[15],dd[15],immx[15]);
                                                                //vf <= resW[16]!=resW[15];
                                                                zf <= resW[15:0]==16'd0;
                                                                nf <= resW[15];
                                                        end
                                                2'b10:
                                                        begin
                                                                xf <= resL[32];
                                                                cf <= resL[32];
                                                                vf <= fnAddOverflow(resL[31],dd[31],immx[31]);
                                                                //vf <= resL[32]!=resL[31];
                                                                zf <= resL[31:0]==32'd0;
                                                                nf <= resL[31];
                                                        end
                                                endcase
                                        end
                                4'hC:   // CMPI
                                        begin
                                                case(sz)
                                                2'b00:
                                                        begin
                                                                cf <= resB[8];
                                                                vf <= fnSubOverflow(resB[7],dd[7],immx[7]);
                                                                zf <= resB[7:0]==8'd0;
                                                                nf <= resB[7];
                                                        end
                                                2'b01:
                                                        begin
                                                                cf <= resW[16];
                                                                vf <= fnSubOverflow(resW[15],dd[15],immx[15]);
                                                                //vf <= resW[16]!=resW[15];
                                                                zf <= resW[15:0]==16'd0;
                                                                nf <= resW[15];
                                                        end
                                                2'b10:
                                                        begin
                                                                cf <= resL[32];
                                                                vf <= fnSubOverflow(resL[31],dd[31],immx[31]);
                                                                //vf <= resL[32]!=resL[31];
                                                                zf <= resL[31:0]==32'd0;
                                                                nf <= resL[31];
                                                        end
                                                endcase
                                        end
                                endcase
                        end
                FU_ANDI_CCR:
                        begin
                                cf <= cf & imm[0];
                                vf <= vf & imm[1];
                                zf <= zf & imm[2];
                                nf <= nf & imm[3];
                                xf <= xf & imm[4];
                        end
                FU_ANDI_SR:
                        begin
                                cf <= cf & imm[0];
                                vf <= vf & imm[1];
                                zf <= zf & imm[2];
                                nf <= nf & imm[3];
                                xf <= xf & imm[4];
                                im[0] <= im[0] & imm[8];
                                im[1] <= im[1] & imm[9];
                                im[2] <= im[2] & imm[10];
                                sf <= sf & imm[13];
                                tf <= tf & imm[15];
                        end
                FU_ANDI_SRX:
                        begin
                                cf <= cf & imm[0];
                                vf <= vf & imm[1];
                                zf <= zf & imm[2];
                                nf <= nf & imm[3];
                                xf <= xf & imm[4];
                                im[0] <= im[0] & imm[8];
                                im[1] <= im[1] & imm[9];
                                im[2] <= im[2] & imm[10];
                                sf <= sf & imm[13];
                                tf <= tf & imm[15];
                        end
                FU_EORI_CCR:
                        begin
                                cf <= cf ^ imm[0];
                                vf <= vf ^ imm[1];
                                zf <= zf ^ imm[2];
                                nf <= nf ^ imm[3];
                                xf <= xf ^ imm[4];
                        end
                FU_EORI_SR:
                        begin
                                cf <= cf ^ imm[0];
                                vf <= vf ^ imm[1];
                                zf <= zf ^ imm[2];
                                nf <= nf ^ imm[3];
                                xf <= xf ^ imm[4];
                                im[0] <= im[0] ^ imm[8];
                                im[1] <= im[1] ^ imm[9];
                                im[2] <= im[2] ^ imm[10];
                                sf <= sf ^ imm[13];
                                tf <= tf ^ imm[15];
                        end
                FU_EORI_SRX:
                        begin
                                cf <= cf ^ imm[0];
                                vf <= vf ^ imm[1];
                                zf <= zf ^ imm[2];
                                nf <= nf ^ imm[3];
                                xf <= xf ^ imm[4];
                                im[0] <= im[0] ^ imm[8];
                                im[1] <= im[1] ^ imm[9];
                                im[2] <= im[2] ^ imm[10];
                                sf <= sf ^ imm[13];
                                tf <= tf ^ imm[15];
                        end
                FU_ORI_CCR:
                        begin
                                cf <= cf | imm[0];
                                vf <= vf | imm[1];
                                zf <= zf | imm[2];
                                nf <= nf | imm[3];
                                xf <= xf | imm[4];
                        end
                FU_ORI_SR:
                        begin
                                cf <= cf | imm[0];
                                vf <= vf | imm[1];
                                zf <= zf | imm[2];
                                nf <= nf | imm[3];
                                xf <= xf | imm[4];
                                im[0] <= im[0] | imm[8];
                                im[1] <= im[1] | imm[9];
                                im[2] <= im[2] | imm[10];
                                sf <= sf | imm[13];
                                tf <= tf | imm[15];
                        end
                FU_ORI_SRX:
                        begin
                                cf <= cf | imm[0];
                                vf <= vf | imm[1];
                                zf <= zf | imm[2];
                                nf <= nf | imm[3];
                                xf <= xf | imm[4];
                                im[0] <= im[0] | imm[8];
                                im[1] <= im[1] | imm[9];
                                im[2] <= im[2] | imm[10];
                                sf <= sf | imm[13];
                                tf <= tf | imm[15];
                        end
                FU_MOVE2CCR:
                        begin
                                cf <= s[0];
                                vf <= s[1];
                                zf <= s[2];
                                nf <= s[3];
                                xf <= s[4];
                                ccr57 <= s[7:5];
                        end     
                FU_MOVE2SR:
                        begin
                                cf <= s[0];
                                vf <= s[1];
                                zf <= s[2];
                                nf <= s[3];
                                xf <= s[4];
                                ccr57 <= s[7:5];
                                im[0] <= s[8];
                                im[1] <= s[9];
                                im[2] <= s[10];
                                sr1112 <= s[12:11];
                                sf <= s[13];
                                sr14 <= s[14];
                                tf <= s[15];
                        end
                FU_MOVE2SRX:
                        begin
                                cf <= s[0];
                                vf <= s[1];
                                zf <= s[2];
                                nf <= s[3];
                                xf <= s[4];
                                ccr57 <= s[7:5];
                                im[0] <= s[8];
                                im[1] <= s[9];
                                im[2] <= s[10];
                                sr1112 <= s[12:11];
                                sf <= s[13];
                                sr14 <= s[14];
                                tf <= s[15];
                        end
                default:        ;
                endcase
                flag_update <= FU_NONE;
                MMMRRR <= 1'b0;
                rtr <= 1'b0;
                bsr <= 1'b0;
                lea <= 1'b0;
                bcdsub <= 1'b0;
                bcdneg <= 1'b0;
                is_illegal <= 1'b0;
                use_sfc <= 1'b0;
                use_dfc <= 1'b0;
                if (!cyc_o) begin
                        is_nmi <= 1'b0;
                        is_irq <= 1'b0;
                        /*
                        if (pe_nmi) begin
                                pe_nmi <= 1'b0;
                                is_nmi <= 1'b1;
                                goto(TRAP);
                        end
                        else 
                        */
                        if (ipl_i > im) begin
                                is_irq <= 1'b1;
                                gosub(TRAP);
                        end
                        else if (pc[0]) begin
                                is_adr_err <= 1'b1;
                                gosub(TRAP);
                        end
                        else begin
                                fc_o <= {sf,2'b10};
                                cyc_o <= 1'b1;
                                stb_o <= 1'b1;
                                sel_o <= 4'b1111;
                                adr_o <= pc;
                                goto (IFETCH);
                        end
                end
                else if (ack_i) begin
                        cyc_o <= 1'b0;
                        stb_o <= 1'b0;
                        sel_o <= 2'b00;
                        ir <= iri;
                        mmm <= iri[5:3];
                        rrr <= iri[2:0];
                        rrrr <= iri[3:0];
                        gosub (DECODE);
                end
        end
IFETCH2:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
                goto (IFETCH2);
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 2'b00;
                ext_ir <= 1'b1;
                ir2 <= iri;
                goto (DECODE);
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DECODE:
        begin
                pc <= pc + 4'd2;
                opc <= pc + 4'd2;
                icnt <= icnt + 2'd1;
        case({ext_ir,ir[15:12]})
        5'h0:
                case(ir[11:8])
                4'h0:
                        case(ir[7:0])
                        8'h3C:  state <= ORI_CCR;
                        8'h7C:
                                if (sf) 
                                        goto (ORI_SR);
                                else
                                        tPrivilegeViolation();
                        8'hBC:  
                                if (sf) 
                                        goto (ORI_SRX);
                                else
                                        tPrivilegeViolation();
                        default:        state <= ADDI;  // ORI
                        endcase
                4'h2:
                        case(ir[7:0])
                        8'h3C:  state <= ANDI_CCR;
                        8'h7C:  
                                if (sf) 
                                        goto (ANDI_SR);
                                else
                                        tPrivilegeViolation();
                        8'hBC:
                                if (sf) 
                                        goto (ANDI_SRX);
                                else
                                        tPrivilegeViolation();
                        default:        state <= ADDI;  // ANDI
                        endcase
                4'h4:   state <= ADDI;  // SUBI
                4'h6:   state <= ADDI;  // ADDI
                4'hA:
                        case(ir[7:0])
                        8'h3C:  state <= EORI_CCR;
                        8'h7C:
                                if (sf) 
                                        goto (EORI_SR);
                                else
                                        tPrivilegeViolation();
                        8'hBC:
                                if (sf) 
                                        goto (EORI_SRX);
                                else
                                        tPrivilegeViolation();
                        default:        state <= ADDI;  // EORI
                        endcase
                4'hC:   state <= ADDI;  // CMPI
`ifdef SUPPORT_010              
                4'hE:   // MOVES
                        begin
                                call(FETCH_IMM16,MOVES);
                        end
`endif                  
                default:        
                        if (mmm==3'b001 && ir[8]) begin
                                push(MOVEP);
                                fs_data(3'b101,rrr,FETCH_NOP_WORD,S);
                        end
                        else
                                goto (BIT);
                endcase
//-----------------------------------------------------------------------------
// MOVE.B
//-----------------------------------------------------------------------------
        5'h1:   
                begin
                        push(STORE_IN_DEST);
                        fs_data(mmm,rrr,FETCH_BYTE,S);
                end
//-----------------------------------------------------------------------------
// MOVE.L
//-----------------------------------------------------------------------------
  5'h2:    
        begin
                        push(STORE_IN_DEST);
        fs_data(mmm,rrr,FETCH_LWORD,S);
    end
//-----------------------------------------------------------------------------
// MOVE.W
//-----------------------------------------------------------------------------
        5'h3:
                begin
                        push(STORE_IN_DEST);
                        fs_data(mmm,rrr,FETCH_WORD,S);
                end
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
        5'h4:
                casez(ir[11:3])
                9'b0000?????:
                        case(sz)
                        2'b00:  begin push(NEGX); fs_data(mmm,rrr,FETCH_BYTE,D); end
                        2'b01:  begin push(NEGX); fs_data(mmm,rrr,FETCH_WORD,D); end
                        2'b10:  begin push(NEGX); fs_data(mmm,rrr,FETCH_LWORD,D); end
                        2'b11:  // MOVE sr,<ea>
                                if (sf) begin 
                                        d <= sr;
                                        resW <= sr;
                                        fs_data(mmm,rrr,STORE_WORD,S);
                                end
                                else
                                        tPrivilegeViolation();
                        endcase
                9'b000110???:   // MOVE.L srx,<ea>
                                if (sf) begin
                                        d <= srx;
                                        resL <= srx;
                                        fs_data(mmm,rrr,STORE_LWORD,S);
                                end     
                                else
                                        tPrivilegeViolation();
                9'b0010?????:
                        begin           // 42xx CLR
                                cf <= 1'b0;
                                vf <= 1'b0;
                                zf <= 1'b1;
                                nf <= 1'b0;
                                d <= 'd0;
                                case(sz)
                                2'b00:  fs_data(mmm,rrr,STORE_BYTE,D);
                                2'b01:  fs_data(mmm,rrr,STORE_WORD,D);
                                2'b10:  fs_data(mmm,rrr,STORE_LWORD,D);
                                default:        tIllegal();
                                endcase
                        end
                9'b0100?????:
                        casez(sz)
                        2'b00:  begin push(NEG); fs_data(mmm,rrr,FETCH_BYTE,D); end
                        2'b01:  begin push(NEG); fs_data(mmm,rrr,FETCH_WORD,D); end
                        2'b10:  begin push(NEG); fs_data(mmm,rrr,FETCH_LWORD,D); end
                        2'b11:  // MOVE <src>,ccr
                                begin
                                        flag_update <= FU_MOVE2CCR;
                                        fs_data(mmm,rrr,FETCH_WORD,S);
                                end
                        endcase
                9'b0110?????:
                        case(sz)
                        2'b00:  begin push(NOT); fs_data(mmm,rrr,FETCH_BYTE,D); end
                        2'b01:  begin push(NOT); fs_data(mmm,rrr,FETCH_WORD,D); end
                        2'b10:  begin push(NOT); fs_data(mmm,rrr,FETCH_LWORD,D); end
                        2'b11:  
                                if (sf) begin   // MOVE <src>,sr
                                        flag_update <= FU_MOVE2SR;
                                        fs_data(mmm,rrr,FETCH_WORD,S);
                                end
                                else
                                        tPrivilegeViolation();
                        default:        ;
                        endcase
/*                      
                9'b0111?????:
                        case(sz)
                        2'b00:  tIllegal();
                        2'b01:  tIllegal();
                        2'b10:  tIllegal();
                        2'b11:  
                                if (sf) begin   // MOVE <src>,srx
                                        flag_update <= FU_MOVE2SRX;
                                        fs_data(mmm,rrr,FETCH_LWORD,S);
                                end
                                else
                                        tPrivilegeViolation();
                        default:        ;
                        endcase
*/                      
                9'b10001?000:
                        if (ir[6]) begin        // EXT.L
                                cf <= 1'b0;
                                vf <= 1'b0;
                                nf <= rfoRnn[15];
                                zf <= rfoRnn[15:0]==16'h0000;
                                rfwrL <= 1'b1;
                                Rt <= {1'b0,ir[2:0]};
                                resL <= {{16{rfoRnn[15]}},rfoRnn[15:0]};
                                ret();
                        end
                        else begin      // EXT.W
                                cf <= 1'b0;
                                vf <= 1'b0;
                                nf <= rfoRnn[7];
                                zf <= rfoRnn[7:0]==8'h00;
                                rfwrW <= 1'b1;
                                Rt <= {1'b0,ir[2:0]};
                                resW <= {rfoRnn[31:16],{8{rfoRnn[7]}},rfoRnn[7:0]};
                                ret();
                        end
`ifdef SUPPORT_BCD                      
                9'b100000???:   // NBCD
                        begin
                                bcdneg <= 1'b1;
                                push(BCD1);
                                fs_data(mmm,rrr,FETCH_BYTE,D);
                        end
`endif                  
                9'b100001000:   // 484x         SWAP
                        begin   
                                cf <= 1'b0;
                                vf <= 1'b0;
                                zf <= rfoDnn==32'd0;
                                nf <= rfoDnn[15];
                                resL <= {rfoDnn[15:0],rfoDnn[31:16]};
                                Rt <= {1'b0,rrr};
                                rfwrL <= 1'b1;
                                ret();
                        end
                9'b100001???:   // PEA
                        begin
                                lea <= 1'b1;
                                goto (PEA1);
                        end
                9'b101011111:
                        case(ir[3:0])
                        4'hC:   tIllegal();     // 4AFC Illegal
                        endcase 
                9'b1010?????:   // TST / TAS
                        case(sz)
                        2'b00:  begin flag_update <= FU_TST; fs_data(mmm,rrr,FETCH_BYTE,D); end
                        2'b01:  begin flag_update <= FU_TST; fs_data(mmm,rrr,FETCH_WORD,D); end
                        2'b10:  begin flag_update <= FU_TST; fs_data(mmm,rrr,FETCH_LWORD,D); end
                        2'b11:  begin push(TAS); fs_data(mmm,rrr,LFETCH_BYTE,D); end            // TAS
                        endcase
                9'b11100100?:
                        goto (TRAP);
                9'b111001010:
                        goto (LINK);
                9'b111001011:
                        begin           // UNLK
                                sp <= rfoAn;
                                goto (UNLNK);
                        end
                9'b11100110?:
                        if (ir[3]) begin
                                ret();
                                Rt <= {1'b1,rrr};
                                rfwrL <= 1'b1;
                                resL <= usp;
                        end
                        else begin
                                ret();
                                usp <= rfoAn;
                        end
                9'b111001110:   // 4E70 RESET
                        case(ir[2:0])
                        3'b000: 
                                if (sf) begin
                                        rst_o <= 1'b1;
                                        rst_cnt <= 5'd10;
                                        ret(); 
                                end  
                                else
                                        tPrivilegeViolation();
                        3'b001: ret();  // NOP
                        3'b010: 
                                if (sf)
                                        goto (STOP);
                                else
                                        tPrivilegeViolation();
                        3'b011: 
                                if (sf)
                                        goto (RTE1);
                                else
                                        tPrivilegeViolation();
                        3'b101:
                                begin
                                        ea <= sp;
                                        sp <= sp + 4'd4;
                                        ds <= S;
                                        call (FETCH_LWORD,RTS1);
                                end
                        3'b110:
                                if (vf) begin
                        isr <= srx;
                        tf <= 1'b0;
                        sf <= 1'b1;
                            vecno <= `TRAPV_VEC;
                        goto (TRAP3);
                                end
                                else
                                        ret();          // 4E76 TRAPV
                        3'b111: 
                                begin
                                        rtr <= 1'b1;
                                        goto (RTE1); // RTR
                                end
                        endcase
                9'b111001111:
                        case(ir[2:0])
                        3'b010:         call(FETCH_IMM16,MOVERc2Rn);
                        3'b011:         call(FETCH_IMM16,MOVERn2Rc);
                        default:        tIllegal();
                        endcase
                9'b111010???:   // JSR          
                        begin
                                push(JSR);
                                fs_data(mmm,rrr,FETCH_LWORD,D);
                        end
                9'b111011???:   // JMP
                        begin
                                push(JMP);
                                fs_data(mmm,rrr,FETCH_NOP_LWORD,D);
                        end
                9'b1?001????:
                        if (ir[10])
                                call(FETCH_IMM16,MOVEM_s2Xn);
                        else
                                call(FETCH_IMM16,MOVEM_Xn2D);
                9'b???111???:
                        begin // LEA
                                lea <= 1'b1;    // ToDo: fix this, lea needs to be set one cycle before fs_data is called
                                goto (LEA);
                        end
                9'b???110???:
                        begin   // CHK
                                d <= rfoDn;
                                push(CHK);
                                fs_data(mmm,rrr,FETCH_WORD,S);
                        end
                default:
                        tIllegal();
                endcase
//***           4'hF:   state <= RTD1;  // 4Fxx = rtd

//-----------------------------------------------------------------------------
// ADDQ / SUBQ / DBRA / Scc
//-----------------------------------------------------------------------------
        5'h5:
                begin
                        casez(ir[7:3])
                        // When optimizing DBRA for performance, the memory access cycle to fetch
                        // the displacement constant is not done, instead the PC is incremented by
                        // two if not doing the DBRA. This is an extra PC increment that increases
                        // the code size. It is slower, but more hardware efficient to just always
                        // fetch the displacement.
                        5'b11001:                                       // DBRA
`ifdef OPT_PERF                 
                                if (~takb) begin
                                        call(FETCH_IMM16,DBRA);
                                end
                                else begin
                                        pc <= pc + 32'd4;       // skip over displacement
                                        ret();
                                end
`else
                                call(FETCH_IMM16,DBRA);                         
`endif                          
                        5'b11???:               // Scc
                                begin
                                        resL <= {32{takb}};
                                        resW <= {16{takb}};
                                        resB <= {8{takb}};
                                        d <= {32{takb}};
                                        if (mmm==3'b000) begin
                                                rfwrB <= 1'b1;
                                                Rt <= {1'b0,rrr};
                                                ret();
                                        end
                                        else begin
                                                fs_data(mmm,rrr,STORE_BYTE,S);
                                        end
                                end
                        default:
                                begin
                                        case(QQQ)
                                        3'd0:   begin imm <= 32'd8; immx <= 32'd8; end
                                        default:        begin imm <= {29'd0,QQQ}; immx <= {29'd0,QQQ}; end
                                        endcase
                                        case(sz)
                                        2'b00:  begin push(ADDQ); fs_data(mmm,rrr,FETCH_BYTE,D); end
                                        2'b01:  begin push(ADDQ); fs_data(mmm,rrr,FETCH_WORD,D); end
                                        2'b10:  begin push(ADDQ); fs_data(mmm,rrr,FETCH_LWORD,D); end
                                        default:        tIllegal();
                                        endcase
                                end
                        endcase
                end
                
//-----------------------------------------------------------------------------
// Branches
//-----------------------------------------------------------------------------
        5'h6:
                begin
                        opc <= pc + 4'd2;
                        ea <= pc + {{24{ir[7]}},ir[7:1],1'b0} + 4'd2;
                        if (ir[11:0]==12'h100) begin            // 6100 = BSR
                                bsr <= 1'b1;
                                call(FETCH_BRDISP,JSR);
                        end
                        else if (ir[11:8]==4'h1)        // 61xx = BSR
                                goto(JSR);
                        else if (takb) begin
                                // If branch back to self, trap
                          if (ir[7:0]==8'hFE)
                                tBadBranchDisp();
                                else
`ifdef SUPPORT_B24                      
                                if (ir[7:0]==8'h00 || ir[0]) begin
`else                           
                                if (ir[7:0]==8'h00) begin
`endif
                                        goto(FETCH_BRDISP);
                                end
                                else begin
                                        pc <= pc + {{24{ir[7]}},ir[7:1],1'b0} + 4'd2;
                                        ret();
                                end
                        end
                        else begin
`ifdef SUPPORT_B24                      
                                if (ir[7:0]==8'h00 || ir[0])            // skip over long displacement
`else
                                if (ir[7:0]==8'h00)             // skip over long displacement
`endif                  
                                        pc <= pc + 4'd4;
                                ret();
                        end
                end

//-----------------------------------------------------------------------------
// MOVEQ
//-----------------------------------------------------------------------------
        5'h7:
                // MOVEQ only if ir[8]==0, but it is otherwise not used for the 68k.
                // So some decode and fmax is saved by not decoding ir[8]
                //if (ir[8]==1'b0) 
                begin
                        vf <= 1'b0;
                        cf <= 1'b0;
                        nf <= ir[7];
                        zf <= ir[7:0]==8'h00;
                        rfwrL <= 1'b1;
                        Rt <= {1'b0,ir[11:9]};
                        resL <= {{24{ir[7]}},ir[7:0]};
                        ret();
                end
//-----------------------------------------------------------------------------
// OR / DIVU / DIVS / SBCD
//-----------------------------------------------------------------------------
        5'h8:
                begin
                        casez(ir[11:0])
`ifdef SUPPORT_DIV                      
                        12'b????_11??_????:     // DIVU / DIVS
                                begin
                                        divs <= ir[8];
                                        d <= rfoDn;
                                        push(DIV1);
                                        fs_data(mmm,rrr,FETCH_WORD,S);
                                end
`endif
`ifdef SUPPORT_BCD                              
                        12'b???1_0000_????:     // SBCD
                                begin
                                        bcdsub <= 1'b1;
                                        if (ir[3])
                                                goto (BCD);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (BCD1);
                                        end
                                end
`endif                          
                        default:        
                                begin
                case(sz)
                2'b00:    begin push(OR); fs_data(mmm,rrr,FETCH_BYTE,ir[8]?D:S); end
                2'b01:    begin push(OR); fs_data(mmm,rrr,FETCH_WORD,ir[8]?D:S); end
                2'b10:    begin push(OR); fs_data(mmm,rrr,FETCH_LWORD,ir[8]?D:S); end
                default:        ;       // can't get here, picked off by DIV
                                        endcase
                                end
                        endcase
                end
//-----------------------------------------------------------------------------
// SUB / SUBA / SUBX
//-----------------------------------------------------------------------------
  5'h9:
    begin
      if (ir[8])
        s <= rfoDn;
      else
        d <= rfoDn;
      if (ir[8] && ir[5:4]==2'b00)
                                case(sz)
                                2'b00:
                                        if (ir[3])
                                                goto (SUBX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (SUBX3);
                                        end
                                2'b01:
                                        if (ir[3])
                                                goto (SUBX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (SUBX3);
                                        end
                                2'b10:
                                        if (ir[3])
                                                goto (SUBX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (SUBX3);
                                        end
                                2'b11:
                begin
                        d <= rfoAna;
                        push(SUB);
                        if (ir[8]) fs_data(mmm,rrr,FETCH_LWORD,S);
                        else fs_data(mmm,rrr,FETCH_WORD,S);
                end
                                endcase
      else
              case(sz)
              2'b00:    begin push(SUB); fs_data(mmm,rrr,FETCH_BYTE,ir[8]?D:S); end
              2'b01:    begin push(SUB); fs_data(mmm,rrr,FETCH_WORD,ir[8]?D:S); end
              2'b10:    begin push(SUB); fs_data(mmm,rrr,FETCH_LWORD,ir[8]?D:S); end
              2'b11:
                begin
                        d <= rfoAna;
                        push(SUB);
                        if (ir[8]) fs_data(mmm,rrr,FETCH_LWORD,S);
                        else fs_data(mmm,rrr,FETCH_WORD,S);
                end
              endcase
    end
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
  5'hA:
        if (ir[11:8]==4'h2)
                goto (IFETCH2);
                else begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
        vecno <= `LINE10_VEC;
        goto (TRAP3);
        end
//-----------------------------------------------------------------------------
// CMP / CMPA / CMPM / EOR
//-----------------------------------------------------------------------------
        5'hB:
                begin
                        if (ir[8]) begin        // EOR
                                if (mmm==001)
                                        case(sz)
                                        2'b00:  begin push(CMPM); fs_data(3'b011,rrr,FETCH_BYTE,S); end
                                        2'b01:  begin push(CMPM); fs_data(3'b011,rrr,FETCH_WORD,S); end
                                        2'b10:  begin push(CMPM); fs_data(3'b011,rrr,FETCH_LWORD,S); end
                                        2'b11:  begin d <= rfoAna; push(CMPA); fs_data(mmm,rrr,FETCH_LWORD,S); end      // CMPA
                                        endcase
                                else
                                        case(sz)
                                        2'b00:  begin push(EOR); fs_data(mmm,rrr,FETCH_BYTE,D); end
                                        2'b01:  begin push(EOR); fs_data(mmm,rrr,FETCH_WORD,D); end
                                        2'b10:  begin push(EOR); fs_data(mmm,rrr,FETCH_LWORD,D); end
                                        2'b11:  begin d <= rfoAna; push(CMPA); fs_data(mmm,rrr,FETCH_LWORD,S); end      // CMPA
                                        endcase
                        end
                        else    // CMP
                                case(sz)
                                2'b00:  begin d <= rfoDn; push(CMP); fs_data(mmm,rrr,FETCH_BYTE,S); end
                                2'b01:  begin d <= rfoDn; push(CMP); fs_data(mmm,rrr,FETCH_WORD,S); end
                                2'b10:  begin d <= rfoDn; push(CMP); fs_data(mmm,rrr,FETCH_LWORD,S); end
                                2'b11:  begin d <= rfoAna; push(CMPA); fs_data(mmm,rrr,FETCH_WORD,S); end       // CMPA
                                endcase
                end
//-----------------------------------------------------------------------------
// AND / EXG / MULU / MULS / ABCD
//-----------------------------------------------------------------------------
        5'hC:
                begin
                        casez(ir[11:0])
`ifdef SUPPORT_BCD                      
                        12'b???1_0000_????:     // ABCD
                                if (ir[3])
                                        goto (BCD);
                                else begin
                                        s <= rfoDnn;
                                        d <= rfoDn;
                                        goto (BCD1);
                                end
`endif                          
                        12'b????_11??_????:     // MULS / MULU
                                begin
                                        push(ir[8] ? MULS1 : MULU1);
                                        fs_data(mmm,rrr,FETCH_WORD,S);
                                end
                        12'b???1_0100_0???:     // EXG  Dx,Dy
                        begin
                                Rt <= {1'b0,DDD};
                                rfwrL <= 1'b1;
                                resL <= rfoRnn;
                                s <= rfoDn;
                                goto (EXG1);
                        end
                        12'b???1_0100_1???:     // EXG Ax,Ay
                        begin
                                Rt <= {1'b1,AAA};
                                rfwrL <= 1'b1;
                                resL <= rfoRnn;
                                s <= rfoAna;
                                goto (EXG1);
                        end
                        12'b???1_1000_1???:     // EXG Dx,Ay
                        begin
                                Rt <= {1'b0,DDD};
                                rfwrL <= 1'b1;
                                resL <= rfoRnn;
                                s <= rfoDn;
                                goto (EXG1);
                        end
                        default:
                                case(sz)
                                2'b00:  begin push(AND); fs_data(mmm,rrr,FETCH_BYTE,ir[8]?D:S); end
                                2'b01:  begin push(AND); fs_data(mmm,rrr,FETCH_WORD,ir[8]?D:S); end
                                2'b10:  begin push(AND); fs_data(mmm,rrr,FETCH_LWORD,ir[8]?D:S); end
                                default:        ;       // Can't get here, picked off by MUL
                                endcase
                        endcase
                end

//-----------------------------------------------------------------------------
// ADD / ADDA / ADDX
//-----------------------------------------------------------------------------
        5'hD:
                begin
                        if (ir[8])
                                s <= rfoDn;
                        else
                                d <= rfoDn;
                        if (ir[8] && ir[5:4]==2'b00)
                                case(sz)
                                2'b00:  
                                        if (ir[3])
                                                goto (ADDX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (ADDX3);
                                        end
                                2'b01:  
                                        if (ir[3])
                                                goto (ADDX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (ADDX3);
                                        end
                                2'b10:
                                        if (ir[3])
                                                goto (ADDX);
                                        else begin
                                                s <= rfoDnn;
                                                d <= rfoDn;
                                                goto (ADDX3);
                                        end
                                2'b11:
                                        begin
                                                d <= rfoAna;
                                                push(ADD);
                                                if (ir[8]) fs_data(mmm,rrr,FETCH_LWORD,S);
                                                else fs_data(mmm,rrr,FETCH_WORD,S);
                                        end
                                endcase
                        else
                                case(sz)
                                2'b00:  begin push(ADD); fs_data(mmm,rrr,FETCH_BYTE,ir[8]?D:S); end
                                2'b01:  begin push(ADD); fs_data(mmm,rrr,FETCH_WORD,ir[8]?D:S); end
                                2'b10:  begin push(ADD); fs_data(mmm,rrr,FETCH_LWORD,ir[8]?D:S); end
                                2'b11:
                                        begin
                                                d <= rfoAna;
                                                push(ADD);
                                                if (ir[8]) fs_data(mmm,rrr,FETCH_LWORD,S);
                                                else fs_data(mmm,rrr,FETCH_WORD,S);
                                        end
                                endcase
                end
//-----------------------------------------------------------------------------
// ASL / LSL / ASR / LSR / ROL / ROR / ROXL / ROXR
//-----------------------------------------------------------------------------
        5'hE:
                begin
                        if (sz==2'b11) begin
                                cnt <= 6'd1;    // memory shifts only by one
                                shift_op <= {ir[8],ir[10:9]};
                                push(SHIFT1);
                                fs_data(mmm,rrr,FETCH_WORD,D);
                        end
                        else begin
                                shift_op <= {ir[8],ir[4:3]};
                                goto (SHIFT1);
                                if (ir[5])
                                        cnt <= rfoDn[5:0];
                                else
                                        cnt <= {2'b0,~|QQQ,QQQ};
                                // Extend by a bit for ASL overflow detection.
                                resL <= {rfoDnn[31],rfoDnn};
                                resB <= {rfoDnn[7],rfoDnn[7:0]};
                                resW <= {rfoDnn[15],rfoDnn[15:0]};
                                d <= rfoDnn;
                        end
                end
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
  5'hF:
    begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
        vecno <= `LINE15_VEC;
        goto (TRAP3);
    end
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
        5'h1A:
                begin
                        ext_ir <= 1'b0;
                        if (ir[11:8]==4'h2) begin
                                case(ir2[15:0])
                                16'h0000:
                                        begin
                                                dd32in <= rfoDnn;
                                                goto (BIN2BCD1);
                                        end
                                16'h0001:
                                        begin
                                                d <= rfoDnn;
                                                goto (BCD2BIN1);
                                        end
                                default:        tIllegal();
                                endcase
                        end
                end
        default: tIllegal();
        endcase
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
`ifdef SUPPORT_010
MOVES:
        begin
                ir2 <= imm[15:0];
                rrrr <= imm[15:12];
                Rt <= imm[15:12];
                if (imm[11])
                        goto (MOVES2);
                else begin
                        push(MOVES3);
                        use_sfc <= 1'b1;
                        case(sz)
                        2'd0:   fs_data(mmm,rrr,FETCH_BYTE,S);
                        2'd1:   fs_data(mmm,rrr,FETCH_WORD,S);
                        2'd2:   fs_data(mmm,rrr,FETCH_LWORD,S);
                        endcase
                end
        end
MOVES2:
        begin
                d <= rfoRnn;
                use_dfc <= 1'b1;
                case(sz)
                2'd0:   fs_data(mmm,rrr,STORE_BYTE,D);
                2'd1:   fs_data(mmm,rrr,STORE_WORD,D);
                2'd2:   fs_data(mmm,rrr,STORE_LWORD,D);
                default:        tIllegal();
                endcase
        end
MOVES3:
        begin
                case(sz)
                2'd0:
                        begin
                                resB <= s[7:0];
                                rfwrB <= 1'b1;
                        end
                2'd1:
                        begin
                                resW <= s[15:0];
                                rfwrW <= 1'b1;
                        end
                2'd2:
                        begin
                                resL <= s[31:0];
                                rfwrL <= 1'b1;
                        end
                default:        ;
                endcase
                ret();
        end
`endif

//-----------------------------------------------------------------------------
// BCD arithmetic
// ABCD / SBCD / NBCD
//-----------------------------------------------------------------------------
`ifdef SUPPORT_BCD
BCD:
        begin
                push(BCD0);
                fs_data(3'b100,rrr,FETCH_BYTE,S);
        end
BCD0:
        begin
                if (ir[3]) begin
                        push(BCD1);
                        fs_data(3'b100,RRR,FETCH_BYTE,D);
                end
                else
                        goto (BCD1);
        end
BCD1:   goto (BCD2);    // clock to convert BCD to binary.
BCD2:
        begin
                if (bcdsub)
                        bcdres <= dbin - sbin - xf;
                else if (bcdneg)
                        bcdres <= 8'h00 - dbin - xf;
                else
                        bcdres <= dbin + sbin + xf;
                goto (BCD3);
        end
BCD3:   goto (BCD4);    // clock to load binary to BCD conversion
BCD4:
        if (dd_done) begin
                if (ir[3] || (bcdneg && mmm!=3'b000 && mmm != 3'b001))
                        goto (STORE_BYTE);
                else begin
                        rfwrB <= 1'b1;
                        if (bcdneg)
                                Rt <= {1'b0,rrr};
                        else
                                Rt <= {1'b0,RRR};
                        resB <= bcdreso[7:0];
                        ret();
                end
                d <= bcdreso[7:0];
                cf <= |bcdreso[11:8];
                xf <= |bcdreso[11:8];
                nf <= bcdreso[7];
                if (bcdreso[7:0]!=8'h00)
                        zf <= 1'b0;
        end
`endif          

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
STOP:
        begin
                if (!sf) begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                        vecno <= `PRIV_VEC;
                        goto (TRAP3);
                end
                else
                        call (FETCH_IMM16, STOP1);
        end
STOP1:
        begin
                cf <= imm[0];
                vf <= imm[1];
                zf <= imm[2];
                nf <= imm[3];
                xf <= imm[4];
                im[0] <= imm[8];
                im[1] <= imm[9];
                im[2] <= imm[10];
                sf <= imm[13];
                tf <= imm[15];
                if (ipl_i > imm[10:8] || ipl_i==3'd7)
                        ret();
        end

//-----------------------------------------------------------------------------
// MULU / MULS
// - a couple of regs may be needed.
//-----------------------------------------------------------------------------
MULS1:
        begin
                resMS1 <= $signed(rfoDn[15:0]) * $signed(s[15:0]);
                goto (MULS2);
        end
MULS2:
        begin
                resMS2 <= resMS1;
                goto (MULS3);
        end
MULS3:
        begin
                flag_update <= FU_MUL;
                rfwrL <= 1'b1;
                Rt <= {1'b0,DDD};
                resL <= resMS2;
                ret();
        end
MULU1:
        begin
                resMU1 <= rfoDn[15:0] * s[15:0];
                goto (MULU2);
        end
MULU2:
        begin
                resMU2 <= resMU1;
                goto (MULU3);
        end
MULU3:
        begin
                flag_update <= FU_MUL;
                rfwrL <= 1'b1;
                Rt <= {1'b0,DDD};
                resL <= resMU2;
                ret();
        end

//-----------------------------------------------------------------------------
// DIVU / DIVS
// - the target register is not updated if overflow occurs.
//-----------------------------------------------------------------------------
DIV1:
        if (s[15:0]==16'd0) begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `DBZ_VEC;
                goto (TRAP3);
        end
        else
                goto (DIV2);
DIV2:
        if (dvdone) begin
                cf <= 1'b0;
                if (dvovf)
                        vf <= 1'b1;
                else begin
                        nf <= divq[15];
                        zf <= divq[15:0]==16'h0000;
                        vf <= 1'b0;
                        Rt <= {1'b0,DDD};
                        resL <= {divr[15:0],divq[15:0]};
                        rfwrL <= 1'b1;
                end
                ret();
        end

//-----------------------------------------------------------------------------
// NOT
//-----------------------------------------------------------------------------
NOT:
        begin
                resB <= ~d[7:0];
                resW <= ~d[15:0];
                resL <= ~d;
                d <= ~d;
                cf <= 1'b0;
                vf <= 1'b0;
                case(sz)
                2'b00:  begin zf <= d[7:0]==8'hFF; nf <= ~d[7]; end
                2'b01:  begin zf <= d[15:0]==16'hFFFF; nf <= ~d[15]; end
                2'b10:  begin zf <= d[31:0]==32'hFFFFFFFF; nf <= ~d[31]; end
                default:        ;
                endcase
                if (mmm==3'b000) begin
                        Rt <= {1'b0,rrr};
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
                else if (mmm==3'b001)
                        ret();
                else begin
                        case(sz)
                        2'b00:  begin goto(STORE_BYTE); end
                        2'b01:  begin goto(STORE_WORD); end
                        2'b10:  begin goto(STORE_LWORD); end
                        default:        ;
                        endcase
                end
        end

//-----------------------------------------------------------------------------
// NEG / NEGX
//-----------------------------------------------------------------------------
NEG:
        begin
                resL <= -d;
                resW <= -d[15:0];
                resB <= -d[7:0];
                d <= -d;
                s <= d;
                dd <= 'd0;
                goto (NEGX1);
        end
NEGX:
        begin
                resL <= -d - xf;
                resW <= -d[15:0] - xf;
                resB <= -d[7:0] - xf;
                d <= -d - xf;
                s <= d + xf;
                dd <= 'd0;
                goto (NEGX1);
        end
NEGX1:
        begin
                case(sz)
                2'b00:  begin cf <= resB[8]; nf <= resB[7]; vf <= fnSubOverflow(resB[7],dd[7],s[7]); zf <= resB[7:0]==8'h00; xf <= resB[8]; end
                2'b01:  begin cf <= resW[16]; nf <= resW[15]; vf <= fnSubOverflow(resW[15],dd[15],s[15]); zf <= resW[15:0]==16'h00; xf <= resW[16]; end
                2'b10:  begin cf <= resL[32]; nf <= resL[31]; vf <= fnSubOverflow(resL[31],dd[31],s[31]); zf <= resL[31:0]==32'h00; xf <= resL[32]; end
                endcase
                if (mmm==3'b000) begin
                        Rt <= {1'b0,rrr};
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
                else if (mmm==3'b001)
                        ret();
                else
                        case(sz)
                        2'b00:  begin goto(STORE_BYTE); end
                        2'b01:  begin goto(STORE_WORD); end
                        2'b10:  begin goto(STORE_LWORD); end
                        default:        ;
                        endcase
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
TAS:
        begin
                resB <= {1'b1,d[6:0]};
                cf <= 1'b0;
                vf <= 1'b0;
                zf <= d[7:0]==8'h00;
                nf <= d[7];
                d <= {1'b1,d[6:0]};
                goto(USTORE_BYTE);
        end

//-----------------------------------------------------------------------------
// Link
//-----------------------------------------------------------------------------
LINK:
        begin
                d <= rfoAn;
                ea <= sp - 4'd4;
                call (STORE_LWORD,LINK1);
        end
LINK1:
        begin
                call(FETCH_IMM16,LINK2);
        end
LINK2:
        begin
                resL <= sp - 32'd4;
                rfwrL <= 1'b1;
                Rt <= {1'b1,rrr};
                sp <= sp + imm - 32'd4;
                ret();          
        end

//-----------------------------------------------------------------------------
// LEA
//-----------------------------------------------------------------------------
LEA:
        begin
                push(LEA2);
                fs_data(mmm,rrr,FETCH_NOP_LWORD,S);
        end
LEA2:
        begin
                Rt <= {1'b1,AAA};
                rfwrL <= 1'b1;
                resL <= ea;
                ret();
        end
        
//-----------------------------------------------------------------------------
// PEA
//-----------------------------------------------------------------------------
PEA1:
        begin
                push(PEA2);
                fs_data(mmm,rrr,FETCH_NOP_LWORD,S);
        end
PEA2:
        begin
                d <= ea;
                ea <= sp - 32'd4;
                call (STORE_LWORD,PEA3);
        end
PEA3:
        begin
                sp <= sp - 32'd4;
                ret();
        end

//-----------------------------------------------------------------------------
// DBRA
//-----------------------------------------------------------------------------
DBRA:
`ifndef OPT_PERF
        if (~takb)
`endif
        begin
                resW <= rfoDnn - 4'd1;
                Rt <= {1'b0,rrr};
                rfwrW <= 1'b1;
                if (rfoDnn[15:0]!=0)
                        pc <= opc + imm;
                ret();
        end
`ifndef OPT_PERF
        else
                ret();
`endif

//-----------------------------------------------------------------------------
// EXG
//-----------------------------------------------------------------------------
EXG1:
        begin
                rfwrL <= 1'b1;
                resL <= s;
                Rt <= rrrr;
                ret();
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
STORE_IN_DEST:
        begin
//              state <= IFETCH;        // In event of bad ir
//              ret();
                resL <= s;
                resW <= s[15:0];
                resB <= s[7:0];
                d <= s;
                case(ir[15:12])
                4'd1:   begin zf <= s[ 7:0]== 8'h00; nf <= s[7]; end
                4'd3:   begin zf <= s[15:0]==16'h00; nf <= s[15]; end
                4'd2:   begin zf <= s[31:0]==32'd0;  nf <= s[31]; end
                default:        ;
                endcase
                cf <= 1'b0;
                vf <= 1'b0;
                case(ir[15:12])
                4'd1:   fs_data(MMM,RRR,STORE_BYTE,D);
                4'd2:   fs_data(MMM,RRR,STORE_LWORD,D);
                4'd3:   fs_data(MMM,RRR,STORE_WORD,D);
                default:        ;       // cant get here
                endcase
        end


//-----------------------------------------------------------------------------
// Compares
//-----------------------------------------------------------------------------
CMP:
        begin
                flag_update <= FU_CMP;
                case(sz)
                2'b00:  resB <= d[ 7:0] - s[ 7:0];
                2'b01:  resW <= d[15:0] - s[15:0];
                2'b10:  resL <= d[31:0] - s[31:0];
                2'b11:  ;
                endcase
                ret();
        end

CMPA:
        begin
                flag_update <= FU_CMP;
                case(ir[8])
                1'b0:   resL <= d[31:0] - {{16{s[15]}},s[15:0]};
                1'b1:   resL <= d[31:0] - s[31:0];
                endcase
                ret();
        end

CMPM:
        begin
                push (CMP);
                case(sz)
                2'd0:   fs_data(3'b011,RRR,FETCH_BYTE,D);
                2'd1:   fs_data(3'b011,RRR,FETCH_WORD,D);
                2'd2:   fs_data(3'b011,RRR,FETCH_LWORD,D);
                default:        ;       // cant get here
                endcase
        end

//-----------------------------------------------------------------------------
// Shifts
// Rotate instructions ROL,ROR do not affect the X flag.
//-----------------------------------------------------------------------------
SHIFT1:
        begin
                vf <= 1'b0;
                case(shift_op)
                3'b010, // ROXL, ROXR
                3'b110: cf <= xf;
                default:
                        begin
                                if (cnt=='d0)
                                        cf <= 1'b0;
                        end
                endcase
                // Extend by a bit for ASL overflow detection.
                resB <= {d[7],d[7:0]};
                resW <= {d[15],d[15:0]};
                resL <= {d[31],d[31:0]};
                state <= SHIFT;
        end
SHIFT:
        if (cnt!='d0) begin
                cnt <= cnt - 2'd1;
                case(shift_op)
                3'b000: // ASR
                        case(sz)
                        2'b00:  begin resB <= {resB[ 7],resB[ 7:1]}; cf <= resB[0]; xf <= resB[0]; end
                        2'b01:  begin resW <= {resW[15],resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        2'b10:  begin resL <= {resL[31],resL[31:1]}; cf <= resL[0]; xf <= resL[0]; end
                        2'b11:  begin resW <= {resW[15],resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        endcase
                3'b001: // LSR
                        case(sz)
                        2'b00:  begin resB <= {1'b0,resB[ 7:1]}; cf <= resB[0]; xf <= resB[0]; end
                        2'b01:  begin resW <= {1'b0,resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        2'b10:  begin resL <= {1'b0,resL[31:1]}; cf <= resL[0]; xf <= resL[0]; end
                        2'b11:  begin resW <= {1'b0,resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        endcase
                3'b010: // ROXR
                        case(sz)
                        2'b00:  begin resB <= {xf,resB[ 7:1]}; cf <= resB[0]; xf <= resB[0]; end
                        2'b01:  begin resW <= {xf,resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        2'b10:  begin resL <= {xf,resL[31:1]}; cf <= resL[0]; xf <= resL[0]; end
                        2'b11:  begin resW <= {xf,resW[15:1]}; cf <= resW[0]; xf <= resW[0]; end
                        endcase
                3'b011: // ROR
                        case(sz)
                        2'b00:  begin resB <= {resB[0],resB[ 7:1]}; cf <= resB[0]; end
                        2'b01:  begin resW <= {resW[0],resW[15:1]}; cf <= resW[0]; end
                        2'b10:  begin resL <= {resL[0],resL[31:1]}; cf <= resL[0]; end
                        2'b11:  begin resW <= {resW[0],resW[15:1]}; cf <= resW[0]; end
                        endcase
                3'b100: // ASL
                        case(sz)
                        2'b00:  begin resB <= {resB[ 7:0],1'b0}; cf <= resB[ 7]; xf <= resB[ 7]; if (resB[ 7] != resB[ 8]) vf <= 1'b1; end
                        2'b01:  begin resW <= {resW[15:0],1'b0}; cf <= resW[15]; xf <= resW[15]; if (resW[15] != resW[16]) vf <= 1'b1; end
                        2'b10:  begin resL <= {resL[31:0],1'b0}; cf <= resL[31]; xf <= resL[31]; if (resL[31] != resL[32]) vf <= 1'b1; end
                        2'b11:  begin resW <= {resW[15:0],1'b0}; cf <= resW[15]; xf <= resW[15]; if (resW[15] != resW[16]) vf <= 1'b1; end
                        endcase
                3'b101: // LSL
                        case(sz)
                        2'b00:  begin resB <= {resB[ 6:0],1'b0}; cf <= resB[ 7]; xf <= resB[ 7]; end
                        2'b01:  begin resW <= {resW[14:0],1'b0}; cf <= resW[15]; xf <= resW[15]; end
                        2'b10:  begin resL <= {resL[30:0],1'b0}; cf <= resL[31]; xf <= resL[31]; end
                        2'b11:  begin resW <= {resW[14:0],1'b0}; cf <= resW[15]; xf <= resW[15]; end
                        endcase
                3'b110: // ROXL
                        case(sz)
                        2'b00:  begin resB <= {resB[ 6:0],xf}; cf <= resB[ 7]; xf <= resB[ 7]; end
                        2'b01:  begin resW <= {resW[14:0],xf}; cf <= resW[15]; xf <= resW[15]; end
                        2'b10:  begin resL <= {resL[30:0],xf}; cf <= resL[31]; xf <= resL[31]; end
                        2'b11:  begin resW <= {resW[14:0],xf}; cf <= resW[15]; xf <= resW[15]; end
                        endcase
                3'b111: // ROL
                        case(sz)
                        2'b00:  begin resB <= {resB[ 6:0],resB[ 7]}; cf <= resB[ 7]; end
                        2'b01:  begin resW <= {resW[14:0],resW[15]}; cf <= resW[15]; end
                        2'b10:  begin resL <= {resL[30:0],resL[31]}; cf <= resL[31]; end
                        2'b11:  begin resW <= {resW[14:0],resW[15]}; cf <= resW[15]; end
                        endcase
                endcase
        end
        else begin
                if (shift_op==3'b100)   // ASL
                        case(sz)
                        2'b00:  if (resB[ 7] != resB[ 8]) vf <= 1'b1;
                        2'b01:  if (resW[15] != resW[16]) vf <= 1'b1;
                        2'b10:  if (resL[31] != resL[32]) vf <= 1'b1;
                        2'b11:  if (resW[15] != resW[16]) vf <= 1'b1;
                        /*
                        2'b00:  vf <= resB[ 7] != d[ 7];
                        2'b01:  vf <= resW[15] != d[15];
                        2'b10:  vf <= resL[31] != d[31];
                        2'b11:  vf <= resW[15] != d[15];
                        */
                        endcase
                case(sz)
                2'b00:  d <= resB;
                2'b01:  d <= resW;
                2'b10:  d <= resL;
                2'b11:  d <= resW;
                endcase
                Rt <= {1'b0,rrr};
                case(sz)
                2'b00:  begin zf <= resB[7:0]== 8'h00; nf <= resB[ 7]; end
                2'b01:  begin zf <= resW[15:0]==16'h00; nf <= resW[15]; end
                2'b10:  begin zf <= resL[31:0]==32'h00; nf <= resL[31]; end
                2'b11:  begin zf <= resW[15:0]==16'h00; nf <= resW[15]; end
                endcase
                case(sz)
                2'b00:  begin rfwrB <= 1'b1; ret(); end
                2'b01:  begin rfwrW <= 1'b1; ret(); end
                2'b10:  begin rfwrL <= 1'b1; ret(); end
                2'b11:  fs_data(mmm,rrr,STORE_WORD,D);  // word operations only if memory operate
                endcase
        end
        
//-----------------------------------------------------------------------------
// ADD / SUB / ADDA / SUBA / ADDX / SUBX
//-----------------------------------------------------------------------------
ADD:
        begin
                flag_update <= FU_ADD;
                if (sz==2'b11) begin
                        Rt <= {1'b1,AAA};
                        if (ir[8]) begin
                                rfwrL <= 1'b1;
                                resL <= d + s;
                        end
                        else begin
                                resW <= d[15:0] + s[15:0];
                                rfwrW <= 1'b1;
                        end
                        d <= d + s;
                        dd <= d;
                        ret();
                end
                else if (ir[8]) begin
                        resB <= d[7:0] + s[7:0];
                        resW <= d[15:0] + s[15:0];
                        resL <= d + s;
                        d <= d + s;
                        dd <= d;
                        if (mmm==3'd0 || mmm==3'd1) begin
                                Rt <= {mmm[0],rrr};
                                case(sz)
                                2'b00:  rfwrB <= 1'b1;
                                2'b01:  rfwrW <= 1'b1;
                                2'b10:  rfwrL <= 1'b1;
                                default:        ;
                                endcase
                                ret();
                        end
                        else begin
                                case(sz)
                                2'b00:  goto(STORE_BYTE);
                                2'b01:  goto(STORE_WORD);
                                2'b10:  goto(STORE_LWORD);
                                default:        ;
                                endcase
                        end
                end
                else begin
                        Rt <= {1'b0,DDD};
                        resB <= d[7:0] + s[7:0];
                        resW <= d[15:0] + s[15:0];
                        resL <= d + s;
                        d <= d + s;
                        dd <= d;
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
SUB:
        begin
                flag_update <= FU_SUB;
                if (sz==2'b11) begin
                        Rt <= {1'b1,AAA};
                        if (ir[8]) begin
                                rfwrL <= 1'b1;
                                resL <= d - s;
                        end
                        else begin
                                resW <= d[15:0] - s[15:0];
                                rfwrW <= 1'b1;
                        end
                        d <= d - s;
                        dd <= d;
                        ret();
                end
                else if (ir[8]) begin
                        resB <= d[7:0] - s[7:0];
                        resW <= d[15:0] - s[15:0];
                        resL <= d - s;
                        d <= d - s;
                        dd <= d;
                        if (mmm==3'd0 || mmm==3'd1) begin
                                Rt <= {mmm[0],rrr};
                                case(sz)
                                2'b00:  rfwrB <= 1'b1;
                                2'b01:  rfwrW <= 1'b1;
                                2'b10:  rfwrL <= 1'b1;
                                default:        ;
                                endcase
                                ret();
                        end
                        else begin
                                case(sz)
                                2'b00:  goto(STORE_BYTE);
                                2'b01:  goto(STORE_WORD);
                                2'b10:  goto(STORE_LWORD);
                                default:        ;
                                endcase
                        end
                end
                else begin
                        Rt <= {1'b0,DDD};
                        resB <= d[7:0] - s[7:0];
                        resW <= d[15:0] - s[15:0];
                        resL <= d - s;
                        dd <= d;
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

ADDX:
        begin
                push (ADDX2);
                case(sz)
                2'd0:   fs_data(3'b100,rrr,FETCH_BYTE,S);
                2'd1:   fs_data(3'b100,rrr,FETCH_WORD,S);
                2'd2:   fs_data(3'b100,rrr,FETCH_LWORD,S);
                default:        ;
                endcase
        end
ADDX2:
        begin
                push(ADDX3);
                case(sz)
                2'd0:   fs_data(3'b100,RRR,FETCH_BYTE,D);
                2'd1:   fs_data(3'b100,RRR,FETCH_WORD,D);
                2'd2:   fs_data(3'b100,RRR,FETCH_LWORD,D);
                default:        ;
                endcase
        end
ADDX3:
        begin
                flag_update <= FU_ADDX;
                resB <= d[ 7:0] + s[ 7:0] + xf;
                resW <= d[15:0] + s[15:0] + xf;
                resL <= d[31:0] + s[31:0] + xf;
                dd <= d;
                d <= d + s + xf;
                if (ir[3])
                        case(sz)
                        2'b00:  goto(STORE_BYTE);
                        2'b01:  goto(STORE_WORD);
                        2'b10:  goto(STORE_LWORD);
                        default:        ;
                        endcase
                else begin
                        Rt <= {1'b0,RRR};
                        case(sz)
                        2'd0:   rfwrB <= 1'b1;
                        2'd1:   rfwrW <= 1'b1;
                        2'd2:   rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

SUBX:
        begin
                push (SUBX2);
                case(sz)
                2'd0:   fs_data(3'b100,rrr,FETCH_BYTE,S);
                2'd1:   fs_data(3'b100,rrr,FETCH_WORD,S);
                2'd2:   fs_data(3'b100,rrr,FETCH_LWORD,S);
                default:        ;
                endcase
        end
SUBX2:
        begin
                push(SUBX3);
                case(sz)
                2'd0:   fs_data(3'b100,RRR,FETCH_BYTE,D);
                2'd1:   fs_data(3'b100,RRR,FETCH_WORD,D);
                2'd2:   fs_data(3'b100,RRR,FETCH_LWORD,D);
                default:        ;
                endcase
        end
SUBX3:
        begin
                flag_update <= FU_SUBX;
                resB <= d[7:0] - s[7:0] - xf;
                resW <= d[15:0] - s[15:0] - xf;
                resL <= d[31:0] - s[31:0] - xf;
                dd <= d;
                d <= d - s - xf;
                if (ir[3])
                        case(sz)
                        2'b00:  goto(STORE_BYTE);
                        2'b01:  goto(STORE_WORD);
                        2'b10:  goto(STORE_LWORD);
                        default:        ;
                        endcase
                else begin
                        Rt <= {1'b0,RRR};
                        case(sz)
                        2'd0:   rfwrB <= 1'b1;
                        2'd1:   rfwrW <= 1'b1;
                        2'd2:   rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
AND:
        begin
                flag_update <= FU_LOGIC;
                if (ir[8]) begin
                        resB <= d[7:0] & rfoDn[7:0];
                        resW <= d[15:0] & rfoDn[15:0];
                        resL <= d & rfoDn;
                        d <= d & rfoDn;
                        if (mmm==3'd0 || mmm==3'd1) begin
                                Rt <= {mmm[0],rrr};
                                case(sz)
                                2'b00:  rfwrB <= 1'b1;
                                2'b01:  rfwrW <= 1'b1;
                                2'b10:  rfwrL <= 1'b1;
                                default:        ;
                                endcase
                                ret();
                        end
                        else begin
                                case(sz)
                                2'b00:  goto(STORE_BYTE);
                                2'b01:  goto(STORE_WORD);
                                2'b10:  goto(STORE_LWORD);
                                default:        ;
                                endcase
                        end
                end
                else begin
                        Rt <= {1'b0,DDD};
                        resB <= rfoDn[7:0] & s[7:0];
                        resW <= rfoDn[15:0] & s[15:0];
                        resL <= rfoDn & s;
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

//-----------------------------------------------------------------------------
// OR
//-----------------------------------------------------------------------------
OR:
        begin
                flag_update <= FU_LOGIC;
                if (ir[8]) begin
                        resB <= d[7:0] | rfoDn[7:0];
                        resW <= d[15:0] | rfoDn[15:0];
                        resL <= d | rfoDn;
                        d <= d | rfoDn;
                        if (mmm==3'd0 || mmm==3'd1) begin
                                Rt <= {mmm[0],rrr};
                                case(sz)
                                2'b00:  rfwrB <= 1'b1;
                                2'b01:  rfwrW <= 1'b1;
                                2'b10:  rfwrL <= 1'b1;
                                default:        ;       // DIV
                                endcase
                                ret();
                        end
                        else begin
                                case(sz)
                                2'b00:  goto(STORE_BYTE);
                                2'b01:  goto(STORE_WORD); 
                                2'b10:  goto(STORE_LWORD);
                                default:        ;       // DIV
                                endcase
                        end
                end
                else begin
                        Rt <= {1'b0,DDD};
                        resB <= rfoDn[7:0] | s[7:0];
                        resW <= rfoDn[15:0] | s[15:0];
                        resL <= rfoDn | s;
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
        end

//-----------------------------------------------------------------------------
// EOR
//-----------------------------------------------------------------------------
EOR:
        begin
                flag_update <= FU_LOGIC;
                resB <= d[7:0] ^ rfoDn[7:0];
                resW <= d[15:0] ^ rfoDn[15:0];
                resL <= d ^ rfoDn;
                d <= d ^ rfoDn;
                if (mmm[2:1]==2'd0) begin
                        Rt <= {mmm[0],rrr};
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        ret();
                end
                else begin
                        case(sz)
                        2'b00:  goto(STORE_BYTE);
                        2'b01:  goto(STORE_WORD);
                        2'b10:  goto(STORE_LWORD);
                        default:        ;
                        endcase
                end
        end

//-----------------------------------------------------------------------------
// ADDQ / SUBQ
// Flags are not updated if the target is an address register.
// If the target is an address register, the entire register is updated.
//-----------------------------------------------------------------------------
ADDQ:
        begin
                if (ir[8]) begin
                        if (mmm!=3'b001)
                                flag_update <= FU_SUBQ;
                        resL <= d - immx;
                        resB <= d[7:0] - immx[7:0];
                        resW <= d[15:0] - immx[15:0];
                        d <= d - immx;
                        dd <= d;
                        s <= immx;
                end
                else begin
                        if (mmm!=3'b001)
                                flag_update <= FU_ADDQ;
                        resL <= d + immx;
                        resB <= d[7:0] + immx[7:0];
                        resW <= d[15:0] + immx[15:0];
                        d <= d + immx;
                        dd <= d;
                        s <= immx;
                end
                if (mmm==3'd0) begin
                        ret();
                        Rt <= {mmm[0],rrr};
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                end
                // If the target is an address register, the entire register is updated.
                else if (mmm==3'b001) begin
                        ret();
                        Rt <= {mmm[0],rrr};
                        rfwrL <= 1'b1;
                end
                else
                        case(sz)
                        2'b00:  goto(STORE_BYTE);
                        2'b01:  goto(STORE_WORD);
                        2'b10:  goto(STORE_LWORD);
                        default:        ;       // Scc / DBRA
                        endcase
        end

//-----------------------------------------------------------------------------
// ADDI / SUBI / CMPI / ANDI / ORI / EORI
//-----------------------------------------------------------------------------
ADDI:
        case(sz)
        2'b00:  call(FETCH_IMM8,ADDI2);
        2'b01:  call(FETCH_IMM16,ADDI2);
        2'b10:  call(FETCH_IMM32,ADDI2);
        default:        tIllegal();
        endcase
ADDI2:
        begin
        immx <= imm;
        case(sz)
        2'b00:  begin push(ADDI3); fs_data(mmm,rrr,FETCH_BYTE,D); end
        2'b01:  begin push(ADDI3); fs_data(mmm,rrr,FETCH_WORD,D); end
        2'b10:  begin push(ADDI3); fs_data(mmm,rrr,FETCH_LWORD,D); end
        default:        ;       // Cant get here
        endcase
        end
ADDI3:
        begin
                flag_update <= FU_ADDI;
                dd <= d;
                s <= immx;
                // Odd numbers are BIT insns.
                case(ir[11:8])
                4'h0:   resL <= d | immx;       // ORI
                4'h2:   resL <= d & immx;       // ANDI
                4'h4:   resL <= d - immx;       // SUBI
                4'h6:   resL <= d + immx;       // ADDI
                4'hA:   resL <= d ^ immx;       // EORI
                4'hC:   resL <= d - immx;       // CMPI
                default:        ;
                endcase
                case(ir[11:8])
                4'h0:   resW <= d[15:0] | immx[15:0];   // ORI
                4'h2:   resW <= d[15:0] & immx[15:0];   // ANDI
                4'h4:   resW <= d[15:0] - immx[15:0];   // SUBI
                4'h6:   resW <= d[15:0] + immx[15:0];   // ADDI
                4'hA:   resW <= d[15:0] ^ immx[15:0];   // EORI
                4'hC:   resW <= d[15:0] - immx[15:0];   // CMPI
                default:        ;
                endcase
                case(ir[11:8])
                4'h0:   resB <= d[7:0] | immx[7:0];     // ORI
                4'h2:   resB <= d[7:0] & immx[7:0];     // ANDI
                4'h4:   resB <= d[7:0] - immx[7:0];     // SUBI
                4'h6:   resB <= d[7:0] + immx[7:0];     // ADDI
                4'hA:   resB <= d[7:0] ^ immx[7:0];     // EORI
                4'hC:   resB <= d[7:0] - immx[7:0];     // CMPI
                default:        ;
                endcase
                case(ir[11:8])
                4'h0:   d <= d | immx;  // ORI
                4'h2:   d <= d & immx;  // ANDI
                4'h4:   d <= d - immx;  // SUBI
                4'h6:   d <= d + immx;  // ADDI
                4'hA:   d <= d ^ immx;  // EORI
                4'hC:   d <= d - immx;  // CMPI
                default:        ;
                endcase
                if (ir[11:8]==4'hC)
                        ret();
                else if (mmm==3'b000 || mmm==3'b001) begin
                        case(sz)
                        2'b00:  rfwrB <= 1'b1;
                        2'b01:  rfwrW <= 1'b1;
                        2'b10:  rfwrL <= 1'b1;
                        default:        ;
                        endcase
                        Rt <= {mmm[0],rrr};
                        ret();
                end
                else
                        case(sz)
                        2'b00:  goto(STORE_BYTE);
                        2'b01:  goto(STORE_WORD);
                        2'b10:  goto(STORE_LWORD);
                        default:        ret();
                        endcase
        end

//-----------------------------------------------------------------------------
// ANDI_CCR / ANDI_SR / EORI_CCR / EORI_SR / ORI_CCR / ORI_SR
//-----------------------------------------------------------------------------
//
ANDI_CCR:
        begin flag_update <= FU_ANDI_CCR; goto(FETCH_IMM8); end
ANDI_SR:
        begin flag_update <= FU_ANDI_SR; goto(FETCH_IMM16); end
ANDI_SRX:
        begin flag_update <= FU_ANDI_SRX; goto(FETCH_IMM32); end
EORI_CCR:
        begin flag_update <= FU_EORI_CCR; goto(FETCH_IMM8); end
EORI_SR:
        begin flag_update <= FU_EORI_SR; goto(FETCH_IMM16); end
EORI_SRX:
        begin flag_update <= FU_EORI_SRX; goto(FETCH_IMM32); end
ORI_CCR:
        begin flag_update <= FU_ORI_CCR; goto(FETCH_IMM8); end
ORI_SR:
        begin flag_update <= FU_ORI_SR; goto(FETCH_IMM16); end
ORI_SRX:
        begin flag_update <= FU_ORI_SRX; goto(FETCH_IMM32); end

//-----------------------------------------------------------------------------
// Bit manipulation
//-----------------------------------------------------------------------------
BIT:
        begin
                mmm_save <= mmm;
                if (ir[11:8]==4'h8) begin
                        call(FETCH_IMM16,BIT1);
                end
                else begin
                        imm <= rfoDn;
                        goto(BIT1);
                end
        end
BIT1:
        begin
                bit2test <= imm;
                if (mmm_save==3'b000) begin     // Dn
                        goto(BIT2);
                        d <= rfob;
                end
                else begin
                        push(BIT2);
                        // This might fetch an immediate
                        // might also alter mmm
                        fs_data(mmm,rrr,FETCH_BYTE,D);
                end
        end
// ToDo: Speed this up by a clock cycle by placing the update in IFETCH.
BIT2:
        begin
                // Targets a data register then the size is 32-bit, test is mod 32.
                if (mmm_save==3'b000)
                        case(sz)
                        2'b00:  // BTST
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b11;
                                        end
                                        else
`endif                                  
                                                zf <= ~d[bit2test[4:0]];
                                        ret();
                                end
                        2'b01:  // BCHG
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b11;
                                                resL <= d ^ (32'd3 << {bit2test[3:0],1'b0});
                                        end
                                        else
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[4:0]];
                                                resL <= d ^  (32'd1 << bit2test[4:0]);
                                        end
                                        rfwrL <= 1'b1;
                                        Rt <= {1'b0,rrr};
                                        ret();
                                end
                        2'b10:  // BCLR
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b11;
                                                resL <= d & ~(32'd3 << {bit2test[3:0],1'b0});
                                        end
                                        else
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[4:0]];
                                                resL <= d & ~(32'd1 << bit2test[4:0]);
                                        end
                                        rfwrL <= 1'b1;
                                        Rt <= {1'b0,rrr};
                                        ret();
                                end
                        2'b11:  // BSET
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[3:0],1'b0} & 4'd3) == 2'b11;
                                                resL <= (d & ~(32'd3 << {bit2test[3:0],1'b0})) | (bit2test[5:4] << {bit2test[3:0],1'b0});
                                        end
                                        else
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[4:0]];
                                                resL <= d |  (32'd1 << bit2test[4:0]);
                                        end
                                        rfwrL <= 1'b1;
                                        Rt <= {1'b0,rrr};
                                        ret();
                                end
                        endcase
                // Target is memory, size is byte, test is mod 8.
                else
                        case(sz)
                        2'b00:  // BTST
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b11;
                                        end
                                        else
`endif                                  
                                                zf <= ~d[bit2test[2:0]];
                                        ret();
                                end
                        2'b01:  // BCHG
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b11;
                                                d <= d ^ (32'd3 << {bit2test[1:0],1'b0});
                                        end
                                        else
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[2:0]];
                                                d <= d ^  (32'd1 << bit2test[2:0]);
                                        end
                                        goto(STORE_BYTE);
                                end
                        2'b10:  // BCLR
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b11;
                                                d <= d & ~(32'd3 << {bit2test[1:0],1'b0});
                                        end
                                        else
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[2:0]];
                                                d <= d & ~(32'd1 << bit2test[2:0]);
                                        end
                                        goto(STORE_BYTE);
                                end
                        2'b11:  // BSET
                                begin
`ifdef SUPPORT_BITPAIRS                                 
                                        if (bit2test[7]) begin
                                                zf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b00;
                                                cf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b01;
                                                nf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b10;
                                                vf <= (d >> {bit2test[1:0],1'b0} & 4'd3) == 2'b11;
                                                d <= (d & ~(32'd3 << {bit2test[1:0],1'b0})) | (bit2test[5:4] << {bit2test[1:0],1'b0});
                                        end
                                        else 
`endif                                  
                                        begin
                                                zf <= ~d[bit2test[2:0]];
                                                d <= d |  (32'd1 << bit2test[2:0]);
                                        end
                                        goto(STORE_BYTE);
                                end
                        endcase
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CHK:
        begin
                if (d[15] || $signed(d[15:0]) > $signed(s[15:0])) begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                        vecno <= `CHK_VEC;
            state <= TRAP3;
                end
                else
                        ret();
        end

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
FETCH_NOP_BYTE,FETCH_NOP_WORD,FETCH_NOP_LWORD:
        ret();

FETCH_BRDISP:
        begin
/*
                if (fnInCache(pc)) begin
                        tFindInCache(pc,disp);
                        goto (FETCH_BRDISP1);
                end
                else
*/              
                if (!cyc_o) begin
                        fc_o <= {sf,2'b10};
                        cyc_o <= 1'b1;
                        stb_o <= 1'b1;
                        sel_o <= 4'b1111;
                        adr_o <= pc;
                end
                else if (ack_i) begin
                        cyc_o <= 1'b0;
                        stb_o <= 1'b0;
                        sel_o <= 4'b00;
                        d <= {16'd0,iri};
                        goto (FETCH_BRDISPa);
                end
        end
FETCH_BRDISPa:
        begin
                // Record 'd' for bsr
`ifdef SUPPORT_B24              
                if (ir[0]) begin
                        d <= pc + {{9{ir[7]}},ir[7:1],d[15:0],1'b0};
                        ea <= pc + {{9{ir[7]}},ir[7:1],d[15:0],1'b0};
                end
                else
`endif          
                        d <= pc + {{16{d[15]}},d[15:0]};
                        ea <= pc + {{16{d[15]}},d[15:0]};
                // Want to point PC to return after displacement, it will be stacked
                if (bsr)
                        pc <= pc + 4'd2;
                // else branch
                else begin
`ifdef SUPPORT_B24                      
                        if (ir[0])
                                pc <= pc + {{9{ir[7]}},ir[7:1],d[15:0],1'b0};
                        else
`endif                  
                                pc <= pc + {{16{d[15]}},d[15:0]};
                end
                ret();
        end

// Fetch 8 bit immediate
//
FETCH_IMM8:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b00;
                imm <= {{24{iri[7]}},iri[7:0]};
                if (ds==D)
                        d <= {{24{iri[7]}},iri[7:0]};
                else
                        s <= {{24{iri[7]}},iri[7:0]};
                goto (FETCH_IMM8a);
        end
FETCH_IMM8a:
        begin
                pc <= pc + 32'd2;
                ret();
        end

// Fetch 16 bit immediate
//
FETCH_IMM16:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b00;
                imm <= {{16{iri[15]}},iri};
                if (ds==D)
                        d <= {{16{iri[15]}},iri};
                else
                        s <= {{16{iri[15]}},iri};
                goto (FETCH_IMM16a);
        end
FETCH_IMM16a:
        begin
                pc <= pc + 32'd2;
                ret();
        end

// Fetch 32 bit immediate
//
FETCH_IMM32:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
                stb_o <= 1'b0;
                sel_o <= 4'b00;
                if (pc[1]) begin
`ifdef BIG_ENDIAN
                        imm[31:16] <= {dat_i[23:16],dat_i[31:24]};
                        if (ds==D)
                                d[31:16] <= {dat_i[23:16],dat_i[31:24]};
                        else
                                s[31:16] <= {dat_i[23:16],dat_i[31:24]};
`else                   
      imm[15:0] <= dat_i[31:16];
      if (ds==D)
        d[15:0] <= dat_i[31:16];
        else
        s[15:0] <= dat_i[31:16];
`endif      
                  goto(FETCH_IMM32a);
                end
                else begin
`ifdef BIG_ENDIAN
                        imm <= rbo(dat_i);
                        if (ds==D)
                                d <= rbo(dat_i);
                        else
                                s <= rbo(dat_i);
`else
      imm <= dat_i;
      if (ds==D)
        d <= dat_i;
      else
        s <= dat_i;
`endif      
                  cyc_o <= 1'b0;
                  goto (FETCH_IMM32b);
                end
        end
FETCH_IMM32a:
        if (!stb_o) begin
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc + 4'd2;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b00;
`ifdef BIG_ENDIAN
                imm[15:0] <= {dat_i[7:0],dat_i[15:8]};
                if (ds==D)
                        d[15:0] <= {dat_i[7:0],dat_i[15:8]};
                else
                        s[15:0] <= {dat_i[7:0],dat_i[15:8]};
`else
                imm[31:16] <= dat_i[15:0];
                if (ds==D)
                        d[31:26] <= dat_i[15:0];
                else
                        s[31:26] <= dat_i[15:0];
`endif
                goto (FETCH_IMM32b);
        end
FETCH_IMM32b:
        begin
                pc <= pc + 32'd4;
                ret();
        end

// Fetch 32 bit displacement
//
FETCH_D32:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
    if (pc[1]) begin
      stb_o <= 1'b0;
      sel_o <= 4'b0000;
`ifdef BIG_ENDIAN
                        disp[31:16] <= {dat_i[23:16],dat_i[31:24]};
`else
      disp[15:0] <= dat_i[31:16];
`endif        
                goto (FETCH_D32a);
                end
                else begin
            cyc_o <= `LOW;
      stb_o <= 1'b0;
      sel_o <= 4'b0000;
`ifdef BIG_ENDIAN
                        disp <= rbo(dat_i);
`else      
      disp <= dat_i;
`endif      
      goto (FETCH_D32b);
                end
        end
FETCH_D32a:
        if (!stb_o) begin
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc + 4'd2;
        end
        else if (ack_i) begin
    cyc_o <= `LOW;
                stb_o <= 1'b0;
                sel_o <= 2'b00;
`ifdef BIG_ENDIAN
                disp[15:0] <= {dat_i[7:0],dat_i[15:8]};
`else           
                disp[31:16] <= dat_i[15:0];
`endif          
                goto (FETCH_D32b);
        end
FETCH_D32b:
        begin
                pc <= pc + 4'd4;
                ea <= ea + disp;
                ret();
        end

// Fetch 16 bit displacement
//
FETCH_D16:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b0;
                disp <= {{16{iri[15]}},iri};
                state <= FETCH_D16a;
        end
FETCH_D16a:
        begin
                pc <= pc + 32'd2;
                ea <= ea + disp;
                ret();
        end

// Fetch index word
//
FETCH_NDX:
        if (!cyc_o) begin
                fc_o <= {sf,2'b10};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= pc;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 2'b00;
                disp <= {{24{iri[7]}},iri[7:0]};
                mmm <= {2'b00,iri[15]}; // to get reg
                rrr <= iri[14:12];
                wl <= iri[11];
                state <= FETCH_NDXa;
        end
FETCH_NDXa:
        begin
                pc <= pc + 32'd2;
                if (wl)
                        ea <= ea + rfob + disp;
                else
                        ea <= ea + {{16{rfob[15]}},rfob[15:0]} + disp;
                ret();
        end

FETCH_BYTE:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= `HIGH;
                stb_o <= `HIGH;
                adr_o <= ea;
                sel_o <= 4'b1111;
        end
        else if (ack_i) begin
                cyc_o <= `LOW;
                stb_o <= `LOW;
                sel_o <= 4'b0000;
                if (ds==D) begin
            case(ea[1:0])
            2'b00:  d <= {{24{dat_i[7]}},dat_i[7:0]};
            2'b01:  d <= {{24{dat_i[15]}},dat_i[15:8]};
            2'b10:  d <= {{24{dat_i[23]}},dat_i[23:16]};
            2'b11:  d <= {{24{dat_i[31]}},dat_i[31:24]};
            default:  ;
            endcase
                end
                else begin
            case(ea[1:0])
      2'b00:  s <= {{24{dat_i[7]}},dat_i[7:0]};
      2'b01:  s <= {{24{dat_i[15]}},dat_i[15:8]};
      2'b10:  s <= {{24{dat_i[23]}},dat_i[23:16]};
      2'b11:  s <= {{24{dat_i[31]}},dat_i[31:24]};
      default:    ;
      endcase
                end
                ret();
        end

// Fetch byte, but hold onto bus
//
LFETCH_BYTE:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                lock_o <= `HIGH;
                cyc_o <= `HIGH;
                stb_o <= `HIGH;
                adr_o <= ea;
                sel_o <= 4'b1111;
        end
        else if (ack_i) begin
                stb_o <= 1'b0;
                sel_o <= 4'b0;
                if (ds==D) begin
      case(ea[1:0])
      2'b00:  d <= {{24{dat_i[7]}},dat_i[7:0]};
      2'b01:  d <= {{24{dat_i[15]}},dat_i[15:8]};
      2'b10:  d <= {{24{dat_i[23]}},dat_i[23:16]};
      2'b11:  d <= {{24{dat_i[31]}},dat_i[31:24]};
      default:    ;
      endcase
    end
    else begin
      case(ea[1:0])
      2'b00:  s <= {{24{dat_i[7]}},dat_i[7:0]};
      2'b01:  s <= {{24{dat_i[15]}},dat_i[15:8]};
      2'b10:  s <= {{24{dat_i[23]}},dat_i[23:16]};
      2'b11:  s <= {{24{dat_i[31]}},dat_i[31:24]};
      default:    ;
      endcase
    end
                ret();
        end

FETCH_WORD:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= `HIGH;
                stb_o <= `HIGH;
                adr_o <= ea;
                sel_o <= 4'b1111;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b00;
`ifdef BIG_ENDIAN
                if (ds==D)
                  d <= ea[1] ? {{16{dat_i[23]}},dat_i[23:16],dat_i[31:24]} : {{16{dat_i[7]}},dat_i[7:0],dat_i[15:8]};
                else
                  s <= ea[1] ? {{16{dat_i[23]}},dat_i[23:16],dat_i[31:24]} : {{16{dat_i[7]}},dat_i[7:0],dat_i[15:8]};
`else
                if (ds==D)
                  d <= ea[1] ? {{16{dat_i[31]}},dat_i[31:16]} : {{16{dat_i[15]}},dat_i[15:0]};
                else
                  s <= ea[1] ? {{16{dat_i[31]}},dat_i[31:16]} : {{16{dat_i[15]}},dat_i[15:0]};
`endif            
                ret();
        end

FETCH_LWORD:
  if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                adr_o <= ea;
                sel_o <= 4'b1111;
        end
        else if (ack_i) begin
                stb_o <= 1'b0;
                sel_o <= 4'b00;
                if (ea[1]) begin
`ifdef BIG_ENDIAN
      if (ds==D)
        d[31:16] <= {dat_i[23:16],dat_i[31:24]};
      else
        s[31:16] <= {dat_i[23:16],dat_i[31:24]};
`else                   
      if (ds==D)
        d[15:0] <= dat_i[31:16];
      else
        s[15:0] <= dat_i[31:16];
`endif          
                goto (FETCH_LWORDa);
    end
    else begin
      cyc_o <= `LOW;
`ifdef BIG_ENDIAN
      if (ds==D)
          d <= rbo(dat_i);
      else
          s <= rbo(dat_i);
`else        
      if (ds==D)
          d <= dat_i;
      else
          s <= dat_i;
`endif            
      ret();
    end
        end
FETCH_LWORDa:
        if (!stb_o) begin
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                adr_o <= adr_o + 32'd2;
                sel_o <= 4'b1111;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 4'b00;
`ifdef BIG_ENDIAN
                if (ds==D)
                        d[15:0] <= {dat_i[7:0],dat_i[15:8]};
                else
                        s[15:0] <= {dat_i[7:0],dat_i[15:8]};
`else           
                if (ds==D)
                        d[31:16] <= dat_i[15:0];
                else
                        s[31:16] <= dat_i[15:0];
`endif                  
                ret();
        end


STORE_BYTE:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                we_o <= 1'b1;
                adr_o <= ea;
                case(ea[1:0])
                2'b00:  sel_o <= 4'b0001;
                2'b01:  sel_o <= 4'b0010;
                2'b10:  sel_o <= 4'b0100;
                2'b11:  sel_o <= 4'b1000;
                endcase
//              dat_o <= {4{resB[7:0]}};
                dat_o <= {4{d[7:0]}};
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                we_o <= 1'b0;
                sel_o <= 4'b0;
                ret();
        end

// Store byte and unlock
//
USTORE_BYTE:
        if (!stb_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                stb_o <= 1'b1;
                we_o <= 1'b1;
                adr_o <= ea;
                case(ea[1:0])
                2'b00:  sel_o <= 4'b0001;
                2'b01:  sel_o <= 4'b0010;
                2'b10:  sel_o <= 4'b0100;
                2'b11:  sel_o <= 4'b1000;
                endcase
//              dat_o <= {4{resB[7:0]}};
                dat_o <= {4{d[7:0]}};
        end
        else if (ack_i) begin
                lock_o <= 1'b0;
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                we_o <= 1'b0;
                sel_o <= 2'b00;
                ret();
        end

STORE_WORD:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                we_o <= 1'b1;
                adr_o <= ea;
                sel_o <= ea[1] ? 4'b1100 : 4'b0011;
`ifdef BIG_ENDIAN
//              dat_o <= {2{resW[7:0],resW[15:8]}};
                dat_o <= {2{d[7:0],d[15:8]}};
`else           
//              dat_o <= {2{resW[15:0]}};
                dat_o <= {2{d[15:0]}};
`endif          
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                we_o <= 1'b0;
                sel_o <= 2'b00;
                ret();
        end
STORE_LWORD:
        if (!cyc_o) begin
                if (use_sfc)
                        fc_o <= sfc[2:0];
                else if (use_dfc)
                        fc_o <= dfc[2:0];
                else
                        fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                we_o <= 1'b1;
                adr_o <= ea;
                sel_o <= ea[1] ? 4'b1100 : 4'b1111;
`ifdef BIG_ENDIAN
//              dat_o <= ea[1] ? {resL[23:16],resL[31:24],resL[7:0],resL[15:8]} : rbo(resL);
                dat_o <= ea[1] ? {d[23:16],d[31:24],d[7:0],d[15:8]} : rbo(d);
`else           
//              dat_o <= ea[1] ? {resL[15:0],resL[31:16]} : resL;
                dat_o <= ea[1] ? {d[15:0],d[31:16]} : d;
`endif          
        end
        else if (ack_i) begin
    if (ea[1]) begin
      stb_o <= 1'b0;
      we_o <= 1'b0;
      sel_o <= 4'b00;
      state <= STORE_LWORDa;
                end
                else begin
            cyc_o <= `LOW;
      stb_o <= 1'b0;
      we_o <= 1'b0;
      sel_o <= 4'b00;
      ret();
                end
        end
STORE_LWORDa:
        if (!stb_o) begin
                stb_o <= 1'b1;
                we_o <= 1'b1;
                adr_o <= adr_o + 32'd2;
                sel_o <= 4'b0011;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                we_o <= 1'b0;
                sel_o <= 4'b0000;
                ret();
        end

//----------------------------------------------------
//----------------------------------------------------
RESET:
  begin
    pc <= `RESET_VECTOR;
    push(IFETCH);
    goto(TRAP);
        end

//----------------------------------------------------
//----------------------------------------------------
TRAP:
  begin
    goto (TRAP3);
    /*
    if (is_nmi)
        vecno <= `NMI_VEC;
    else
    */
    case(1'b1)
    // group 0
    is_rst:
        begin
                is_rst <= 1'b0;
                tf <= 1'b0;
                sf <= 1'b1;
                im <= 3'd7;
                vecno <= `RESET_VEC;
                goto(TRAP6);
        end
    is_adr_err:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `ADDRERR_VEC;
        goto (TRAP3);
        end
    is_bus_err:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `BUSERR_VEC;
        goto (TRAP3);
        end
    // group 1
    is_trace:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `TRACE_VEC;
        goto (TRAP3);
        end
    is_irq:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
        vecno <= `IRQ_VEC + ipl_i;
        im <= ipl_i;
        goto (INTA);
        end
    is_priv:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `PRIV_VEC;
        goto (TRAP3);
        end
    is_illegal:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                vecno <= `ILLEGAL_VEC;
        goto (TRAP3);
        end
    default:
        begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
        vecno <= `TRAP_VEC + ir[3:0];
        end
    endcase
  end
INTA:
  if (!cyc_o) begin
        fc_o <= 3'b111;
    cyc_o <= `HIGH;
    stb_o <= `HIGH;
    sel_o <= 4'b1111;
    adr_o <= {28'hFFFFFFF,ipl_i,1'b0};
  end
  else if (ack_i|err_i|vpa_i) begin
    cyc_o <= `LOW;
    stb_o <= `LOW;
    sel_o <= 4'b0;
    if (err_i)
        vecno <= `SPURIOUS_VEC;
    else if (!vpa_i)
        vecno <= iri[7:0];
    goto (TRAP3);
  end
TRAP3:
        begin
                // If was in user mode, capture stack pointer in usp.
                if (!isr[13]) begin
                        usp <= sp;
                        sp <= ssp;
                end
`ifdef SUPPORT_010
                if (is_bus_err | is_adr_err)
                        goto (TRAP20);
                else
                        goto (TRAP3a);
`else
                goto (TRAP3b);
`endif          
        end
// First 16 words of internal state are stored
TRAP20:
        begin
                sp <= sp - 6'd32;
                goto (TRAP21);
        end
// Next instruction input buffer.
TRAP21:
        begin
                d <= ir;
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                call (STORE_WORD, TRAP22);
        end
TRAP22:
        begin
                d <= dati_buf;
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                call (STORE_LWORD, TRAP23);
        end
TRAP23:
        begin
                d <= dato_buf;
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                call (STORE_LWORD, TRAP24);
        end
// 1 word Unused
TRAP24:
        begin
                sp <= sp - 4'd2;
                goto (TRAP25);
        end
TRAP25:
        begin
                d <= bad_addr;
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                call (STORE_LWORD, TRAP26);
        end
TRAP26:
        begin
                d <= mac_cycle_type;
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                s <= sp - 4'd2;
                call (STORE_WORD, TRAP3a);
        end
// For the 68010 and above push the format word.
TRAP3a:
        begin
`ifdef SUPPORT_010
                if (is_bus_err|is_adr_err)
                        d <= {4'b1000,2'b00,vecno,2'b00};
                else            
                        d <= {4'b0000,2'b00,vecno,2'b00};
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                call (STORE_WORD, TRAP3b);
`else           
                goto (TRAP3b);
`endif          
        end
// Push the program counter
TRAP3b:
        begin
                d <= pc;
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                call (STORE_LWORD, TRAP4);
        end
// And the status register
TRAP4:
        begin
                d <= isr;
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                s <= sp - 4'd2;
`ifdef SUPPORT_010
                call (STORE_WORD, TRAP7);
`else           
                call (STORE_WORD, is_bus_err|is_adr_err?TRAP8:TRAP7);
`endif          
        end
// Push IR
TRAP8:
        begin
                d <= ir;
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                is_bus_err <= 1'b0;
                is_adr_err <= 1'b0;
                call (STORE_WORD, TRAP9);
        end
// Push bad address
TRAP9:
        begin
                d <= bad_addr;
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                call (STORE_LWORD, TRAP10);
        end
TRAP10:
        begin
                d <= mac_cycle_type;
                ea <= sp - 4'd2;
                sp <= sp - 4'd2;
                s <= sp - 4'd2;
                call (STORE_WORD, TRAP7);
        end
// Load SP from vector table
TRAP6:
        begin
                ea <= 'd0;
                ds <= S;
                call (FETCH_LWORD, TRAP7);
        end
// Load PC from vector table.
TRAP7:
        begin
                sp <= s;
                ssp <= s;
                ea <= {vbr[31:2]+vecno,2'b00};
                ds <= S;
                call (FETCH_LWORD, TRAP7a);
        end
TRAP7a:
        begin
                pc <= s;
                ret();
        end

//----------------------------------------------------
//----------------------------------------------------
/*
JMP_VECTOR:
        if (!cyc_o) begin
                fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 2'b11;
                adr_o <= vector;
        end
        else if (ack_i) begin
                stb_o <= 1'b0;
                sel_o <= 2'b00;
                pc[15:0] <= dat_i;
                state <= JMP_VECTOR2;
        end
JMP_VECTOR2:
        if (!stb_o) begin
                fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                sel_o <= 2'b11;
                adr_o <= adr_o + 32'd2;
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                sel_o <= 2'b00;
                pc[31:16] <= dat_i;
                state <= IFETCH;
        end
*/
//----------------------------------------------------
//----------------------------------------------------
UNLNK:
        begin
                ds <= S;
                ea <= sp;
                sp <= sp + 4'd4;
                call (FETCH_LWORD,UNLNK2);
        end
UNLNK2:
        begin
                rfwrL <= 1'b1;
                Rt <= {1'b1,rrr};
                resL <= s;
                ret();
        end

//----------------------------------------------------
// JMP / JSR / BSR
//----------------------------------------------------

JMP:
        begin
                pc <= ea;
                ret();
        end
JSR:
        begin
                ea <= sp - 4'd4;
                sp <= sp - 4'd4;
                d <= pc;
                pc <= ea;
                goto (STORE_LWORD);
        end
/*
        if (!cyc_o) begin
                fc_o <= {sf,2'b01};
                cyc_o <= 1'b1;
                stb_o <= 1'b1;
                we_o <= 1'b1;
                sel_o <= 4'b1111;
                adr_o <= sp - 32'd4;
`ifdef BIG_ENDIAN
                dat_o <= rbo(pc);
`else           
                dat_o <= pc;
`endif          
        end
        else if (ack_i) begin
                cyc_o <= 1'b0;
                stb_o <= 1'b0;
                we_o <= 1'b0;
                sel_o <= 4'b00;
                sp <= sp - 32'd4;
                pc <= d;
`ifdef SUPPORT_TASK             
`ifdef BIG_ENDIAN               
                if (d[24]) begin
                        otr <= tr;
                        tr <= d[29:25];
        reg_copy_mask <= {d[7:0],d[15:8],d[16]};
                        goto (THREAD2);
    end
                else
                        ret();
`else           
                if (d[0]) begin
                        otr <= tr;
                        tr <= d[5:1];
                        reg_copy_mask <= d[31:16];
                        goto (THREAD2);
                end
                else
                        ret();
`endif
`else
                ret();
`endif
        end
*/

//----------------------------------------------------
// RTE / RTR
// Return from exception
//----------------------------------------------------

RTE1:
        begin
                ds <= S;
                ea <= sp;
                sp <= sp + 4'd2;
                call (FETCH_WORD,RTE2);
        end
RTE2:
        begin
                ds <= S;
                ea <= sp;
                sp <= sp + 4'd4;
                cf <= s[0];
                vf <= s[1];
                zf <= s[2];
                nf <= s[3];
                xf <= s[4];
                ccr57 <= s[7:5];
                if (!rtr) begin
                        im[0] <= s[8];
                        im[1] <= s[9];
                        im[2] <= s[10];
                        sr1112 <= s[12:11];
                        sf <= s[13];
                        sr14 <= s[14];
                        tf <= s[15];
                        //pl <= s[31:24];
                end
                call (FETCH_LWORD,RTE3);
        end
RTE3:
        begin
                pc <= s;
`ifdef SUPPORT_010
                ea <= sp;
                sp <= sp + 4'd2;
                if (!rtr)
                        call (FETCH_WORD,RTE4);
                else
                        ret();
`else
                if (!rtr && !sf) begin
                        ssp <= sp;
                        sp <= usp;
                end             
                ret();
`endif          
        end
// The core might have been in supervisor mode already when the exception
// occurred. Reset the working stack pointer accordingly.
`ifdef SUPPORT_010
RTE4:
        begin
                if (s[15:12]==4'b1000) begin
                        ea <= sp;
                        sp <= sp + 4'd2;
                        call(FETCH_WORD,RTE5);
                end
                else begin
                        if (!sf) begin
                                ssp <= sp;
                                sp <= usp;      // switch back to user stack
                        end
                        ret();
                end
        end
RTE5:
        begin
                mac_cycle_type <= s;
                ea <= sp;
                sp <= sp + 4'd4;
                call(FETCH_LWORD,RTE6);
        end
RTE6:
        begin
                bad_addr <= s;
                ea <= sp;
                sp <= sp + 4'd2;
                call(FETCH_WORD,RTE7);
        end
RTE7:
        begin
                ea <= sp;
                sp <= sp + 4'd4;
                call(FETCH_LWORD,RTE8);
        end
RTE8:
        begin
                dato_buf <= s;
                ea <= sp;
                sp <= sp + 4'd4;
                call(FETCH_LWORD,RTE9);
        end
RTE9:
        begin
                dati_buf <= s;
                ea <= sp;
                sp <= sp + 4'd2;
                call(FETCH_WORD,RTE10);
        end
RTE10:
        begin
                ea <= sp;
                sp <= sp + 6'd32;
                goto (RTE11);
        end
RTE11:
        begin
                if (!sf) begin
                        ssp <= sp;
                        sp <= usp;      // switch back to user stack
                end
                ret();
        end
`endif
        
//----------------------------------------------------
// Return from subroutine.
//----------------------------------------------------

RTS1:
        begin
                pc <= s;
                ret();
        end

//----------------------------------------------------
MOVEM_Xn2D:
`ifdef OPT_PERF
        if (imm[15:0]!=16'h0000) begin
                push(MOVEM_Xn2D2);
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,D);
        end
        else
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,D);
`else
        begin
                push(MOVEM_Xn2D2);
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,D);
        end
`endif
MOVEM_Xn2D2:
        begin
                if (imm[15:0]!=16'h0000)
                        state <= MOVEM_Xn2D3;
                else begin
                        case(mmm)
                        3'b100: // -(An)
                                begin
                                        Rt <= {1'b1,rrr};
                                        resL <= ea + (ir[6] ? 32'd4 : 32'd2);
                                        rfwrL <= 1'b1;
                                end
                        endcase
                        ret();
                end
                if (mmm!=3'b100) begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                rrrr <= 4'd0;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd1;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd2;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd3;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd4;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd5;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd6;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd7;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                rrrr <= 4'd8;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                rrrr <= 4'd9;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                rrrr <= 4'd10;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                rrrr <= 4'd11;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                rrrr <= 4'd12;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                rrrr <= 4'd13;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                rrrr <= 4'd14;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                rrrr <= 4'd15;
                        end
                end
                else begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                rrrr <= 4'd15;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd14;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd13;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd12;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd11;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd10;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd9;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd8;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                rrrr <= 4'd7;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                rrrr <= 4'd6;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                rrrr <= 4'd5;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                rrrr <= 4'd4;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                rrrr <= 4'd3;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                rrrr <= 4'd2;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                rrrr <= 4'd1;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                rrrr <= 4'd0;
                        end
                end
        end
MOVEM_Xn2D3:
        begin
                resL <= rfoRnn;
                resW <= rfoRnn[15:0];
                d <= rfoRnn;
                ds <= D;
                call(ir[6] ? STORE_LWORD : STORE_WORD,MOVEM_Xn2D4);
        end
MOVEM_Xn2D4:
        begin
                case(mmm)
                3'b011: ea <= ea + (ir[6] ? 32'd4 : 32'd2);
                3'b100: ea <= ea - (ir[6] ? 32'd4 : 32'd2);
                default:
                        ea <= ea + (ir[6] ? 32'd4 : 32'd2);
                endcase
                if (imm[15:0]!=16'h0000)
                        state <= MOVEM_Xn2D3;
                else begin
                        case(mmm)
                        3'b011:
                                begin
                                        Rt <= {1'b1,rrr};
                                        resL <= ea + (ir[6] ? 32'd4 : 32'd2);
                                        rfwrL <= 1'b1;
                                end
                        3'b100:
                                begin
                                        Rt <= {1'b1,rrr};
                                        resL <= ea;
                                        rfwrL <= 1'b1;
                                end
                        endcase
                        ret();
                end
                if (mmm!=3'b100) begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                rrrr <= 4'd0;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd1;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd2;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd3;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd4;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd5;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd6;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd7;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                rrrr <= 4'd8;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                rrrr <= 4'd9;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                rrrr <= 4'd10;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                rrrr <= 4'd11;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                rrrr <= 4'd12;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                rrrr <= 4'd13;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                rrrr <= 4'd14;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                rrrr <= 4'd15;
                        end
                end
                else begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                rrrr <= 4'd15;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd14;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd13;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd12;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd11;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd10;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd9;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd8;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                rrrr <= 4'd7;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                rrrr <= 4'd6;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                rrrr <= 4'd5;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                rrrr <= 4'd4;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                rrrr <= 4'd3;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                rrrr <= 4'd2;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                rrrr <= 4'd1;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                rrrr <= 4'd0;
                        end
                end
        end
        
//----------------------------------------------------
MOVEM_s2Xn:
`ifdef OPT_PERF
        if (imm[15:0]!=16'h0000) begin
                push(MOVEM_s2Xn2);
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
        end
        else
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
`else
        begin
                push(MOVEM_s2Xn2);
                fs_data(mmm,rrr,ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
        end
`endif
MOVEM_s2Xn2:
        if (imm[15:0] != 16'h0000) begin
                ds <= S;
                call(ir[6] ? FETCH_LWORD : FETCH_WORD,MOVEM_s2Xn3);
        end
        else begin
                case(mmm)
                3'b011: // (An)+
                        begin
                                Rt <= {1'b1,rrr};
                                resL <= ea;
                                rfwrL <= 1'b1;
                        end
                3'b100: // -(An)
                        begin
                                Rt <= {1'b1,rrr};
                                resL <= ea + (ir[6] ? 32'd4 : 32'd2);
                                rfwrL <= 1'b1;
                        end
                endcase
                ret();
        end
MOVEM_s2Xn3:
        begin
                case(mmm)
                3'b011: ea <= ea + (ir[6] ? 32'd4 : 32'd2);
                3'b100: ea <= ea - (ir[6] ? 32'd4 : 32'd2);
                default:
                        ea <= ea + (ir[6] ? 32'd4 : 32'd2);
                endcase
                goto (MOVEM_s2Xn2);
                // Another bizzare gotcha. Word values moved to a data register are sign
                // extended to long-word width.
                rfwrL <= 1'b1;
                if (ir[6])
                        resL <= s;
                else
                        resL <= {{16{s[15]}},s[15:0]};
                if (mmm!=3'b100) begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                Rt <= 4'd0;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                Rt <= 4'd1;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                Rt <= 4'd2;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                Rt <= 4'd3;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                Rt <= 4'd4;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                Rt <= 4'd5;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                Rt <= 4'd6;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                Rt <= 4'd7;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                Rt <= 4'd8;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                Rt <= 4'd9;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                Rt <= 4'd10;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                Rt <= 4'd11;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                Rt <= 4'd12;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                Rt <= 4'd13;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                Rt <= 4'd14;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                Rt <= 4'd15;
                        end
                end
                else begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                Rt <= 4'd15;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                Rt <= 4'd14;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                Rt <= 4'd13;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                Rt <= 4'd12;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                Rt <= 4'd11;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                Rt <= 4'd10;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                Rt <= 4'd9;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                Rt <= 4'd8;
                        end
                        else if (imm[8]) begin
                                imm[8] <= 1'b0;
                                Rt <= 4'd7;
                        end
                        else if (imm[9]) begin
                                imm[9] <= 1'b0;
                                Rt <= 4'd6;
                        end
                        else if (imm[10]) begin
                                imm[10] <= 1'b0;
                                Rt <= 4'd5;
                        end
                        else if (imm[11]) begin
                                imm[11] <= 1'b0;
                                Rt <= 4'd4;
                        end
                        else if (imm[12]) begin
                                imm[12] <= 1'b0;
                                Rt <= 4'd3;
                        end
                        else if (imm[13]) begin
                                imm[13] <= 1'b0;
                                Rt <= 4'd2;
                        end
                        else if (imm[14]) begin
                                imm[14] <= 1'b0;
                                Rt <= 4'd1;
                        end
                        else if (imm[15]) begin
                                imm[15] <= 1'b0;
                                Rt <= 4'd0;
                        end
                end
        end
//----------------------------------------------------
RETSTATE:
        ret();

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
MOVEP:
        if (!cyc_o) begin
                cyc_o <= `HIGH;
                stb_o <= `HIGH;
                we_o <= ir[7];
                casez({ir[7],ea[1:0]})
                3'b0??: sel_o <= 4'b1111;
                3'b100: sel_o <= 4'b0001;
                3'b101: sel_o <= 4'b0010;
                3'b110: sel_o <= 4'b0100;
                3'b111: sel_o <= 4'b1000;
                endcase
                adr_o <= ea;
                if (ir[6])
                        dat_o <= {4{rfoDn[31:24]}};
                else
                        dat_o <= {4{rfoDn[15:8]}};
        end
        else if (ack_i) begin
                stb_o <= `LOW;
                if (ir[6])
                        resL[31:24] <= dat_i >> {ea[1:0],3'b0};
                else
                        resW[15:8] <= dat_i >> {ea[1:0],3'b0};
                goto (MOVEP1);
        end
MOVEP1:
        if (!stb_o) begin
                stb_o <= `HIGH;
                we_o <= ir[7];
                casez({ir[7],~ea[1],ea[0]})
                3'b0??: sel_o <= 4'b1111;
                3'b100: sel_o <= 4'b0001;
                3'b101: sel_o <= 4'b0010;
                3'b110: sel_o <= 4'b0100;
                3'b111: sel_o <= 4'b1000;
                endcase
                adr_o <= ea + 4'd2;
                if (ir[6])
                        dat_o <= {4{rfoDn[23:16]}};
                else
                        dat_o <= {4{rfoDn[7:0]}};
        end
        else if (ack_i) begin
                stb_o <= `LOW;
                if (ir[6])
                        resL[23:16] <= dat_i >> {ea[1:0]+4'd2,3'b0};
                else
                        resW[7:0] <= dat_i >> {ea[1:0]+4'd2,3'b0};
                Rt <= {1'b0,DDD};
                if (ir[6])
                        goto (MOVEP2);
                else begin
                        cyc_o <= `LOW;
                        we_o <= `LOW;
                        sel_o <= 4'h0;
                        rfwrW <= ~ir[7];
                        ret();
                end
        end
MOVEP2:
        if (!stb_o) begin
                stb_o <= `HIGH;
                we_o <= ir[7];
                casez({ir[7],ea[1:0]})
                3'b0??: sel_o <= 4'b1111;
                3'b100: sel_o <= 4'b0001;
                3'b101: sel_o <= 4'b0010;
                3'b110: sel_o <= 4'b0100;
                3'b111: sel_o <= 4'b1000;
                endcase
                adr_o <= ea + 4'd4;
                dat_o <= {4{rfoDn[15:8]}};
        end
        else if (ack_i) begin
                stb_o <= `LOW;
                resL[15:8] <= dat_i >> {ea[1:0],3'b0};
                goto (MOVEP3);
        end
MOVEP3:
        if (!stb_o) begin
                stb_o <= `HIGH;
                we_o <= ir[7];
                casez({ir[7],~ea[1],ea[0]})
                3'b0??: sel_o <= 4'b1111;
                3'b100: sel_o <= 4'b0001;
                3'b101: sel_o <= 4'b0010;
                3'b110: sel_o <= 4'b0100;
                3'b111: sel_o <= 4'b1000;
                endcase
                adr_o <= ea + 4'd6;
                dat_o <= {4{rfoDn[7:0]}};
        end
        else if (ack_i) begin
                cyc_o <= `LOW;
                stb_o <= `LOW;
                we_o <= `LOW;
                sel_o <= 4'h0;
                resL[7:0] <= dat_i >> {ea[1:0]+4'd2,3'b0};
                Rt <= {1'b0,DDD};
                rfwrL <= ~ir[7];
                ret();
        end


FSDATA2:
        fs_data2(mmmx,rrrx,sz_state,dsix);

// On a retry, wait some random number of cycle before retrying the bus
// operation.
`ifdef SUPPORT_RETRY
RETRY:
        begin
                cnt <= {lfsr_o[3:0] + 4'd8};
                goto (RETRY2);
        end
RETRY2:
        begin
                cnt <= cnt - 2'd1;
                if (cnt=='d0)
                        goto (rstate);
        end
`endif

MOVERn2Rc:
        begin
                rrrr <= imm[15:12];
                goto (MOVERn2Rc2);
        end
MOVERn2Rc2:
        case(imm[11:0])
        12'h000:        begin sfc <= rfoRnn; ret(); end
        12'h001:        begin dfc <= rfoRnn; ret(); end
        12'h003:  begin asid <= rfoRnn[7:0]; ret(); end
        12'h010:  begin apc <= rfoRnn; ret(); end
        12'h011:  begin cpl <= rfoRnn[7:0]; ret(); end
        12'h012:  begin tr <= rfoRnn; ret(); end
        12'h013:  begin tcba <= rfoRnn; ret(); end
        12'h014:        begin mmus <= rfoRnn; ret(); end
        12'h015:        begin ios <= rfoRnn; ret(); end
        12'h016:        begin iops <= rfoRnn; ret(); end
        12'h800:        begin usp <= rfoRnn; ret(); end
        12'h801:        begin vbr <= rfoRnn; ret(); end
/*      
        12'hFE1:
                begin
                        cf <= rfoRnn[0];
                        vf <= rfoRnn[1];
                        zf <= rfoRnn[2];
                        nf <= rfoRnn[3];
                        xf <= rfoRnn[4];
                        ccr57 <= rfoRnn[7:5];
                        if (!rtr) begin
                                im[0] <= rfoRnn[8];
                                im[1] <= rfoRnn[9];
                                im[2] <= rfoRnn[10];
                                sr1112 <= rfoRnn[12:11];
                                sf <= rfoRnn[13];
                                sr14 <= rfoRnn[14];
                                tf <= rfoRnn[15];
                                //pl <= rfoRnn[31:24];
                        end
//                      tr <= rfoRnn[23:16];
//                      pl <= rfoRnn[31:24];
                end
*/              
        default:        tIllegal();
        endcase
MOVERc2Rn:
        case(imm[11:0])
        12'h000:        begin resL <= sfc; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h001:        begin resL <= dfc; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h003:  begin resL <= {24'h0,asid}; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h010:  begin resL <= apc; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h011:  begin resL <= {24'h0,cpl}; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h012:  begin resL <= tr; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h013:  begin resL <= tcba; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h014:  begin resL <= mmus; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h015:  begin resL <= ios; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h016:  begin resL <= iops; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h800:        begin resL <= usp; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'h801:        begin resL <= vbr; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'hFE0:        begin resL <= coreno_i; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
//      12'hFE1:        begin resL <= srx; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'hFF0:        begin resL <= tick; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        12'hFF8:        begin resL <= icnt; Rt <= imm[15:12]; rfwrL <= 1'b1; ret(); end
        default:        tIllegal();
        endcase

BIN2BCD1:
        goto (BIN2BCD2);
BIN2BCD2:
        if (dd32done) begin
                zf <= dd32in==32'h0;
                vf <= dd32out[39:32]!=8'h00;
                resL <= dd32out[31:0];
                rfwrL <= 1'b1;
                Rt <= {1'b0,rrr};
                ret();
        end
BCD2BIN1:
        begin
                (* USE_DSP = "no" *)
                resL1 <= d[3:0] +
                     d[7:4] * 4'd10 +
                     d[11:8] * 7'd100 +
                     d[15:12] * 10'd1000 +
                     d[19:16] * 14'd10000 +
                     d[23:20] * 17'd100000 +
                     d[27:24] * 20'd1000000 +
                     d[31:28] * 24'd10000000
                     ;
                goto (BCD2BIN2);
        end
BCD2BIN2:
        begin
                resL2 <= resL1;
                goto (BCD2BIN3);
        end
BCD2BIN3:
        begin
                resL <= resL2;
                rfwrL <= 1'b1;
                Rt <= {1'b0,rrr};
                ret();
        end
default:
        goto(RESET);
endcase

        // Bus error: abort current cycle and trap.
        if (cyc_o & err_i) begin
                cyc_o <= `LOW;
                stb_o <= `LOW;
                we_o <= `LOW;
                sel_o <= 4'h0;
                mac_cycle_type <= {state[6:0],sel_o,~we_o,1'b0,fc_o};
                bad_addr <= adr_o;
                if (state != INTA) begin
                        is_bus_err <= 1'b1;
                        dati_buf <= dat_i;
                        dato_buf <= dat_o;
                        goto (TRAP);
                end
        end

`ifdef SUPPORT_RETRY
        // Retry: abort current cycle and retry.
        if (cyc_o & rty_i) begin
                cyc_o <= `LOW;
                stb_o <= `LOW;
                we_o <= `LOW;
                sel_o <= 4'h0;
                rstate <= state;
                goto (RETRY);
        end
`endif

end
        
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
task fs_data;
input [2:0] mmm;
input [2:0] rrr;
input state_t size_state;
input dsi;
begin
        ds <= dsi;
        case(mmm)
        3'd0:   begin
                                if (dsi==D)
                                        d <= MMMRRR ? (mmm[0] ? rfoAna : rfoDn) : rfob;
                                else
                                        s <= MMMRRR ? (mmm[0] ? rfoAna : rfoDn) : rfob;
                                case(size_state)
                                STORE_LWORD:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrL <= 1'b1;
                                        end
                                STORE_WORD:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrW <= 1'b1;
                                        end
                                STORE_BYTE:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrB <= 1'b1;
                                        end
                                default:        ;
                                endcase
                                goto(RETSTATE);
                        end     // Dn
        3'd1:   begin
                                if (dsi==D)
                                        d <= rfob;
                                else
                                        s <= rfob;
                                case(size_state)
                                STORE_LWORD:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrL <= 1'b1;
                                        end
                                STORE_WORD:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrW <= 1'b1;
                                        end
                                STORE_BYTE:
                                        begin
                                                Rt <= {mmm[0],rrr};
                                                rfwrB <= 1'b1;
                                        end
                                default:        ;
                                endcase
                                goto(RETSTATE);
                                end     // An
        3'd2:   begin   //(An)
                                ea <= MMMRRR ? rfoAna : rfoAn;
                                goto(size_state);
                        end
        3'd3:   begin   // (An)+
                                ea <= (MMMRRR ? rfoAna : rfoAn);
                                if (!lea) begin
                                        Rt <= {1'b1,rrr};
                                        rfwrL <= 1'b1;
                                end                     
                                case(size_state)
                                LFETCH_BYTE,FETCH_BYTE,STORE_BYTE,USTORE_BYTE:  resL <= (MMMRRR ? rfoAna : rfoAn) + 4'd1;
                                FETCH_WORD,STORE_WORD:  resL <= (MMMRRR ? rfoAna : rfoAn) + 4'd2;
                                FETCH_LWORD,STORE_LWORD:        resL <= (MMMRRR ? rfoAna : rfoAn) + 4'd4;
                                default:        ;
                                endcase
                                goto(size_state);
                        end
        3'd4:   begin   // -(An)
                                if (!lea) begin
                                        Rt <= {1'b1,rrr};
                                        rfwrL <= 1'b1;
                                end
                                case(size_state)
                                FETCH_NOP_BYTE,LFETCH_BYTE,FETCH_BYTE,STORE_BYTE,USTORE_BYTE:   ea <= (MMMRRR ? rfoAna : rfoAn) - 4'd1;
                                FETCH_NOP_WORD,FETCH_WORD,STORE_WORD:   ea <= (MMMRRR ? rfoAna : rfoAn) - 4'd2;
                                FETCH_NOP_LWORD,FETCH_LWORD,STORE_LWORD:        ea <= (MMMRRR ? rfoAna : rfoAn) - 4'd4;
                                default:        ;
                                endcase
                                case(size_state)
                                LFETCH_BYTE,FETCH_BYTE,STORE_BYTE,USTORE_BYTE:  resL <= (MMMRRR ? rfoAna : rfoAn) - 4'd1;
                                FETCH_WORD,STORE_WORD:  resL <= (MMMRRR ? rfoAna : rfoAn) - 4'd2;
                                FETCH_LWORD,STORE_LWORD:        resL <= (MMMRRR ? rfoAna : rfoAn) - 4'd4;
                                default:        ;
                                endcase
                                goto(size_state);
                        end
        3'd5:   begin   // d16(An)
                                ea <= (MMMRRR ? rfoAna : rfoAn);
                                mmmx <= mmm;
                                rrrx <= rrr;
                                sz_state <= size_state;
                                dsix <= dsi;
                                goto (FSDATA2);
                        end
        3'd6:   begin   // d8(An,Xn)
                                ea <= (MMMRRR ? rfoAna : rfoAn);
                                mmmx <= mmm;
                                rrrx <= rrr;
                                sz_state <= size_state;
                                dsix <= dsi;
                                goto (FSDATA2);
                        end
        3'd7:   begin
                                case(rrr)
                                3'd0:   begin   // abs short
                                                        ea <= 32'd0;
                                                        mmmx <= mmm;
                                                        rrrx <= rrr;
                                                        sz_state <= size_state;
                                                        dsix <= dsi;
                                                        goto (FSDATA2);
                                                end
                                3'd1:   begin   // abs long
                                                        ea <= 32'd0;
                                                        mmmx <= mmm;
                                                        rrrx <= rrr;
                                                        sz_state <= size_state;
                                                        dsix <= dsi;
                                                        goto (FSDATA2);
                                                end
                                3'd2:   begin   // d16(PC)
                                                        ea <= pc;
                                                        mmmx <= mmm;
                                                        rrrx <= rrr;
                                                        sz_state <= size_state;
                                                        dsix <= dsi;
                                                        goto (FSDATA2);
                                                end
                                3'd3:   begin   // d8(PC,Xn)
                                                        ea <= pc;
                                                        mmmx <= mmm;
                                                        rrrx <= rrr;
                                                        sz_state <= size_state;
                                                        dsix <= dsi;
                                                        goto (FSDATA2);
                                                end
                                3'd4:   begin   // #i16
                                                        goto((size_state==FETCH_LWORD||size_state==FETCH_NOP_LWORD)?FETCH_IMM32:FETCH_IMM16);
                                                end
                                3'd5:   begin   // #i32
                                                        state <= FETCH_IMM32;
                                                        goto (FETCH_IMM32);
                                                end
                                endcase
                        end
                endcase
        end
endtask

task fs_data2;
input [2:0] mmm;
input [2:0] rrr;
input state_t size_state;
input dsi;
begin
        ds <= dsi;
        case(mmm)
        3'd5:   begin   // d16(An)
                                ea <= (MMMRRR ? rfoAna : rfoAn);
                                call(FETCH_D16,size_state);
                        end
        3'd6:   begin   // d8(An,Xn)
                                ea <= (MMMRRR ? rfoAna : rfoAn);
                                call(FETCH_NDX,size_state);
                        end
        3'd7:   begin
                                case(rrr)
                                3'd0:   begin   // abs short
                                                        ea <= 32'd0;
                                                        call(FETCH_D16,size_state);
                                                end
                                3'd1:   begin   // abs long
                                                        ea <= 32'd0;
                                                        call(FETCH_D32,size_state);
                                                end
                                3'd2:   begin   // d16(PC)
                                                        ea <= pc;
                                                        call(FETCH_D16,size_state);
                                                end
                                3'd3:   begin   // d8(PC,Xn)
                                                        ea <= pc;
                                                        call(FETCH_NDX,size_state);
                                                end
                                3'd4:   begin   // #i16
                                                        goto((size_state==FETCH_LWORD||size_state==FETCH_NOP_LWORD)?FETCH_IMM32:FETCH_IMM16);
                                                        end
                                3'd5:   begin   // #i32
                                                        state <= FETCH_IMM32;
                                                        goto (FETCH_IMM32);
                                                end
                                endcase
                        end
                endcase
        end
endtask

task goto;
input state_t nst;
begin
        state <= nst;
end
endtask

task gosub;
input state_t tgt;
begin
        state_stk1 <= state;
        state_stk2 <= state_stk1;
        state_stk3 <= state_stk2;
        state_stk4 <= state_stk3;
        state <= tgt;
end
endtask

task call;
input state_t tgt;
input state_t retst;
begin
        state_stk1 <= retst;
        state_stk2 <= state_stk1;
        state_stk3 <= state_stk2;
        state_stk4 <= state_stk3;
        state <= tgt;
end
endtask

task push;
input state_t st;
begin
        state_stk1 <= st;
        state_stk2 <= state_stk1;
        state_stk3 <= state_stk2;
        state_stk4 <= state_stk3;
end
endtask

task tIllegal;
begin
        is_illegal <= 1'b1;
  vecno <= `ILLEGAL_VEC;
  goto (TRAP);
end
endtask

task tPrivilegeViolation;
begin
        is_priv <= 1'b1;
        vecno <= `PRIV_VEC;
        goto (TRAP);
end
endtask

task tBadBranchDisp;
begin
        isr <= srx;
        tf <= 1'b0;
        sf <= 1'b1;
        vecno <= `DISP_VEC;
        goto (TRAP3);
end
endtask

// MMMRRR needs to be set already when the STORE_IN_DEST state is entered.
// This state is entered after being popped off the state stack.
// If about to fetch the next instruction and trace is enabled, then take the
// trace trap.
task ret;
begin
        if (state_stk1==STORE_IN_DEST ||
                        state_stk1==ADDX2 ||    
                        state_stk1==SUBX2 ||
                        state_stk1==BCD0 ||
                        state_stk1==CMPM)
                MMMRRR <= 1'b1;
        if (state_stk1==IFETCH && tf) begin
                is_trace <= 1'b1;
                state <= TRAP;
        end
        else
                state <= state_stk1;
        state_stk1 <= state_stk2;
        state_stk2 <= state_stk3;
        state_stk3 <= state_stk4;
end
endtask

endmodule

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.