Open ladmanj opened 3 years ago
Hello @ladmanj
Looks like we are both hacking a non-PC IA16 device 😉
Hello @ladmanj,
Is there any other way to contact the community involved in ia16 asm and gcc topic?
I am not sure, but perhaps VOGONS might be a good place? It seems to be mostly geared towards IBM PC-compatibles (with MS-DOS or old Windows versions), and old Macs --- but you might have some luck there. I have not yet joined myself, but I may in the future.
Generic, platform-independent issues about GCC can probably use one of the official GCC mailing lists, e.g. gcc-help
. Issues specific to gcc-ia16
can come here, for lack of a better place. 😑
There is of course also Stack Overflow, but you probably already know that.
Hello @mfld-fr,
Looks like we are both hacking a non-PC IA16 device :wink:
This to me brings up a question: do you think there is utility in having gcc-ia16
directly support writing programs to be burnt onto EPROMs? To me this seems to be an extremely niche area (even more so than writing PC booter programs), but maybe I am missing something.
Thank you!
Hello @ladmanj,
By the way, @mfld-fr wrote an emu86
emulator which helps debug x86-16 code meant for EPROMs. You may find it helpful.
Thank you!
@tkchia : I think you are right, hard bare metal on IA6 is only for a very few. GCC-IA16 already does the job, at the cost of a little but must have assembly code for the glue...
Hello @tkchia and @mfld-fr,
do you think there is utility in having gcc-ia16 directly support writing programs to be burnt onto EPROMs?
When the ELKS kernel is configured for far text, the gcc-ia16 output is not usable when directly burned in ROM because of the required text relocations. In non-ROM scenarios, this is handled by setup.S when copying from the disk image. A nice addition would be having the ability to specify a final text segment with the linker or elf2elks, which would relocate the .text and .fartext sections and emit a short-form a.out header. Without it, a separate utility will have to be written to allow the ELKS fartext kernel to be ROMable. This could be somewhat easily tested by setting the final text segment to be REL_SYS, in which case the normal ELKS boot/setup.S should load it successfully without modification. I am much less concerned with data segment relocations, as haven't been any so far, and likely could be worked around if generated.
With @mfld-fr's EMU86 now able to show that the current ELKS kernel will run in ROM, this would be nice to have.
Thank you!
Hello @tkchia,
By the way, @mfld-fr wrote an
emu86
emulator which helps debug x86-16 code meant for EPROMs. You may find it helpful.
I will definitely try it
Hello @mfld-fr
Looks like we are both hacking a non-PC IA16 device wink
Welcome my brother :-)
Hello all
I'm trying to use the technique from here https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html#Output-Section-LMA
But I'm getting these errors:
(.text._init_mem+0x5): undefined reference to `_data!'
(.text._init_mem+0x8): undefined reference to `_etext!'
(.text._init_mem+0xc): undefined reference to `_data!'
(.text._init_mem+0xf): undefined reference to `_edata!'
(.text._init_mem+0x14): undefined reference to `_bstart!
I don't understand why the linker doesn't behave as the documentation is describing. Probably different versions of gnu linkers differ in behaviour.
Thanks
OMG, there is the same example with different syntax - i will try it immediately, but I feel I should warn you. https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
Thanks
OMG, there is the same example with different syntax - i will try it immediately, but I feel I should warn you. https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
Thanks
But the result doesn't differ :-(
Hello @ghaerr,
A nice addition would be having the ability to specify a final text segment with the linker or elf2elks, which would relocate the .text and .fartext sections and emit a short-form a.out header. Without it, a separate utility will have to be written to allow the ELKS fartext kernel to be ROMable.
Let me look into that. Thanks!
Hello @tkchia
Let me look into that. Thanks!
Please also kindly look at the linker code. I'm afraid, that there may be a bug.
For example, the function SIZEOF(.text) in the linkerscript returns wrong value. There is 0x85, and the actual .text code size is around 0xcb0 (not exactly, I'm not looking at it right now, but the order of magnitude is correct).
Thank you 😊
Hello @ladmanj,
But I'm getting these errors:
For example, the function SIZEOF(.text) in the linkerscript returns wrong value.
Please give more information about what you were trying to do. Because, unfortunately, I cannot read minds, and I especially cannot read minds from a distance. I cannot guess what exactly you were doing, based only on what you just said.
What would be useful is if you give me your complete input(s) and your complete command line(s) that led to the problems --- enough information so that the rest of us can reproduce the problem on our setups.
If for whatever reason you cannot send your entire inputs, try to come up with smaller inputs that exhibit the same problems you are facing, and send those.
Thank you!
Hello @ladmanj,
But I'm getting these errors:
For example, the function SIZEOF(.text) in the linkerscript returns wrong value.
Please give more information about what you were trying to do. Because, unfortunately, I cannot read minds, and I especially cannot read minds from a distance. I cannot guess what exactly you were doing, based only on what you just said.
What would be useful is if you give me your complete input(s) and your complete command line(s) that led to the problems --- enough information so that the rest of us can reproduce the problem on our setups.
If for whatever reason you cannot send your entire inputs, try to come up with smaller inputs that exhibit the same problems you are facing, and send those.
Thank you!
Ok, this is the whole project. Please read the few comments in gdbstub.ld.in first. In the files aren't archived all the attempts I've made, these are lost now.
Thank you
Hello @ladmanj,
I have uploaded a modified Makefile
and a modified gdbstub.ld.in
for your code, which should help you get going a bit further.
A few things:
-msegelf
scheme is unfortunately still not supported by nasm
. (segelf
was actually proposed by none other than the nasm
maintainer himself, Mr. Anvin, but he has not yet implemented it there.) So if you want to link with nasm
code, you have to use -mno-segelf
for now.:
offset addressing scheme) that you want your code to use, even if the offsets will simply be 0. You cannot just say 0xfa700
and expect the linker to magically guess whether it means 0xf000:0xa700
, or 0xfa70:0x0000
, or something else. (The linker does not know how to read minds either...)
MEMORY
command in the modified linker script to see how to represent segment:
offset's for the -mno-segelf
scheme.-mcmodel=small
), you can have your data segment separate from your text segment (mostly this means ds
= ss
≠cs
). However, the read-only data (.rodata
) should be addressable from the same data segment. Again, as always, you must think explicitly about offsets within segments when figuring out how to lay out your code and data segments.nasm
, you probably also have the disassembler ndisasm
installed. Use it! Run it on your output file to get an idea of what code is generated.Thank you!
Thank you @tkchia.
You mentioned that nasm is not fully compatible with ia16 toolchain, can you recommend me which other assembler to use? I have no preference, I'm using nasm, because the author of the gdbstub I'm forking chosen that. Only the at&t syntax is not my cup of tea, but i can get familiar wit that too.
Best regards
Hello @ladmanj,
I have uploaded a modified
Makefile
and a modifiedgdbstub.ld.in
for your code, which should help you get going a bit further.A few things:
* The `-msegelf` scheme is unfortunately still not supported by `nasm`. (`segelf` was actually proposed by none other than the `nasm` maintainer himself, Mr. Anvin, but he has not yet implemented it there.) So if you want to link with `nasm` code, you have to use `-mno-segelf` for now. * When specifying memory areas, you _need_ to always explicitly think about the offsets (in the segment`:`offset addressing scheme) that you want your code to use, even if the offsets will simply be 0. You cannot just say `0xfa700` and expect the linker to magically guess whether it means `0xf000:0xa700`, or `0xfa70:0x0000`, or something else. (The linker does not know how to read minds either...) * See the `MEMORY` command in the modified linker script to see how to represent segment`:`offset's for the `-mno-segelf` scheme. * If you use the "small" memory model (`-mcmodel=small`), you _can_ have your data segment _separate_ from your text segment (mostly this means `ds` = `ss` ≠`cs`). However, the read-only data (`.rodata`) should be addressable from the same data segment. Again, as always, you must think explicitly about offsets within segments when figuring out how to lay out your code and data segments. * Also, if you are using `nasm`, you probably also have the disassembler `ndisasm` installed. Use it! Run it on your output file to get an idea of what code is generated.
Thank you!
Hello @ladmanj,
You can use nasm
, just not with -msegelf
for now, because this option is implemented only in the gcc-ia16
toolchain.
Thank you!
Hello @tkchia,
Regarding the Makefile you modified for me - you have deleted the long paths to CC and other tools - of course to be able use your own installation.
I have the long paths because i was unable to 'make install' the tools I've built by your script from build-ia16 on ubuntu 20.10, so I'm pointing to the folder where it was built.
If you know what the issue can be, please help. But I don't remember the particular step which failed and you also don't have a crystal ball as you mentioned few times :-)
Thanks
Hello @ladmanj,
You can use
nasm
, just not with-msegelf
for now, because this option is implemented only in thegcc-ia16
toolchain.Thank you!
Hi
I did understand it the first time, but the question was meant as "do you think I've better use some other asm and stay with -msegelf
, and which one will be the recommended one?".
EDIT: Oh I see now, only the as contained in ia16 can be used with -msegelf, because ... this option is implemented only in the gcc-ia16
toolchain.
I'm sorry.
Thank you
Hello @ladmanj,
If you know what the issue can be, please help.
No, there is no problem on your end. You can directly add .../prefix/bin
--- which is where build-ia16
"installs" everything --- to your $PATH
.
Alternatively, if you are using Ubuntu 18.04 or 20.04, I would recommend that you simply install the packages in my Ubuntu PPA. These should be much more stable. Also, these will be installed in the usual places (/usr/bin/
etc.).
Thank you!
Alternatively, if you are using Ubuntu 18.04 or 20.04, I would recommend that you simply install the packages in my Ubuntu PPA. These should be much more stable. Also, these will be installed in the usual places (
/usr/bin/
etc.).
Unfortunately not, I'm usually an early adopter and have already switched to ubuntu 20.10.
I will do the manual PATH modification - good point.
Thanks
Hi @tkchia,
Oh this is great!!! I had no idea of this linker capabilities, but I was asking for a documentation how the offsets are correctly defined.
MEMORY
{
// These are for absolute physical addresses
ram (!RX) : ORIGIN = DATA_SEG * 0x10 + DATA_OFFSET,
LENGTH = DATA_LENGTH
rom (RX) : ORIGIN = BASE_SEG * 0x10 + BASE_OFFSET,
LENGTH = BASE_LENGTH
// These are for offsets relative to the respective segments
ramoff (!RX) : ORIGIN = DATA_OFFSET, LENGTH = DATA_LENGTH
romoff (RX) : ORIGIN = BASE_OFFSET, LENGTH = BASE_LENGTH
}
Thank you!
Hello @tkchia,
Your Makefile and linkersctript seem to be great, but there is an problem left.
; Initialize rw data
initmem:
mov di,_data
mov cx,_edata
sub cx,_data
mov si,_etext
rep movsb
; Clear bss
mov di,_bstart
mov cx,_bend
sub cx,_bstart
mov al,0
rep stosb
retn
Leads to:
00000035 <initmem>:
35: bf 00 14 mov di,0x1400
38: b9 1d 14 mov cx,0x141d
3b: 81 e9 00 14 sub cx,0x1400
3f: be 54 00 mov si,0x54
42: f3 a4 rep movs BYTE PTR es:[di],BYTE PTR ds:[si]
44: bf 1e 14 mov di,0x141e
47: b9 60 14 mov cx,0x1460
4a: 81 e9 1e 14 sub cx,0x141e
4e: b0 00 mov al,0x0
50: f3 aa rep stos BYTE PTR es:[di],al
52: c3 ret
53: 90 nop
This is almost OK, only 3f: be 54 00 mov si,0x54
is a nonsense. 0x54 isn't the LMA of the .data section, where the in linkerscript defined symbol _etext should point to.
Interresting fact is, that in the binary file which I'm getting by ia16-elf-objcopy -j .text* -j .rodata* -j .data* --output-target=binary gdbstub.elf gdbstub.bin
the start of initialization data seems to be right after the .text and .rodata content.
The computation of _etext = . ;
by linker seems to be wrong as I was concerned already yesterday.
Thank you
Hi @tkchia
I have partly succeded with
SECTIONS {
.text :
{
*(.text) ; *(.text*) ;
_etext = . ;
} >romoff AT>rom
.data :
{
_data = . ;
*(.rodata) ; *(.rodata*) ;
*(.data) ; *(.data*) ;
_edata = . ;
} >ramoff AT>rom
.bss :
{
_bstart = . ;
*(.bss) *(COMMON)
_bend = . ;
} >ramoff AT>ram
The addresses in disassembly are looking really good, and the initialization data is where it should be in the ROM image. But this function still doesn't work and i can't see any error:
#define EOF (-1)
const char digits[] = "0123456789abcdef";
char dbg_get_digit(int val)
{
if ((val >= 0) && (val <= 0xf)) {
return digits[val];
} else {
return EOF;
}
}
Compiled as:
00000133 <dbg_get_digit>:
133: 89 e3 mov bx,sp
135: 8b 5f 02 mov bx,WORD PTR [bx+0x2]
138: b0 ff mov al,0xff
13a: 83 fb 0f cmp bx,0xf
13d: 77 04 ja 143 <dbg_get_digit+0x10>
13f: 8a 87 00 14 mov al,BYTE PTR [bx+0x1400]
143: c3 ret
The string is at this address:
00001400 g O .data 00000011 digits
EDIT: Both SS, DS, ES are set to 0xff00.
I can't understand what's wrong. I will run it in simulator next evening, but now it's almost 3 AM and I must go to sleep immediately.
Thank you.
Uff, this one is solved, originally i didn't realize that the init data next after the .text is reachable at by cs not the default ds.
initmem:
; Initialize rw data
mov di,_data
mov cx,_edata
sub cx,_data
mov si,_etext
rep cs movsb <--- magic cs here
; Clear bss
mov di,_bstart
mov cx,_bend
sub cx,_bstart
mov al,0
rep stosb
retn
Yes, completely my fault - but completely invisible for me :-(
Thank you for patience.
Hi all For your interest, I'm able now to do single instruction step, continue and memory examination in GDB, connected via serial port to gdb-server running on my hardware.
I have still problems continuing from different than original address of interruption and register updates, but maybe I will solve it soon. Regards
@ladmanj : looks like you are making progress. :-)
Hi all
Please, what's the best way to read byte from arbitrary memory address from the C function (using inline asm) addressed by 32 bit integer?
I was trying to split the 32bit integer (with 19 or 20 valid bits) to segment and offset and then inline asm to push ss and load it with the segment, then use ordinary 16bit pointer access in C and then inline asm to pop the original ss, but I failed to do so.
I don't understand the inline asm syntax, even looking to gcc manual :-( https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands
Thanks for help
Jakub
Hi
Maybe I should use far pointers and leave it in C only, but how? I can't find any documentation again what's the usage of such pointers :-(
Thanks J.
Hi
It seems that *val = *(__far volatile char *)addr;
is working, but I don't know if it's correct or not.
J.
Hello @ladmanj ,
It seems that
*val = *(__far volatile char *)addr;
is working, but I don't know if it's correct or not.
That should be fine. Note that addr
here needs to be a segment:offset pair expressed as a 32-bit integer --- high 16 bits are the segment, low 16 bits are the offset.
addr
should not be a flat absolute address. If you want to read from a flat absolute address, you must transform it into a segment:offset form first.
I don't understand the inline asm syntax, even looking to gcc manual :-( https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands
Basically you specify these things:
This is a very powerful inline assembly facility --- it allows inline assembly to jive with GCC's optimizer. But admittedly yes, it is a bit hard to use: you need to specify the inputs, outputs, and clobbers very precisely so that GCC does not produce incorrect code.
If you are not sure about using inline assembly, just write a separate assembly language module.
push ss and load it with the segment,
Erm, you probably do not want to mess with %ss
.
Thank you!
Hello @tkchia
Thank you for the advice. I didn't know that the the __far pointer must be consisting of segment:offset pair. From my amateur point of view, the flat memory address can be broken down in a arbitrary way providing addr=16*seg+ofs. Is that true or is there some limitation? The only limitation I see now is that the offset must not wrap in case of accessing an array.
It comes to my mind right now, that I must figure out whether gdb sends split address or flat memory address first in the RSP packet.
Thank you
Ps: maybe i will finally remember to not mess with SS, this time.
Hello @ladmanj,
From my amateur point of view, the flat memory address can be broken down in a arbitrary way providing addr=16*seg+ofs. Is that true or is there some limitation? The only limitation I see now is that the offset must not wrap in case of accessing an array.
That is the case, at least if you will only be addressing the first 1 MiB or memory in real mode --- this will always be the case on the 8086 or 80186.
(If, perhaps in the future, you want to access the HMA above 1 MiB or use protected mode on an 80286, then things are bit more complicated.)
Thank you!
Hello @ladmanj,
From my amateur point of view, the flat memory address can be broken down in a arbitrary way providing addr=16*seg+ofs. Is that true or is there some limitation? The only limitation I see now is that the offset must not wrap in case of accessing an array.
That is the case, at least if you will only be addressing the first 1 MiB or memory in real mode --- this will always be the case on the 8086 or 80186.
(If, perhaps in the future, you want to access the HMA above 1 MiB or use protected mode on an 80286, then things are bit more complicated.)
Thank you!
I am modifying gdb-stub that's originaly targeted to real mode (only) on 386 and higher to work on 8086 only. If somebody will want to add support of 286, it will be a separate task.
Now there is single byte access to arbitrary address in the 1 MiB space, so the address could be break down to seg an ofs in arbitrary way. That's done now.
Honestly, I have absolutely no clue how to break it in the case of memory larger than 1MiB.
Thank you
Hi @tkchia and all others
I am back for a while after a while :-) And again lost in the woods ...
I'm trying to reuse memory tester code I successfully used on other embedded platform for my not-PC-compatible board vith 8088 CPU.
Here's my make output:
$ make
ia16-elf-gcc -o memtest.ld -x c -P -E \
-DBASE_SEG=0xf800 \
-DDATA_SEG=0x0000 \
-DBASE_OFFSET=0 \
-DDATA_OFFSET=0 \
-DBASE_LENGTH=0x8000 \
-DDATA_LENGTH=0x1800 \
memtest.ld.in
ia16-elf-gcc -mcmodel=small -Werror -Os -ffunction-sections -fno-stack-protector -Iarch_8086 -I/home/ladmanj/workspace/rwt_memtest -march=i8088 -mno-segelf -o main.o -c main.c
ia16-elf-gcc -mcmodel=small -Werror -Os -ffunction-sections -fno-stack-protector -Iarch_8086 -I/home/ladmanj/workspace/rwt_memtest -march=i8088 -mno-segelf -o memtest.o -c memtest.c
ia16-elf-gcc -mcmodel=small -Werror -Os -ffunction-sections -fno-stack-protector -Iarch_8086 -I/home/ladmanj/workspace/rwt_memtest -march=i8088 -mno-segelf -o console.o -c console.c
ia16-elf-gcc -mcmodel=small -Werror -Os -ffunction-sections -fno-stack-protector -Iarch_8086 -I/home/ladmanj/workspace/rwt_memtest -march=i8088 -mno-segelf -o arch_8086/io.o -c arch_8086/io.c
nasm -o arch_8086/init.o -felf arch_8086/init.nasm
ia16-elf-ld -L/home/ladmanj/DataDisk/src/build-ia16-master/prefix/lib/gcc/ia16-elf/6.3.0/ -lgcc --script=memtest.ld -Map=memtest.map --verbose -melf_i386 -N -o memtest.elf main.o memtest.o console.o arch_8086/io.o arch_8086/init.o
GNU ld (GNU Binutils) 2.32.0.20190814
Supported emulations:
elf_i386_msdos_mz
elf_i386
i386elks
i386msdos
using external linker script:
==================================================
MEMORY
{
ram (!RX) : ORIGIN = 0x0000 * 0x10 + 0,
LENGTH = 0x1800
rom (RX) : ORIGIN = 0xf800 * 0x10 + 0,
LENGTH = 0x8000
boot (RX) : ORIGIN = 0xffff0, LENGTH = 0x10
ramoff (!RX) : ORIGIN = 0, LENGTH = 0x1800
romoff (RX) : ORIGIN = 0, LENGTH = 0x8000
bootoff (RX) : ORIGIN = 0x7ff0, LENGTH = 0x10
}
SECTIONS {
.text :
{
*(.text) ; *(.text*) ;
_etext = . ;
} >romoff AT>rom
.data :
{
_data = . ;
*(.rodata) ; *(.rodata*) ;
*(.data) ; *(.data*) ;
_edata = . ;
} >ramoff AT>rom
.bss :
{
_bstart = . ;
*(.bss) *(COMMON)
_bend = . ;
} >ramoff AT>ram
.boot :
{
*(.boot) ; *(.boot*) ;
} >bootoff AT>boot
/DISCARD/ : {
*(.comment)
*(.note.GNU-stack)
*(.eh_frame)
*(.rela.eh_frame)
*(.shstrtab)
*(.symtab)
*(.strtab)
}
}
==================================================
ia16-elf-ld: mode elf_i386
attempt to open /home/ladmanj/DataDisk/src/build-ia16-master/prefix/lib/gcc/ia16-elf/6.3.0//libgcc.so failed
attempt to open /home/ladmanj/DataDisk/src/build-ia16-master/prefix/lib/gcc/ia16-elf/6.3.0//libgcc.a succeeded
/home/ladmanj/DataDisk/src/build-ia16-master/prefix/lib/gcc/ia16-elf/6.3.0//libgcc.a
attempt to open main.o succeeded
main.o
attempt to open memtest.o succeeded
memtest.o
attempt to open console.o succeeded
console.o
attempt to open arch_8086/io.o succeeded
arch_8086/io.o
attempt to open arch_8086/init.o succeeded
arch_8086/init.o
ia16-elf-ld: console.o: in function `xprintf':
(.text.xprintf+0x154): undefined reference to `__umodsi3'
ia16-elf-ld: (.text.xprintf+0x167): undefined reference to `__udivsi3'
ia16-elf-ld: link errors found, deleting executable `memtest.elf'
make: *** [Makefile:68: memtest.elf] Error 1
rm memtest.o console.o arch_8086/init.o main.o arch_8086/io.o
The umodsi3 and udivsi3 functions are unreachable even I have tried everything i found in every regarding topic here on github. Please look in the makefile how the path to libgcc.a is determined.
Please help.
Whole project is attached.
Thank you!
$ ia16-elf-gcc -v
Using built-in specs.
COLLECT_GCC=ia16-elf-gcc
COLLECT_LTO_WRAPPER=/home/ladmanj/DataDisk/src/build-ia16-master/prefix/libexec/gcc/ia16-elf/6.3.0/lto-wrapper
Target: ia16-elf
Configured with: ../gcc-ia16/configure --target=ia16-elf --prefix=/home/ladmanj/DataDisk/src/build-ia16-master/prefix --enable-libssp --enable-languages=c,c++ --with-newlib --disable-libstdcxx-dual-abi --disable-extern-template --disable-wchar_t --disable-libstdcxx-verbose --disable-libquadmath --with-gmp=/home/ladmanj/DataDisk/src/build-ia16-master/prefix-gmp --with-mpc=/home/ladmanj/DataDisk/src/build-ia16-master/prefix-mpc --with-mpfr=/home/ladmanj/DataDisk/src/build-ia16-master/prefix-mpfr --with-isl=/home/ladmanj/DataDisk/src/build-ia16-master/prefix-isl
Thread model: single
gcc version 6.3.0 (GCC)
$ ia16-elf-ld -v
GNU ld (GNU Binutils) 2.32.0.20190814
Here's a few rambling thoughts as I work with gcc-ia16 on a platform which is very ROM-centric, with little RAM:
.fartext/.farrodata
segment per compilation unit - like many 8086 compilers seem to do - would be much more economical....farrodata
, once the ability to detect being in the same segment were to be implemented - as it wouldn't need to reach to another segment, not always anyway..rodata
only, which means they occupy the data segment, and thus RAM, on my target. This is easy to work around at the cost of performance - passing -fno-jump-tables
to GCC does the trick.Thank you for your hard, hard work. Have you considered a way to donate towards future development efforts?
(Also, it might be a good idea to enable GitHub's Discussions feature to provide non-bug-report/feature-request user forums, as opposed to this issue)
Hello @asiekierka,
When writing platform-specific code, I'd think generating a .fartext/.farrodata segment per compilation unit - like many 8086 compilers seem to do - would be much more economical...
I'm not sure what the difference would be, using one segment per function or compilation unit - the linker script ends up placing all the functions in one of two far text segments in the end anyways (for a maximum of 128K code).
once the ability to detect being in the same segment were to be implemented - as it wouldn't need to reach to another segment, not always anyway.
I'm not sure about this either, since far code will always end up being in one of two far segments, and near code won't ever be mixed in. Since the segment can't be known at compile time (unless its a near function or a non-standard linker script were used with in conjunction with .section function attributes), all far functions are compiled to be called the same way, using far prologue/epilogues.
Thank you!
I'm not sure what the difference would be, using one segment per function or compilation unit - the linker script ends up placing all the functions in one of two far text segments in the end anyways (for a maximum of 128K code).
I'm using my own linker script, as I'm targetting a non-DOS/ELKS platform... With segelf enabled on the medium memory model (I might have a mistake somewhere), each function seems to be padded to a 16-byte boundary, which feels a little wasteful.
I'm not sure about this either, since far code will always end up being in one of two far segments, and near code won't ever be mixed in.
It's about far data, not far code. It would make more sense if the compiler mechanisms proposed in https://github.com/tkchia/gcc-ia16/issues/79 were implemented - this would make it easy to access data in the same section as the code with a mere segment override; an option for per-compilation-unit sections would then make it easier for end-users to benefit from the optimization without manually planning out sections, though I admit the benefit here is negligible.
I've partially worked around putting every function in its own segment
by digging into ia16.c
and realizing that -fno-function-sections
will also put every file in its own segment instead. I wonder if it's possible to decouple the two, but for now I achieved what I wanted to - a ~2-3% reduction in total filesize and a tiny speed boost (on V30MZ, a far call takes 10 cycles, but PUSH CS
+ a near call takes only 7).
About jump tables, I've made a patch to put them in the .text
section and adjust the emitted jmp
to %cs
accordingly; however, I'm entirely not sure if it's upstream-quality.
Hello
I know, this isn't bug report, i don't want to be annoying. Is there any other way to contact the community involved in ia16 asm and gcc topic?
Thank everyone 😊