On 13/08/2022 07:24, Philipp Klaus Krause wrote:
If SDCC can find out that there is no division in the ISR, it will omit the workaround. Can you show the code of your ISR here?

Okay, this is confusing... Since my previous message, I changed some other code - not touching the ISR code at all - and now SDCC is not generating the DIV workaround in the ISR! I change that code back to how it was, and SDCC does generate the DIV.

Here is the assembly (unoptimised, with --no-peep, in case optimisations were obscuring things) generated for the ISR:

;    main.c: 267: void i2c_isr(void) __interrupt(ISR_I2C) {
;    -----------------------------------------
;     function i2c_isr
;    -----------------------------------------
_i2c_isr:
    clr    a
    div    x, a
;    main.c: 274: PC_ODR ^= _BV(PC_ODR_ODR5);
    ld    a, 0x500a
    xor    a, #0x20
    ld    0x500a, a
;    main.c: 279: sr1 = I2C_SR1;
    mov    _i2c_isr_sr1_65536_68+0, 0x5217
;    main.c: 280: sr2 = I2C_SR2;
    mov    _i2c_isr_sr2_65536_68+0, 0x5218
;    main.c: 281: sr3 = I2C_SR3;
    mov    _i2c_isr_sr3_65536_68+0, 0x5219
;    main.c: 284: if(bit_is_set(sr1, I2C_SR1_ADDR)) {
    ld    a, _i2c_isr_sr1_65536_68+0
    bcp    a, #0x02
    jrne    00182$
    jp    00105$
00182$:
;    main.c: 285: PC_ODR ^= _BV(PC_ODR_ODR1);
    ld    a, 0x500a
    xor    a, #0x02
    ld    0x500a, a
;    main.c: 291: if(bit_is_set(sr3, I2C_SR3_TRA)) {
    ld    a, _i2c_isr_sr3_65536_68+0
    bcp    a, #0x04
    jrne    00183$
    jp    00102$
00183$:
;    main.c: 292: state = EEPROM_STATE_DATA;
    mov    _i2c_isr_state_65536_68+0, #0x03
    jp    00103$
00102$:
;    main.c: 294: state = EEPROM_STATE_ADDR_MSB;
    mov    _i2c_isr_state_65536_68+0, #0x01
00103$:
;    main.c: 297: PC_ODR ^= _BV(PC_ODR_ODR1);
    ld    a, 0x500a
    xor    a, #0x02
    ld    0x500a, a
00105$:
;    main.c: 301: if(bit_is_set(sr1, I2C_SR1_RXNE)) {
    ld    a, _i2c_isr_sr1_65536_68+0
    bcp    a, #0x40
    jrne    00184$
    jp    00111$
00184$:
;    main.c: 302: PC_ODR ^= _BV(PC_ODR_ODR2);
    ld    a, 0x500a
    xor    a, #0x04
    ld    0x500a, a
;    main.c: 304: switch(state) {
    ld    a, _i2c_isr_state_65536_68+0
    dec    a
    jrne    00186$
    jp    00106$
00186$:
    ld    a, _i2c_isr_state_65536_68+0
    cp    a, #0x02
    jrne    00189$
    jp    00107$
00189$:
    jp    00108$
;    main.c: 305: case EEPROM_STATE_ADDR_MSB:
00106$:
;    main.c: 307: addr = (I2C_DR & EEPROM_ADDR_MASK_MSB) << 8;
    ld    a, 0x5216
    and    a, #0x0f
    clrw    x
    ld    xh, a
    clr    a
    ld    xl, a
    ldw    _i2c_isr_addr_65536_68+0, x
;    main.c: 308: state = EEPROM_STATE_ADDR_LSB;
    mov    _i2c_isr_state_65536_68+0, #0x02
;    main.c: 309: break;
    jp    00109$
;    main.c: 310: case EEPROM_STATE_ADDR_LSB:
00107$:
;    main.c: 313: addr |= (I2C_DR & EEPROM_ADDR_MASK_LSB);
    ld    a, 0x5216
    clrw    x
    or    a, _i2c_isr_addr_65536_68+1
    ld    xl, a
    ld    a, xh
    or    a, _i2c_isr_addr_65536_68+0
    ld    xh, a
    ldw    _i2c_isr_addr_65536_68+0, x
;    main.c: 314: state = EEPROM_STATE_START;
    clr    _i2c_isr_state_65536_68+0
;    main.c: 315: break;
    jp    00109$
;    main.c: 316: default:
00108$:
;    main.c: 317: state = EEPROM_STATE_START;
    clr    _i2c_isr_state_65536_68+0
;    main.c: 319: }
00109$:
;    main.c: 321: PC_ODR ^= _BV(PC_ODR_ODR2);
    ld    a, 0x500a
    xor    a, #0x04
    ld    0x500a, a
00111$:
;    main.c: 325: if(bit_is_set(sr1, I2C_SR1_TXE)) {
    ld    a, _i2c_isr_sr1_65536_68+0
    tnz    a
    jrmi    00191$
    jp    00118$
00191$:
;    main.c: 326: PC_ODR ^= _BV(PC_ODR_ODR3);
    ld    a, 0x500a
    xor    a, #0x08
    ld    0x500a, a
;    main.c: 328: switch(state) {
    ld    a, _i2c_isr_state_65536_68+0
    cp    a, #0x03
    jrne    00193$
    jp    00194$
00193$:
    jp    00115$
00194$:
;    main.c: 333: data = (addr < sizeof(eeprom_data) ? eeprom_data[addr] : EEPROM_DATA_BLANK);
    ldw    x, _i2c_isr_addr_65536_68+0
    cpw    x, #0x0279
    jrc    00195$
    jp    00125$
00195$:
    ldw    x, #_eeprom_data+0
    addw    x, _i2c_isr_addr_65536_68+0
    ld    a, (x)
    clrw    x
    jp    00126$
00125$:
    ld    a, #0xff
    clrw    x
00126$:
    ld    _i2c_isr_data_65536_68+0, a
;    main.c: 334: I2C_DR = data;
    mov    0x5216+0, _i2c_isr_data_65536_68+0
;    main.c: 336: addr = (addr + 1) & EEPROM_ADDR_MASK;
    ldw    x, _i2c_isr_addr_65536_68+0
    incw    x
    ld    a, xh
    and    a, #0x0f
    ld    xh, a
    ldw    _i2c_isr_addr_65536_68+0, x
;    main.c: 338: if(!eeprom_log_fifo_is_full()) {
    call    _eeprom_log_fifo_is_full
    tnz    a
    jreq    00196$
    jp    00116$
00196$:
;    main.c: 339: log_msg.address = addr;
    mov    _i2c_isr_log_msg_65536_68+1, _i2c_isr_addr_65536_68+1
    mov    _i2c_isr_log_msg_65536_68+0, _i2c_isr_addr_65536_68+0
;    main.c: 340: log_msg.data = data;
    mov    _i2c_isr_log_msg_65536_68+2, _i2c_isr_data_65536_68+0
;    main.c: 341: eeprom_log_fifo_push(&log_msg);
    ldw    x, #(_i2c_isr_log_msg_65536_68+0)
    call    _eeprom_log_fifo_push
;    main.c: 344: break;
    jp    00116$
;    main.c: 345: default:
00115$:
;    main.c: 346: state = EEPROM_STATE_START;
    clr    _i2c_isr_state_65536_68+0
;    main.c: 348: }
00116$:
;    main.c: 350: PC_ODR ^= _BV(PC_ODR_ODR3);
    ld    a, 0x500a
    xor    a, #0x08
    ld    0x500a, a
00118$:
;    main.c: 354: if(bit_is_set(sr2, I2C_SR2_AF)) {
    ld    a, _i2c_isr_sr2_65536_68+0
    bcp    a, #0x04
    jrne    00197$
    jp    00120$
00197$:
;    main.c: 355: PC_ODR ^= _BV(PC_ODR_ODR4);
    ld    a, 0x500a
    xor    a, #0x10
    ld    0x500a, a
;    main.c: 358: I2C_SR2 &= ~(_BV(I2C_SR2_AF));
    ld    a, 0x5218
    and    a, #0xfb
    ld    0x5218, a
;    main.c: 359: state = EEPROM_STATE_START;
    clr    _i2c_isr_state_65536_68+0
;    main.c: 361: PC_ODR ^= _BV(PC_ODR_ODR4);
    ld    a, 0x500a
    xor    a, #0x10
    ld    0x500a, a
00120$:
;    main.c: 365: if(bit_is_set(sr1, I2C_SR1_STOPF)) {
    ld    a, _i2c_isr_sr1_65536_68+0
    bcp    a, #0x10
    jrne    00198$
    jp    00122$
00198$:
;    main.c: 366: PC_ODR ^= _BV(PC_ODR_ODR4);
    ld    a, 0x500a
    xor    a, #0x10
    ld    0x500a, a
;    main.c: 369: I2C_CR2 |= _BV(I2C_CR2_ACK);
    ld    a, 0x5211
    or    a, #0x04
    ld    0x5211, a
;    main.c: 370: state = EEPROM_STATE_START;
    clr    _i2c_isr_state_65536_68+0
;    main.c: 372: PC_ODR ^= _BV(PC_ODR_ODR4);
    ld    a, 0x500a
    xor    a, #0x10
    ld    0x500a, a
00122$:
;    main.c: 375: PC_ODR ^= _BV(PC_ODR_ODR5);
    ld    a, 0x500a
    xor    a, #0x20
    ld    0x500a, a
00123$:
;    main.c: 376: }
    iret

The code that I changed that caused SDCC not to generate the DIV workaround was in another function, eeprom_log_fifo_push(). The only relation of that to the ISR is that the ISR calls it.

The code for that function is quite simple. Here is the version that causes DIV to be generated:

;    main.c: 201: static void eeprom_log_fifo_push(const eeprom_log_msg_t *msg) {
;    -----------------------------------------
;     function eeprom_log_fifo_push
;    -----------------------------------------
_eeprom_log_fifo_push:
;    main.c: 202: eeprom_log.head = (eeprom_log.head + 1) & EEPROM_LOG_FIFO_LEN_MASK;
    ld    a, _eeprom_log+0
    inc    a
    and    a, #0x7f
    ld    _eeprom_log+0, a
;    main.c: 214: eeprom_log.queue[eeprom_log.head] = *msg;
    exgw    x, y
    ld    a, _eeprom_log+0
    ld    xl, a
    ld    a, #0x03
    mul    x, a
    addw    x, #(_eeprom_log+2)
    push    #0x03
    push    #0x00
    pushw    y
    call    ___memcpy
00101$:
;    main.c: 215: }
    ret

And here is the changed version that does not generate the DIV:

;    main.c: 201: static void eeprom_log_fifo_push(const eeprom_log_msg_t *msg) {
;    -----------------------------------------
;     function eeprom_log_fifo_push
;    -----------------------------------------
_eeprom_log_fifo_push:
    sub    sp, #2
    ldw    (0x01, sp), x
;    main.c: 202: eeprom_log.head = (eeprom_log.head + 1) & EEPROM_LOG_FIFO_LEN_MASK;
    ld    a, _eeprom_log+0
    inc    a
    and    a, #0x7f
    ld    _eeprom_log+0, a
;    main.c: 205: eeprom_log_msg_t *log_msg = &eeprom_log.queue[eeprom_log.head];
    ld    a, _eeprom_log+0
    ld    xl, a
    ld    a, #0x03
    mul    x, a
    addw    x, #(_eeprom_log+2)
;    main.c: 206: log_msg->address = msg->address;
    ldw    y, (0x01, sp)
    ldw    y, (y)
    ldw    (x), y
;    main.c: 207: log_msg->data = msg->data;
    incw    x
    incw    x
    ldw    y, (0x01, sp)
    ld    a, (0x2, y)
    ld    (x), a
00101$:
;    main.c: 215: }
    addw    sp, #2
    ret

(I was attempting to get rid of the call to ___memcpy().)

I don't see how any of the code in the other function would have any impact on whether the DIV workaround is generated or not in the ISR. Unless it's something to do with the sub-call to ___memcpy() - but I don't see why that would ever be using a DIV/DIVW instruction.

Regards,
Basil Hussain


_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to