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

Subversion Repositories rf68000

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

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 SUPPORT_DECFLT 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,
        
        // 150
        INT3,
        INT4,

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

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

        MOVES,
        MOVES2,
        
        // 180
        MOVES3,

        ADDX,
        ADDX2,
        ADDX3,
        SUBX,
        SUBX2,
        SUBX3,

        MULU1,
        MULU2,
        MULU3,

        //190   
        MULS1,
        MULS2,
        MULS3,
        
        BIN2BCD1,
        BIN2BCD2,
        BCD2BIN1,
        BCD2BIN2,
        BCD2BIN3,

        IFETCH2,
        FADD,

        // 200
        FCMP,
        FMUL1,
        FMUL2,
        FDIV1,
        FDIV2,
        FNEG,
        FMOVE,
        I2DF1,
        I2DF2,
        DF2I1,
        DF2I2,
        FTST,
        FBCC,
        FSCALE,
        FCOPYEXP,

        FETCH_HEXI1,
        FETCH_HEXI2,
        FETCH_HEXI3,
        FETCH_HEXI4,
        FETCH_NOP_HEXI,
        STORE_HEXI1,
        STORE_HEXI2,
        STORE_HEXI3,
        STORE_HEXI4,

        FMOVEM1,

        FETCH_IMM96,
        FETCH_IMM96b,
        FETCH_IMM96c,
        FETCH_IMM96d,
        
        CCHK,
        
        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;

