buserror / simavr

simavr is a lean, mean and hackable AVR simulator for linux & OSX
GNU General Public License v3.0
1.54k stars 366 forks source link

Incorrect SBI behaviour, PINx usecase #337

Open djfd opened 5 years ago

djfd commented 5 years ago

Hi,

Current SBI simulation implementation works wrong when the target is PINx register. The code:

case 0x9a00: {  // SBI -- Set Bit in I/O Register -- 1001 1010 AAAA Abbb
    get_io5_b3mask(opcode);
    uint8_t res = _avr_get_ram(avr, io) | mask;
    STATE("sbi %s[%04x], 0x%02x = %02x\n", avr_regname(io), avr->data[io], mask, res);
    _avr_set_ram(avr, io, res);
    cycle++;
} break;

That is we read (with avr_ioport_read) port value, then ORing it with a bit to set, then pushing it back (via avr_ioport_pin_write).

It is clear that the value read is not zero (DATAx bits for output lines + PINx bits for inputs) and avr_ioport_pin_write flips them all causing incorrect operation (disabling pull-ups for inputs, inverting all outputs, not the only one intended to be inverted).

Likely need to distinguish this marginal use case somewhere, maybe right in SBI simulator handler.

OFF THE TOPIC Just to do not create an extra issue. I looked through the code briefly, and I cannot see if external reset (by means of RESET pin) is supported. Does anybody know for sure?

UPD simplest way is to use avr_ioport_write instead of avr_ioport_pin_write for this, after detecting that we dealing with PINx port.

Thanks

smalcom commented 3 years ago

Try this https://github.com/buserror/simavr/issues/342#issuecomment-678438599