/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cz.karry.dop.core.alu;

import cz.karry.dop.core.Bus;
import cz.karry.dop.core.BusListener;
import cz.karry.dop.core.Signal;
import cz.karry.dop.core.SignalListener;
import cz.karry.dop.core.registers.LoadRegister;
import cz.karry.dop.core.registers.Register;
import cz.karry.dop.core.registers.RegisterListener;

/**
 *
 * @author karry
 */
class Blf implements 
    RegisterListener,
    BusListener,
    SignalListener{
    private Bus output;
    private Bus bus;
    private Register w;
    private Signal cf;
    private Bus op;
    private int opLowValue;

    public Blf(Register w, Bus bus, Signal cf, Bus op, Bus output) {
        this.w = w;
        this.bus = bus;
        this.cf = cf;
        this.op = op;
        this.output = output;
        
        opLowValue = op.getValue() & 0x07;
        
        w.addChangeListener(this);
        bus.addBusListener(this);
        cf.addSignalListener(this);
        op.addBusListener(this);
    }

    public void registerChangePerformed(Register register, int value) {
        perform();
    }

    public void busChangePerformed(Bus bus, int value) {
        if ((bus == op) && (opLowValue == (op.getValue() & 0x07))) return;
        perform();
    }

    public void signalChangePerformed(Signal signal, boolean active) {
        perform();
    }

    private void perform() {
        opLowValue = op.getValue() & 0x07;
        
        switch(opLowValue){
            case 0: output.setValue( 0 ); break;                                // 0
            case 1: output.setValue( cf.isActive()? ((w.getValue() >> 1) | 0x8000): (w.getValue() >> 1) ); break;
                                                                                // W shift right
            case 2: output.setValue( bus.getValue() ); break;                   // bus
            case 3: output.setValue( (~bus.getValue()) & 0xffff ); break;       // not(BUS)
            case 4: output.setValue( w.getValue() & bus.getValue() ); break;    // W and BUS
            case 5: output.setValue( w.getValue() | bus.getValue() ); break;    // W or BUS
            case 6: output.setValue( w.getValue() ^ bus.getValue() ); break;    // W xor BUS
            case 7: output.setValue( w.getValue() ); break;                     // W
        }
    }

}