wire DECFLT = coreno_i==32'd2;

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 state_stk5;
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 [95:0] fp0 = 'd0;
reg [95:0] fp1 = 'd0;
reg [95:0] fp2 = 'd0;
reg [95:0] fp3 = 'd0;
reg [95:0] fp4 = 'd0;
reg [95:0] fp5 = 'd0;
reg [95:0] fp6 = 'd0;
reg [95: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 fnf,fzf,fvf,fnanf;
wire finff = fvf;
reg [7:0] quotient_bits;
reg [2:0] quotient_bitshi;
reg [7:0] fpexc,fpaexc;
wire [31:0] fpsr = {1'b0,quotient_bitshi,fnf,fzf,fvf,fnanf,quotient_bits,fpexc,fpaexc};
reg [31:0] isr;
reg [3:0] ifmt;
reg [7:0] fpcnt;
reg [31:0] pc;
reg [31:0] opc;                 // pc for branch references
reg [31:0] fpiar;
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 [2:0] FLTSRC;
reg [2:0] FLTDST;
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
reg [95:0] rfoFpdst, rfoFpsrc;
`ifdef SUPPORT_DECFLT
always_comb
case(FLTDST)
3'd0:   rfoFpdst <= fp0;
3'd1:   rfoFpdst <= fp1;
3'd2:   rfoFpdst <= fp2;
3'd3:   rfoFpdst <= fp3;
3'd4:   rfoFpdst <= fp4;
3'd5:   rfoFpdst <= fp5;
3'd6:   rfoFpdst <= fp6;
3'd7:   rfoFpdst <= fp7;
endcase
always_comb
case(FLTSRC)
3'd0:   rfoFpsrc <= fp0;
3'd1:   rfoFpsrc <= fp1;
3'd2:   rfoFpsrc <= fp2;
3'd3:   rfoFpsrc <= fp3;
3'd4:   rfoFpsrc <= fp4;
3'd5:   rfoFpsrc <= fp5;
3'd6:   rfoFpsrc <= fp6;
3'd7:   rfoFpsrc <= fp7;
endcase
`endif
//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 rfwrF;
reg takb, ftakb;
reg [8:0] resB;
reg [16:0] resW;
reg [32:0] resL;
reg [95:0] resF;
reg [95:0] fps, fpd;
(* 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 fsub,fabs;
reg bcdsub, bcdneg;
reg fmovem;
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;
reg [31:0] canary;
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()
);

wire [95:0] dfaddsubo, dfmulo, dfdivo, i2dfo, df2io;
wire [95:0] dfscaleo;
wire dfmulinf;
wire dfmuldone, dfmulover, dfmulunder;
wire dfdivdone, dfdivover, dfdivunder;
wire [11:0] dfcmpo;
wire i2dfdone, df2idone;
wire df2iover;
//DFP96U fpsu, fpdu;
//DFP96 fpdp;

`ifdef SUPPORT_DECFLT

/*
assign fpdu.infinity = fpsu.infinity;
assign fpdu.nan = fpsu.nan;
assign fpdu.snan = fpsu.snan;
assign fpdu.qnan = fpsu.qnan;
assign fpdu.sign = fpsu.sign;
assign fpdu.exp = fpsu.exp;
assign fpdu.sig = {4'h1,24{4'h0}};

DFPPack upack1
(
        .i(fpdu),
        .o(fpdp)
);

DFPUnpack uunpack1
(
        .i(fps),
        .o(fpsu)
);
*/

DFPAddsub96nr ufaddsub1
(
        .clk(clk_g),
        .ce(1'b1),
        .rm(3'b0),
        .op(fsub),
        .a(fpd),
        .b(fps),
        .o(dfaddsubo)
);

DFPMultiply96nr udfmul1
(
        .clk(clk_g),
        .ce(1'b1),
        .ld(state==FMUL1),
        .a(fpd),
        .b(fps),
        .o(dfmulo),
        .rm(3'b000),
        .sign_exe(),
        .inf(dfmulinf),
        .overflow(dfmulover),
        .underflow(dfmulunder),
        .done(dfmuldone)
);

DFPDivide96nr udfdiv1
(
        .rst(rst_i),
        .clk(clk_g),
        .ce(1'b1),
        .ld(state==FDIV1),
        .op(1'b0),
        .a(fpd),
        .b(fps),
        .o(dfdivo),
        .rm(3'b000),
        .done(dfdivdone),
        .sign_exe(),
        .inf(),
        .overflow(dfdivover),
        .underflow(dfdivunder)
);

DFPCompare96 udfcmp1
(
        .a(fpd),
        .b(fps),
        .o(dfcmpo)
);

i2df96 ui2df1
(
        .rst(rst_i),
        .clk(clk_g),
        .ce(1'b1),
        .ld(state==I2DF1),
        .op(1'b0),      // 0=unsigned, 1= signed
        .rm(3'b000),
        .i(fps),
        .o(i2dfo),
        .done(i2dfdone)
);

df96Toi udf2i1 (
        .rst(rst_i),
        .clk(clk_g),
        .ce(1'b1),
        .ld(state==DF2I1),
        .op(1'b0),
        .i(fps),
        .o(df2io),
        .overflow(df2iover),
        .done(df2idone)
);

DFPScaleb96 udfscale1
(
        .clk(clk_g),
        .ce(1'b1),
        .a(fpd),
        .b(s),
        .o(dfscaleo)
);

`endif

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 SUPPORT_DECFLT
always_comb
case(ir[5:0])
6'b000001:      ftakb =  fzf;   // EQ
6'b001110:      ftakb = !fzf;   // NE
6'b010010:      ftakb = !fnanf && !fzf && !fvf && !fnf; // GT
6'b011101:      ftakb = fnanf || fzf || fnf;    // NGT
6'b010011:      ftakb = fzf || (!fnanf && !fvf && !fnf);        // GE
6'b011100:      ftakb = fnanf || (fnf && !fzf);         // NGE
6'b010100:      ftakb = fnf && (!fnanf && !fvf && !fzf);        // LT
6'b011011:      ftakb = fnanf || (fzf || !fnf); // NLT
6'b010101:      ftakb = fzf || (fnf && !fnanf); // LE
6'b011010:      ftakb = fnanf || (!fnf && !fvf && !fzf);        // NLE
6'b010110:      ftakb = !fnanf && !fvf && !fzf; // GL
6'b011001:      ftakb = fnanf || fzf;   // NGL
6'b010111:      ftakb = !fnanf; // GLE
6'b011000:      ftakb = fnanf;  // NGLE

6'b000010:      ftakb = !fnanf && !fzf && !fvf && !fnf; // OGT
6'b001101:      ftakb = fnanf || fzf || fnf;    // ULE
6'b000011:      ftakb = fzf || (!fnanf && !fvf && !fnf);        // OGE
6'b001100:      ftakb = fnanf || (fnf && !fzf); // ULT
6'b000100:      ftakb = fnf && (!fnanf && !fvf && !fzf);        // OLT
6'b001011:      ftakb = fnanf || fzf || fnf;    // UGE
6'b000101:      ftakb = fzf || (fnf && !fnanf); // OLE
6'b001010:      ftakb = fnanf || (!fnf && !fvf && !fzf); // UGT
6'b000110:      ftakb = !fnanf && !fvf && !fzf; // OGL
6'b001001:      ftakb = fnanf || fzf;   // UEQ
6'b000111:      ftakb = !fnanf;
6'b001000:      ftakb = fnanf;

6'b000000:      ftakb = 1'b0;   // F
6'b001111:      ftakb = 1'b1;   // T
6'b010000:      ftakb = 1'b0;   // SF
6'b011111:      ftakb = 1'b1;   // ST
6'b010001:      ftakb = fzf;    // SEQ
6'b011110:      ftakb = !fzf;   // SNE
endcase
`endif

`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;
        rfwrF <= 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;
        fnanf <= 1'b0;
        fzf <= 1'b0;
        fnf <= 1'b0;
        fvf <= 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;
        fsub <= 1'b0;
        fabs <= 1'b0;
        bcdsub <= 1'b0;
        bcdneg <= 1'b0;
        fmovem <= 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;
        canary <= 'd0;
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;
rfwrF <= 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
`ifdef SUPPORT_DECFLT  
 if (rfwrF && DECFLT)
        case(Rt)
        4'd0:   fp0 <= resF;
        4'd1:   fp1 <= resF;
        4'd2:   fp2 <= resF;
        4'd3:   fp3 <= resF;
        4'd4:   fp4 <= resF;
        4'd5:   fp5 <= resF;
        4'd6:   fp6 <= resF;
        4'd7:   fp7 <= resF;
        default:        ;
        endcase
`endif

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;
                fsub <= 1'b0;
                fabs <= 1'b0;
                bcdsub <= 1'b0;
                bcdneg <= 1'b0;
                fmovem <= 1'b0;
                is_illegal <= 1'b0;
                use_sfc <= 1'b0;
                use_dfc <= 1'b0;
                fpcnt <= 'd0;
                fpiar <= pc;
                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;
                ext_ir <= 1'b1;
                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;
                FLTSRC <= iri[12:10];
                FLTDST <= iri[ 9: 7];
                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;
                                resB <= 'd0;
                                resW <= 'd0;
                                resL <= '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:
        if (ir[11:9]==3'b001)
                        if (ir[8:7]==2'b01) begin
                                if (ir[6])
                                        call(FETCH_IMM32,FBCC);
                                else
                                        call(FETCH_IMM16,FBCC);
                        end
                        else
                        goto (IFETCH2);
                else 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
                                16'h0003:
                                        begin
                                                push(CCHK);
                                                fs_data(mmm,rrr,FETCH_LWORD,S);
                                        end
                                default:        tIllegal();
                                endcase
                        end
                        else
                                tIllegal();
                end
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
`ifdef SUPPORT_DECFLT
        5'h1F:
                begin
                        ext_ir <= 1'b0;
                        if (ir[11:9]==3'b001) begin
                                casez(ir2[15:8])
                                8'h6?,8'h7?:    // FMOVE to memory
                                        begin
                                                case(ir2[12:10])
                                                3'b000,3'b100,3'b110:
                                                        begin
                                                                fps <= rfoFpdst;
                                                                goto (DF2I1);
                                                        end
                                                3'b011:
                                                        begin
                                                                fpd <= rfoFpdst;
                                                                fs_data(mmm,rrr,STORE_HEXI1,D);
                                                        end
                                                default:
                                                        begin
                                                                fpd <= rfoFpdst;
                                                                fs_data(mmm,rrr,STORE_HEXI1,D);
                                                        end
                                                endcase
                                        end
                                8'b10????00:    // PG 4-71
                                        if (ir2[13])
                                                case(ir2[7:0])
                                                8'h00:  // FMOVE
                                                        case(ir2[12:10])
                                                        3'b001: // FPIAR
                                                                begin
                                                                        d <= fpiar;
                                                                        fs_data(mmm,rrr,STORE_LWORD,D);
                                                                end
                                                        3'b010: // FPSR
                                                                begin
                                                                        d <= fpsr;
                                                                        fs_data(mmm,rrr,STORE_LWORD,D);
                                                                end
                                                        3'b100: tIllegal();// FPCR
                                                        default:        tIllegal();
                                                        endcase
                                                default:        tIllegal();
                                                endcase
                                        else
                                                tIllegal();
                                8'b11??????:    // FMOVEM
                                        begin
                                                fmovem <= 1'b1;
                                                if (ir2[11]) begin      // dynamic list?
                                                        rrr <= ir2[6:4];
                                                        goto (FMOVEM1);
                                                end
                                                else begin
                                                        imm <= ir2[7:0];
                                                        if (ir2[13])
                                                                goto(MOVEM_Xn2D);
                                                        else
                                                                goto(MOVEM_s2Xn);
                                                end
                                        end
                                8'h??:
                                        case(ir2[6:0])
                                        7'b0000000:     // FMOVE
                                                if (ir2[14]) begin      // RM
                                                        push(FMOVE);
                                                        case(ir2[12:10])
                                                        3'b000: fs_data(mmm,rrr,FETCH_LWORD,S);
                                                        3'b100: fs_data(mmm,rrr,FETCH_WORD,S);
                                                        3'b110: fs_data(mmm,rrr,FETCH_BYTE,S);
                                                        default:        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                        endcase
                                                end
                                                else begin
                                                        fps <= rfoFpsrc;
                                                        goto(FMOVE);
                                                end
                                        7'b0100000:     // FDIV
                                                if (ir2[14]) begin      // RM
                                                        fpd <= rfoFpdst;
                                                        push(FDIV1);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FDIV1);
                                                end
                                        7'b0100010:     // FADD
                                                if (ir2[14]) begin      // RM
                                                        fpd <= rfoFpdst;
                                                        push(FADD);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FADD);
                                                end
                                        7'b0100011:     // FMUL
                                                if (ir2[14]) begin      // RM
                                                        fpd <= rfoFpdst;
                                                        push(FMUL1);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FMUL1);
                                                end
                                        7'b0101000:     // FSUB
                                                if (ir2[14]) begin      // RM
                                                        fsub <= 1'b1;
                                                        fpd <= rfoFpdst;
                                                        push(FADD);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fsub <= 1'b1;
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FADD);
                                                end
                                        7'b0011000:     // FABS
                                                if (ir2[14]) begin      // RM
                                                        fabs <= 1'b1;
                                                        push(FNEG);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fabs <= 1'b1;
                                                        fps <= rfoFpsrc;
                                                        goto(FNEG);
                                                end
                                        7'b0011010:     // FNEG
                                                if (ir2[14]) begin      // RM
                                                        push(FNEG);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fps <= rfoFpsrc;
                                                        goto(FNEG);
                                                end
                                        7'b0111000:     // FCMP
                                                if (ir2[14]) begin      // RM
                                                        fpd <= rfoFpdst;
                                                        push(FCMP);
                                                        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                end
                                                else begin
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FCMP);
                                                end
                                        7'b0111010:     // FTST
                                                if (ir2[14]) begin
                                                        push (FTST);
                                                        case(ir2[12:10])
                                                        3'b000: fs_data(mmm,rrr,FETCH_LWORD,S);
                                                        3'b011: fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                        3'b100: fs_data(mmm,rrr,FETCH_WORD,S);
                                                        3'b110: fs_data(mmm,rrr,FETCH_BYTE,S);
                                                        default:        fs_data(mmm,rrr,FETCH_HEXI1,S);
                                                        endcase
                                                end
                                                else begin
                                                        fnf <= rfoFpsrc[95];
                                                        fzf <= rfoFpsrc[94:0]=='d0;
                                                        ret();
                                                end
                                        7'b0100110:     // FSCALE
                                                if (ir2[14]) begin      // RM
                                                        fpd <= rfoFpdst;
                                                        push(FSCALE);
                                                        case(ir2[12:10])
                                                        3'b000: fs_data(mmm,rrr,FETCH_LWORD,S);
                                                        3'b100: fs_data(mmm,rrr,FETCH_WORD,S);
                                                        3'b110: fs_data(mmm,rrr,FETCH_BYTE,S);
                                                        default:        fs_data(mmm,rrr,FETCH_LWORD,S);
                                                        endcase
                                                end
                                                else begin
                                                        fpd <= rfoFpdst;
                                                        fps <= rfoFpsrc;
                                                        goto(FSCALE);
                                                end
/*                                              
                                        7'b0011011:     // FGETEXP2
                                                begin
                                                        resL <= {18'd0,fpsu.exp};
                                                        rfwrL <= 1'b1;
                                                        Rt <= {1'b0,rrr};
                                                        ret();
                                                end
*/                                              
/*                                              
                                        7'b0011100:     // FCOPY
                                                begin
                                                        fps <= rfoFpsrc;
                                                        goto (FCOPYEXP);
                                                end
*/                                              
                                        default:
                                                tIllegal();
                                        endcase
                                default:
                                        tIllegal();
                                endcase
                        end
                        else
                                tIllegal();
                end
`endif          
        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

//-----------------------------------------------------------------------------
// The destination store for the MOVE instruction.
// Flags are not updated if the target is an address register.
//-----------------------------------------------------------------------------

STORE_IN_DEST:
        begin
                resL <= s;
                resW <= s[15:0];
                resB <= s[7:0];
                d <= s;
                if (ir[8:6]!=3'b001) begin
                        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;
                end
                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
                        flag_update <= FU_NONE;
                        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
                        flag_update <= FU_NONE;
                        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
        
`ifdef SUPPORT_DECFLT
FETCH_IMM96:
        begin
                call(FETCH_IMM32,FETCH_IMM96b);
        end
FETCH_IMM96b:
        begin
`ifdef BIG_ENDIAN
                fps[95:64] <= imm;
`else
                fps[31: 0] <= imm;
`endif
                call(FETCH_IMM32,FETCH_IMM96c);
        end
FETCH_IMM96c:
        begin
`ifdef BIG_ENDIAN
                fps[63:32] <= imm;
`else
                fps[63:32] <= imm;
`endif
                call(FETCH_IMM32,FETCH_IMM96d);
        end
FETCH_IMM96d:
        begin
`ifdef BIG_ENDIAN
                fps[31: 0] <= imm;
`else
                fps[95:64] <= imm;
`endif
                ret();
        end
`endif

// 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

`ifdef SUPPORT_DECFLT
FETCH_HEXI1:
        call (FETCH_LWORD,FETCH_HEXI2);
FETCH_HEXI2:
        begin
`ifdef BIG_ENDIAN
                if (ds==S)
                        fps[95:64] <= s;
                else
                        fpd[95:64] <= d;
`else
                if (ds==S)
                        fps[31: 0] <= s;
                else
                        fpd[31: 0] <= d;
`endif
                ea <= ea + 4'd4;                        
                call (FETCH_LWORD,FETCH_HEXI3);
        end
FETCH_HEXI3:
        begin
`ifdef BIG_ENDIAN
                if (ds==S)
                        fps[63:32] <= s;
                else
                        fpd[63:32] <= d;
`else
                if (ds==S)
                        fps[63:32] <= s;
                else
                        fpd[63:32] <= d;
`endif                  
                ea <= ea + 4'd4;
                call (FETCH_LWORD,FETCH_HEXI4);
        end
FETCH_HEXI4:
        begin
`ifdef BIG_ENDIAN
                if (ds==S)
                        fps[31: 0] <= s;
                else
                        fpd[31: 0] <= d;
`else
                if (ds==S)
                        fps[95:64] <= s;
                else
                        fpd[95:64] <= d;
`endif
                ea <= ea - 4'd8;                        
                ret();
        end

STORE_HEXI1:
        begin
`ifdef BIG_ENDIAN
                d <= fpd[95:64];
`else
                d <= fpd[31: 0];
`endif
                call (STORE_LWORD,STORE_HEXI2);
        end
STORE_HEXI2:
        begin
`ifdef BIG_ENDIAN
                d <= fpd[63:32];
`else
                d <= fpd[63:32];
`endif
                ea <= ea + 4'd4;
                call (STORE_LWORD,STORE_HEXI3);
        end
STORE_HEXI3:
        begin
`ifdef BIG_ENDIAN
                d <= fpd[31: 0];
`else
                d <= fpd[95:32];
`endif
                ea <= ea + 4'd4;
                call (STORE_LWORD,STORE_HEXI4);
        end
STORE_HEXI4:
        begin
                ea <= ea - 4'd8;
                ret();
        end

`endif

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,fmovem ? FETCH_NOP_HEXI : ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,D);
        end
        else
                fs_data(mmm,rrr,fmovem ? FETCH_NOP_HEXI : ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,D);
`else
        begin
                push(MOVEM_Xn2D2);
                fs_data(mmm,rrr,fmovem ? FETCH_NOP_HEXI : 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 + (fmovem ? 32'd12 : 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;
                                FLTSRC <= 3'd7;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd1;
                                FLTSRC <= 3'd6;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd2;
                                FLTSRC <= 3'd5;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd3;
                                FLTSRC <= 3'd4;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd4;
                                FLTSRC <= 3'd3;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd5;
                                FLTSRC <= 3'd2;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd6;
                                FLTSRC <= 3'd1;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd7;
                                FLTSRC <= 3'd0;
                        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;
                                FLTSRC <= 3'd0;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd14;
                                FLTSRC <= 3'd1;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd13;
                                FLTSRC <= 3'd2;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd12;
                                FLTSRC <= 3'd3;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd11;
                                FLTSRC <= 3'd4;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd10;
                                FLTSRC <= 3'd5;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd9;
                                FLTSRC <= 3'd6;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd8;
                                FLTSRC <= 3'd7;
                        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];
                if (fmovem)
                        fpd <= rfoFpsrc;
                else
                        d <= rfoRnn;
                ds <= D;
                call(fmovem ? STORE_HEXI1 : ir[6] ? STORE_LWORD : STORE_WORD,MOVEM_Xn2D4);
        end
MOVEM_Xn2D4:
        begin
                case(mmm)
                // ea is updated by STORE_HEXI1, incremented by 8
                3'b011: ea <= ea + (fmovem ? 32'd12 : ir[6] ? 32'd4 : 32'd2);
                3'b100: ea <= ea - (fmovem ? 32'd12 : ir[6] ? 32'd4 : 32'd2);
                default:
                        ea <= ea + (fmovem ? 32'd12 : 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 + (fmovem ? 32'd12 : 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;
                                FLTSRC <= 3'd7;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd1;
                                FLTSRC <= 3'd6;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd2;
                                FLTSRC <= 3'd5;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd3;
                                FLTSRC <= 3'd4;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd4;
                                FLTSRC <= 3'd3;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd5;
                                FLTSRC <= 3'd2;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd6;
                                FLTSRC <= 3'd1;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd7;
                                FLTSRC <= 3'd0;
                        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;
                                FLTSRC <= 3'd0;
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                rrrr <= 4'd14;
                                FLTSRC <= 3'd1;
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                rrrr <= 4'd13;
                                FLTSRC <= 3'd2;
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                rrrr <= 4'd12;
                                FLTSRC <= 3'd3;
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                rrrr <= 4'd11;
                                FLTSRC <= 3'd4;
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                rrrr <= 4'd10;
                                FLTSRC <= 3'd5;
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                rrrr <= 4'd9;
                                FLTSRC <= 3'd6;
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                rrrr <= 4'd8;
                                FLTSRC <= 3'd7;
                        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,fmovem ? FETCH_NOP_HEXI : ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
        end
        else
                fs_data(mmm,rrr,fmovem ? FETCH_NOP_HEXI : ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
`else
        begin
                push(MOVEM_s2Xn2);
                fs_data(mmm,rrr,fmovem ? FETCH_NOP_HEXI : ir[6] ? FETCH_NOP_LWORD : FETCH_NOP_WORD,S);
        end
`endif
MOVEM_s2Xn2:
        if (imm[15:0] != 16'h0000) begin
                ds <= S;
                call(fmovem ? FETCH_HEXI1 : 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 + (fmovem ? 32'd12 : ir[6] ? 32'd4 : 32'd2);
                                rfwrL <= 1'b1;
                        end
                endcase
                ret();
        end
MOVEM_s2Xn3:
        begin
                case(mmm)
                3'b011: ea <= ea + (fmovem ? 32'd12 : ir[6] ? 32'd4 : 32'd2);
                3'b100: ea <= ea - (fmovem ? 32'd12 : ir[6] ? 32'd4 : 32'd2);
                default:
                        ea <= ea + (fmovem ? 32'd12 : 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]};
                resF <= fps;
                if (mmm!=3'b100) begin
                        if (imm[0]) begin
                                imm[0] <= 1'b0;
                                Rt <= 4'd0 ^ {3{fmovem}};
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                Rt <= 4'd1 ^ {3{fmovem}};
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                Rt <= 4'd2 ^ {3{fmovem}};
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                Rt <= 4'd3 ^ {3{fmovem}};
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                Rt <= 4'd4 ^ {3{fmovem}};
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                Rt <= 4'd5 ^ {3{fmovem}};
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                Rt <= 4'd6 ^ {3{fmovem}};
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                Rt <= 4'd7 ^ {3{fmovem}};
                        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 ^ {4{fmovem}};
                        end
                        else if (imm[1]) begin
                                imm[1] <= 1'b0;
                                Rt <= 4'd14 ^ {4{fmovem}};
                        end
                        else if (imm[2]) begin
                                imm[2] <= 1'b0;
                                Rt <= 4'd13 ^ {4{fmovem}};
                        end
                        else if (imm[3]) begin
                                imm[3] <= 1'b0;
                                Rt <= 4'd12 ^ {4{fmovem}};
                        end
                        else if (imm[4]) begin
                                imm[4] <= 1'b0;
                                Rt <= 4'd11 ^ {4{fmovem}};
                        end
                        else if (imm[5]) begin
                                imm[5] <= 1'b0;
                                Rt <= 4'd10 ^ {4{fmovem}};
                        end
                        else if (imm[6]) begin
                                imm[6] <= 1'b0;
                                Rt <= 4'd9 ^ {4{fmovem}};
                        end
                        else if (imm[7]) begin
                                imm[7] <= 1'b0;
                                Rt <= 4'd8 ^ {4{fmovem}};
                        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'h020:        begin canary <= 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'h020:  begin resL <= canary; 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
CCHK:
        begin
                if (s != canary) begin
                isr <= srx;
                tf <= 1'b0;
                sf <= 1'b1;
                        vecno <= `CHK_VEC;
            goto (TRAP3);
                end
                else
                        ret();
        end
`ifdef SUPPORT_DECFLT
FADD:
        begin
                fpcnt <= fpcnt + 2'd1;
                if (fpcnt==8'd50) begin
                        if (DECFLT) begin
                                fzf <= dfaddsubo[94:0]==95'd0;
                                fnf <= dfaddsubo[95];
                                fvf <= dfaddsubo[94:90]==5'b11110;
                                fnanf <= dfaddsubo[94:90]==5'b11111;
                                resF <= dfaddsubo;
                                Rt <= {1'b0,FLTDST};
                                rfwrF <= 1'b1;
                        end
                        ret();
                end
        end
FSCALE:
        begin
                fpcnt <= fpcnt + 2'd1;
                if (fpcnt==8'd3) begin
                        if (DECFLT) begin
                                fzf <= dfscaleo[94:0]==95'd0;
                                fnf <= dfscaleo[95];
                                fvf <= dfscaleo[94:90]==5'b11110;
                                fnanf <= dfscaleo[94:90]==5'b11111;
                                resF <= dfscaleo;
                                Rt <= {1'b0,FLTDST};
                                rfwrF <= 1'b1;
                        end
                        ret();
                end
        end
FNEG:   // Also FABS
        begin
                if (DECFLT) begin
                        resF <= {~fps[95] & ~fabs,fps[94:0]};
                        fzf <= fps[94:0]==95'd0;
                        fnf <= ~fps[95] & ~fabs;
                        Rt <= {1'b0,FLTDST};
                        rfwrF <= 1'b1;
                end
                ret();
        end
FMUL1:
        goto (FMUL2);
FMUL2:
        if (DECFLT) begin
                if (dfmuldone) begin
                        fzf <= dfmulo[94:0]==95'd0;
                        fnf <= dfmulo[95];
                        fvf <= dfmulo[94:90]==5'b11110;
                        fnanf <= dfmulo[94:90]==5'b11111;
                        resF <= dfmulo;
                        Rt <= {1'b0,FLTDST};
                        rfwrF <= 1'b1;
                        ret();
                end
        end
        else
                ret();
        // For divide the done signal may take several cycles to go inactive after
        // the load signal is activated. Prevent a premature recognition of done
        // using a counter.
FDIV1:
        begin
                fpcnt <= fpcnt + 2'd1;
                if (fpcnt == 8'd50)
                        goto (FDIV2);
        end
FDIV2:
        if (dfdivdone) begin
                if (DECFLT) begin
                        fzf <= dfdivo[94:0]==95'd0;
                        fnf <= dfdivo[95];
                        fvf <= dfdivo[94:90]==5'b11110;
                        fnanf <= dfdivo[94:90]==5'b11111;
                        resF <= dfdivo;
                        Rt <= {1'b0,FLTDST};
                        rfwrF <= 1'b1;
                        quotient_bits <= {dfdivo[95],dfdivo[6:0]};
                        quotient_bitshi <= {dfdivo[9:7]};
                end
                ret();
        end
FCMP:
        begin
                if (DECFLT) begin
                        fzf <= dfcmpo[0];
                        fnf <= dfcmpo[1];
                        fvf <= 1'b0;
                        fnanf <= dfcmpo[4];
                end
                ret();
        end
FMOVE:
        begin
                if (DECFLT) begin
                        if (ir2[14])
                                case(ir2[12:10])
                                3'b000:
                                        begin
                                                fps <= {64'd0,s};
                                                goto (I2DF1);
                                        end
                                3'b100:
                                        begin
                                                fps <= {80'd0,s[15:0]};
                                                goto (I2DF1);
                                        end
                                3'b110:
                                        begin
                                                fps <= {88'd0,s[7:0]};
                                                goto (I2DF1);
                                        end
                                default:
                                        begin
                                                resF <= fps[95:0];
                                                fzf <= fps[94:0]==95'd0;
                                                fnf <= fps[95];
                                                Rt <= {1'b0,FLTDST};
                                                rfwrF <= 1'b1;
                                                ret();
                                        end
                                endcase
                        else begin
                                resF <= fps[95:0];
                                fzf <= fps[94:0]==95'd0;
                                fnf <= fps[95];
                                Rt <= {1'b0,FLTDST};
                                rfwrF <= 1'b1;
                                ret();
                        end
                end
                else
                        ret();
        end
I2DF1:
        goto (I2DF2);
I2DF2:
        begin
                if (DECFLT) begin
                        if (i2dfdone) begin
                                resF <= i2dfo;
                                fzf <= i2dfo[94:0]==95'd0;
                                fnf <= i2dfo[95];
                                Rt <= {1'b0,FLTDST};
                                rfwrF <= 1'b1;
                                ret();
                        end
                end
                else
                        ret();
        end
DF2I1:
        goto (DF2I2);
DF2I2:
        begin
                if (DECFLT) begin
                        if (df2idone) begin
                                case(ir2[12:10])
                                3'b000: fs_data(mmm,rrr,STORE_LWORD,D);
                                3'b100: fs_data(mmm,rrr,STORE_WORD,D);
                                3'b110: fs_data(mmm,rrr,STORE_BYTE,D);
                                default:        ret();
                                endcase
                                resF <= df2io;
                                resL <= df2io[31:0];
                                resW <= df2io[15:0];
                                resB <= df2io[ 7:0];
                                d <= df2io;
                                fzf <= df2io[94:0]==95'd0;
                                fnf <= df2io[95];
                                fvf <= df2iover;
                                //Rt <= {1'b0,FLTDST};
                                //rfwrL <= 1'b1;
                        end
                end
                else
                        ret();
        end
FTST:
        begin
                case(ir2[12:10])
                3'b000: begin fnf <= s[31]; fzf <= s[31:0]==32'd0; fnanf <= 1'b0; fvf <= 1'b0; end
                3'b100: begin fnf <= s[15]; fzf <= s[15:0]==16'd0; fnanf <= 1'b0; fvf <= 1'b0; end
                3'b110: begin fnf <= s[ 7]; fzf <= s[ 7:0]== 8'd0; fnanf <= 1'b0; fvf <= 1'b0; end
                default:
                        begin
                                fnf <= fps[95];
                                fzf <= fps[94:0]=='d0;
                                fnanf <= fps[94:90]==5'b11111;
                                fvf <= fps[94:90]==5'b11110;
                        end
                endcase
                ret();
        end
FBCC:
        begin
                if (ftakb)
                        pc <= opc + imm;
                ret();
        end
/*      
FCOPYEXP:
        begin
                resF <= fpdp;
                rfwrF <= 1'b1;
                Rt <= {1'b0,FLTDST};
                ret();
        end
*/
FMOVEM1:
        begin
                imm <= rfoDnn[7:0];
                if (ir2[13])
                        goto(MOVEM_Xn2D);
                else
                        goto(MOVEM_s2Xn);
        end

`endif

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 ? rfoDn : rfob;
                                else begin
                                        s <= MMMRRR ? rfoDn : rfob;
                                        fps <= MMMRRR ? rfoDn : rfob;
                                end
                                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;
`ifdef SUPPORT_DECFLT                           
                                FETCH_HEXI1,STORE_HEXI1: resL <= rfoAn + 5'd12;
`endif                          
                                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;
`ifdef SUPPORT_DECFLT                           
                                FETCH_NOP_HEXI,FETCH_HEXI1,STORE_HEXI1: ea <= rfoAn - 5'd12;
`endif                          
                                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;
`ifdef SUPPORT_DECFLT                           
                                FETCH_HEXI1,STORE_HEXI1: resL <= rfoAn - 5'd12;
`endif
                                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
                                                // ToDo: add FETCH_IMM128
                                3'd4:   begin   // #i16
                                                        goto(size_state==FETCH_NOP_HEXI ? FETCH_IMM96:(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||size_state==FETCH_NOP_HEXI)?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_stk5 <= state_stk4;
        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_stk5 <= state_stk4;
        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;
        state_stk5 <= state_stk4;
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;
        state_stk4 <= state_stk5;
end
endtask

endmodule

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.