• prevent a possible overflow when adding in a 16-bit processor register

    From =?UTF-8?B?0JDQvdC00YDQtdC5INCd0LjQu@21:1/5 to All on Tue Oct 12 12:40:20 2021
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fridtjof.martin.weigel@gmail.com@21:1/5 to nikiti...@gmail.com on Tue Oct 12 15:24:26 2021
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Sure -- look at my am9511 emulator

    https://github.com/ratboy666/am9511

    and, in specific, file ova.c (overflow arithmetic). It shows how to do overflow checking on add, subtract, and multiply.

    Have fun!
    Fred Weigel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fridtjof.martin.weigel@gmail.com@21:1/5 to nikiti...@gmail.com on Tue Oct 12 17:57:15 2021
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Anyway, there is no overflow here at all -- what is the type of pointer2? Note that if p is a pointer, p+n
    is numeric p + (n * sizeof(*p)): in other words, this calculation:

    char *p2 = (char *)p;
    p = p + (n * sizeof(*p));
    p2 = (void *)p;

    Now, it looks like ix+6 and ix+7 are the "n", appears to do n + 1, and then makes it an even number (and 0feh)
    Can I see the C source for this production?

    Note that ova.c that I pointed you at earlier does overflow detection for C arithmetic. And it works on both Hi-Tech C
    on the Z80, and GCC on modern platforms. It is reasonably efficient on both of those. Note that carry is returned by the
    add/subtract, and overflow is detected after the add/subtract.

    FredW

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?B?0JDQvdC00YDQtdC5INCd0LjQu@21:1/5 to All on Wed Oct 13 04:10:22 2021
    среда, 13 октября 2021 г. в 03:57:16 UTC+3, fridtjof.ma...@gmail.com:
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Anyway, there is no overflow here at all -- what is the type of pointer2? Note that if p is a pointer, p+n
    is numeric p + (n * sizeof(*p)): in other words, this calculation:

    char *p2 = (char *)p;
    p = p + (n * sizeof(*p));
    p2 = (void *)p;

    Now, it looks like ix+6 and ix+7 are the "n", appears to do n + 1, and then makes it an even number (and 0feh)
    Can I see the C source for this production?

    Note that ova.c that I pointed you at earlier does overflow detection for C arithmetic. And it works on both Hi-Tech C
    on the Z80, and GCC on modern platforms. It is reasonably efficient on both of those. Note that carry is returned by the
    add/subtract, and overflow is detected after the add/subtract.

    FredW

    This is the memory allocation function:
    The recreated C code is as follows:
    char * alloc_mem (int size) {
    char * l1;
    register char * st;

    if (word_707a <(word_7082 + (size = (size + 1) & 0xFE))) {
    if ((word_7082 = sbrk (512)) == (char *) - 1)
    pr_error ("Out of memory in% s", name_fun);
    word_707a = sbrk (0);
    }
    st = word_7082;
    word_7082 + = size;
    l1 = st;
    while (size--! = 0) * (l1 ++) = 0; // Clearing the allocated memory area
    return st;
    }
    However, the first if statement in this function generates code that is different from the one in the executable image.
    I cannot understand why these actions (size = (size + 1) & 0xFE) and how important they are.

    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fridtjof.martin.weigel@gmail.com@21:1/5 to nikiti...@gmail.com on Wed Oct 13 07:55:59 2021
    On Wednesday, October 13, 2021 at 7:10:23 AM UTC-4, nikiti...@gmail.com wrote:
    среда, 13 октября 2021 г. в 03:57:16 UTC+3, fridtjof.ma...@gmail.com:
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Anyway, there is no overflow here at all -- what is the type of pointer2? Note that if p is a pointer, p+n
    is numeric p + (n * sizeof(*p)): in other words, this calculation:

    char *p2 = (char *)p;
    p = p + (n * sizeof(*p));
    p2 = (void *)p;

    Now, it looks like ix+6 and ix+7 are the "n", appears to do n + 1, and then makes it an even number (and 0feh)
    Can I see the C source for this production?

    Note that ova.c that I pointed you at earlier does overflow detection for C arithmetic. And it works on both Hi-Tech C
    on the Z80, and GCC on modern platforms. It is reasonably efficient on both of those. Note that carry is returned by the
    add/subtract, and overflow is detected after the add/subtract.

    FredW
    This is the memory allocation function:
    The recreated C code is as follows:
    char * alloc_mem (int size) {
    char * l1;
    register char * st;

    if (word_707a <(word_7082 + (size = (size + 1) & 0xFE))) {
    if ((word_7082 = sbrk (512)) == (char *) - 1)
    pr_error ("Out of memory in% s", name_fun);
    word_707a = sbrk (0);
    }
    st = word_7082;
    word_7082 + = size;
    l1 = st;
    while (size--! = 0) * (l1 ++) = 0; // Clearing the allocated memory area return st;
    }
    However, the first if statement in this function generates code that is different from the one in the executable image.
    I cannot understand why these actions (size = (size + 1) & 0xFE) and how important they are.

    Andrey
    Andrey

    Ah... the first line is actually

    if (word_707a < (word_7082 + (size = (size + 1) & 0xFFFE)))

    Let us look at

    size = (size + 1) &0xfffe

    what this is doing is making size even: say, size is 13, 13 + 1 is 14 and 14 & 0xfffe is still 14. Say size is 14, 14 + 1 is 15, 15 & 0xfffe
    is 14. So, size ends up being either size or the next higher even number. We then make sure the allocation fits into the already
    allocated space. If it does we end up at st = word_7082. If not, we use sbrk() to add more memory,

    How important? The code just ensures integer (16 bit) addressing -- so the least significant bit should always be zero on
    allocated addresses.. may be important elsewhere (even+even = even -- but note that if address is odd, odd+even is odd --
    if size is always even, the least significant bit will never change).

    FredW

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fridtjof.martin.weigel@gmail.com@21:1/5 to nikiti...@gmail.com on Wed Oct 13 07:59:54 2021
    On Wednesday, October 13, 2021 at 7:10:23 AM UTC-4, nikiti...@gmail.com wrote:
    среда, 13 октября 2021 г. в 03:57:16 UTC+3, fridtjof.ma...@gmail.com:
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Anyway, there is no overflow here at all -- what is the type of pointer2? Note that if p is a pointer, p+n
    is numeric p + (n * sizeof(*p)): in other words, this calculation:

    char *p2 = (char *)p;
    p = p + (n * sizeof(*p));
    p2 = (void *)p;

    Now, it looks like ix+6 and ix+7 are the "n", appears to do n + 1, and then makes it an even number (and 0feh)
    Can I see the C source for this production?

    Note that ova.c that I pointed you at earlier does overflow detection for C arithmetic. And it works on both Hi-Tech C
    on the Z80, and GCC on modern platforms. It is reasonably efficient on both of those. Note that carry is returned by the
    add/subtract, and overflow is detected after the add/subtract.

    FredW
    This is the memory allocation function:
    The recreated C code is as follows:
    char * alloc_mem (int size) {
    char * l1;
    register char * st;

    if (word_707a <(word_7082 + (size = (size + 1) & 0xFE))) {
    if ((word_7082 = sbrk (512)) == (char *) - 1)
    pr_error ("Out of memory in% s", name_fun);
    word_707a = sbrk (0);
    }
    st = word_7082;
    word_7082 + = size;
    l1 = st;
    while (size--! = 0) * (l1 ++) = 0; // Clearing the allocated memory area return st;
    }
    However, the first if statement in this function generates code that is different from the one in the executable image.
    I cannot understand why these actions (size = (size + 1) & 0xFE) and how important they are.

    Andrey
    Andrey

    Was the peephole optimizer used? It looks like a production was removed:

    mov a,h
    and 0ffh
    mov h,a

    is "missing" -- note that *if* the code were actually &0xFE, it should have been:

    mov a,l
    and 0feh
    mov l,a
    mov h,0

    (or something along those lines)

    or, the compiler code generator is smart enough to deal with converting word into byte as needed.

    FredW

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?B?0JDQvdC00YDQtdC5INCd0LjQu@21:1/5 to All on Wed Oct 13 10:20:09 2021
    среда, 13 октября 2021 г. в 17:59:55 UTC+3, fridtjof.ma...@gmail.com:
    On Wednesday, October 13, 2021 at 7:10:23 AM UTC-4, nikiti...@gmail.com wrote:
    среда, 13 октября 2021 г. в 03:57:16 UTC+3, fridtjof.ma...@gmail.com:
    On Tuesday, October 12, 2021 at 3:40:22 PM UTC-4, nikiti...@gmail.com wrote:
    When adding an integer n to pointer2 (16-bit unsigned number) and comparing it to pointer1, the following z80 assembly code is used:

    ld l, (ix+6)
    ld h, (ix+7)
    inc hl
    ld a, l
    and 0feh
    ld l, a
    ld a, h
    ld (ix+6), l
    ld (ix+7), h
    ld de, (pointer2)
    add hl, de
    ex de, hl
    ld hl, (pointer1)
    call wrelop
    jr nc, label1

    Most likely this is done to prevent a possible overflow when adding in a 16-bit processor register.
    Maybe someone has come across a similar one and knows how these actions can be programmed in C.

    Andrey
    Andrey

    Anyway, there is no overflow here at all -- what is the type of pointer2? Note that if p is a pointer, p+n
    is numeric p + (n * sizeof(*p)): in other words, this calculation:

    char *p2 = (char *)p;
    p = p + (n * sizeof(*p));
    p2 = (void *)p;

    Now, it looks like ix+6 and ix+7 are the "n", appears to do n + 1, and then makes it an even number (and 0feh)
    Can I see the C source for this production?

    Note that ova.c that I pointed you at earlier does overflow detection for C arithmetic. And it works on both Hi-Tech C
    on the Z80, and GCC on modern platforms. It is reasonably efficient on both of those. Note that carry is returned by the
    add/subtract, and overflow is detected after the add/subtract.

    FredW
    This is the memory allocation function:
    The recreated C code is as follows:
    char * alloc_mem (int size) {
    char * l1;
    register char * st;

    if (word_707a <(word_7082 + (size = (size + 1) & 0xFE))) {
    if ((word_7082 = sbrk (512)) == (char *) - 1)
    pr_error ("Out of memory in% s", name_fun);
    word_707a = sbrk (0);
    }
    st = word_7082;
    word_7082 + = size;
    l1 = st;
    while (size--! = 0) * (l1 ++) = 0; // Clearing the allocated memory area return st;
    }
    However, the first if statement in this function generates code that is different from the one in the executable image.
    I cannot understand why these actions (size = (size + 1) & 0xFE) and how important they are.

    Andrey
    Andrey

    Was the peephole optimizer used? It looks like a production was removed:

    mov a,h
    and 0ffh
    mov h,a

    is "missing" -- note that *if* the code were actually &0xFE, it should have been:

    mov a,l
    and 0feh
    mov l,a
    mov h,0

    (or something along those lines)

    or, the compiler code generator is smart enough to deal with converting word into byte as needed.

    FredW

    Thanks. I understood.

    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)