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