need some help with rewriting from sasc to gcc, and for mixing 68kbinary with aos4 library.

11 posts / 0 new
Last post
kas1e
kas1e's picture
Offline
Last seen: 1 year 5 months ago
Joined: 2010-11-30 15:30
need some help with rewriting from sasc to gcc, and for mixing 68kbinary with aos4 library.

We currently works on porting dopus5 to all amigang platforms (include our os4 of course, there is SF page), and Xenic almost rewrite dopus5.library to gcc (our plan firstly rewrite library, make a native builds, and then start with main programm and modules). So, he almost rewrite it, but have some problems in which i hope someone can help us, there is relewant part from him:

There is issues like SASC setreg()/getreg(), chip, & ARGS that don't seem to exist in GCC. How we can replace it ? Also SDI didn't have REG_A6, etc declarations.. The "__chip" only appears in one place and it is contingently used if the Intuition library version is 38 or less. I think that means AmigaOS2 and don't think we need to make Dopus5 backward compatable that far. We can probably just get rid of that line of code. Alternatively, a short function can be added to allocate the chip memory and copy the data to that location. I seem to remember seeing a macro replacement for getreg() on some Amiga WEB site but don't remember where. Maybe someone else has a substitute we can use. I don't think we need to worry about the ARGS statement. From what I can tell from some Internet research, ARGS means nothing to GCC and can simply be defined as ARGS(x)=x in a header file.

And the last question is: Should we add to main 68k binary anything, to make it works with aos4 native library when it will be done ? As far as i remember there need some changes to make such combo works ? (that need to do because before starting to rewrtite main programm, we want to test deeply if we rewrite dopus5.library to native format with no bugs and problems).

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
I can answer the last one.

I can answer the last one. You can use an OS4 library with a 68K executable unchanged. IOW a 68K program can open and use an OS4 native library unchanged. As if it was an updated version.

What you need to do is export a 68K interface in the library. That is it just needs a 68K jump table with 68K wrapper functions diverting to native PPC functions. Check out the docs in the SDK for porting libraries. There are also tools involved that will generate all this stuff for you. IIRC one is called FDLTool. You'll need to convert the FD file to XML using an SDK tool I think.

Been a while since I did this but I made up the ground work when writing CIAgent. Although that was customised as I took the 68K stuff the tools generated and merged it into a commodity. If you can't find what you need I will dig into the SDK again to see what tools are needed. :-)

kas1e
kas1e's picture
Offline
Last seen: 1 year 5 months ago
Joined: 2010-11-30 15:30
Another question: how to

Another question: how to replace sasc's getreg/putreg on gcc ? In the code we have a lot of such kind of strings:

getreg

  1. hook->hook.h_Entry=(ULONG (*)())string_edit_hook;
  2. hook->a4=getreg(REG_A4);
  3. hook->a6=getreg(REG_A6);
  1. L_StoreGadgetValue(OBJLIST(msg->IDCMPWindow),msg,(struct MyLibrary *)getreg(REG_A6));
  1. prog->pw_A4=getreg(REG_A4);
  1. startup->a4=getreg(REG_A4);
  1. hook->hook.h_Entry=(ULONG (*)())string_edit_hook;
  2. hook->a4=getreg(REG_A4);
  3. hook->a6=getreg(REG_A6);

putreg

  1. putreg(REG_A4,data->a4);
  1. putreg(REG_A4,prog->pw_A4);
  1. putreg(REG_A4,startup->a4);
  1. putreg(REG_A4,hook->a4);
  2. putreg(REG_A6,hook->a6);

We use SDIs, but A4 and A6 do not defined there, so we define it like:

  1. #define REG_A4 12
  2. #define REG_A6 14

So we need getreg/putreg functions which we can just add to misc.c and compile it with. Someone told us that we should leave getreg() and setreg() for SAS/C but when compiling for GCC it can be just omitted because we are not coding for small data model. But i am not sure if we can just comment it out at all.

Any help appricated.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
There's somehing here that

There's somehing here that can convert REG types to OS4 but is quick and dirty:
http://os4depot.net/index.php?function=showfile&file=development/utility/changereg.lha

Just found this again, a GCC porting guide:
http://os4depot.net/share/document/tutorial/gccportnotes.guide

Now, obviously, those registers are hardcodded to the compiler DOpus 5 was built with. But to be portable they have to go. Especially in hook functions where they shouldn't be needed as the OS takes care of all that stuff. At least it is meant too. Can the hooks be modified so the OS takes care of the semantics of register placement?

What else I wonder is what A4 and A6 contain? Does the code control them? If possible you could just define them as another global variable and write your own getreg()/putreg() macros that access the variables. Not perfectly clean but should work.

Whatever is is doing, does it do more than save them and restore them? A4 would be global variable base and A6 library base. If it really changes them and especially A4 for its own use then it would be hacking another global space in there which seems unlikely and impossible almost to port. But I suspect it wouldn't do that. You should be able to ignore them and just invoke CallHoookPkt().

kas1e
kas1e's picture
Offline
Last seen: 1 year 5 months ago
Joined: 2010-11-30 15:30
Xenic make a replacement for

Xenic make a replacement for getreg(), but still haven't success with putreg():

Here is the macro replacement for getreg():

  1. #define GET_REG(reg) \
  2. ({ \
  3. register unsigned long ret; \
  4. \
  5. __asm__ __volatile__ \
  6. ( \
  7. "movl %%" #reg ",%0\n": \
  8. "=r"(ret)::"cc" \
  9. ); \
  10. \
  11. ret; \
  12. })

He did manage to make a limited putreg() replacement that he used to test the getreg() replacement but it only works with text input. We need it to work with a pointer for input. Here is what he have for putreq():

  1. #define PUT_REG(reg,val) \
  2. ({ \
  3. \
  4. __asm__ __volatile__ \
  5. ( \
  6. "movl #"#val"," #reg"\n" \
  7. ); \
  8. })

That works with text like: PUT_REG(a4,999) but he don't know how to get it to work with a pointer. The putreg() and getreg() replacements must be inline 68k assembler code because C code will change the registers when it runs.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
Good to see sone progess but

Good to see sone progess but IMHO it's in the opposite direction. For one thing that looks like x86 assembly and only useful for x86 AROS. Another thing is it isn't portable and doesn't allow you to progress beyond OS3 68K. Futhermore you might as well use the original code as is if you still need to resort to assembly and direct manipulation of registers.

How much code relies on modifying A4/A6? From what you have shown me it is in hooks or string hooks. But I don't know why it is saving registers like that in a structure. Unless it is using that above the stack. Hooks have the low level and high level entry points. Low level for ASM and register saving then calling the high level function and restoring registers after. Also SAS/C provides features to use register parameters and protect the global register in C function calls so what ever it is doing shouldn't be neccessary.

For example:

  1. * With a compiler capable of registerized parameters, such as SAS C, you
  2. * can put the C function in the h_Entry field directly. For example, for
  3. * SAS C:
  4. *
  5. * ULONG __saveds __asm HookFunc(register __a0 struct Hook *hook,
  6. * register __a2 APTR object,
  7. * register __a1 APTR message);

I can see I will have to take a look at the source code myself to see what's problem is and why it's tied itself to non-portable C style code. :-)

kas1e
kas1e's picture
Offline
Last seen: 1 year 5 months ago
Joined: 2010-11-30 15:30
@hypex For one thing that

@hypex


For one thing that looks like x86 assembly and only useful for x86 AROS.

? Its a gcc/m68k inline asm


Another thing is it isn't portable and doesn't allow you to progress beyond OS3 68K.

We firstly want to migrate to 68k-gcc only, and when that will works, we will clean up library for port it to all others. So now not portability of getreg/putreg matter (we will remove them alltogether later), we just now need 68k-gcc library to clean up it better in working stage. And because of that want to leave for first version of gcc-library as much as possible of original stuff to avoid any of possible bugs at first stage.


How much code relies on modifying A4/A6?

Only that one which i show, nowhere else (yep, hooks and string hooks). Thats if you mean only those putreg/getregs. But if you mean general usage of registers, then for example A6 is used everythere. Check for example backfill hook:

original sasc code

  1. void __asm __saveds L_SetReqBackFill(
  2. register __a0 struct Hook *hook,
  3. register __a1 struct Screen **screen,
  4. register __a6 struct MyLibrary *libbase)

That library function later used from the main binary like this:

  1. SetReqBackFill(&GUI->req_pattern.hook,&GUI->screen_pointer);

So while main binary still keeps the same 68k-sasc, for gcc-library we do with help of SDI:

our gcc replacement

  1. //proto
  2.  
  3. LIBPROTO(L_SetReqBackFill, void,
  4. REG(a0, struct Hook *hook),
  5. REG(a1, struct Screen **screen),
  6. REG(a6, struct MyLibrary *libbase));
  7.  
  8. //function itself
  9. void LIBFUNC L_SetReqBackFill(
  10. REG(a0, struct Hook *hook),
  11. REG(a1, struct Screen **screen),
  12. REG(a6, struct MyLibrary *libbase))
  13. {
  14. blablalb original code
  15. }

+ in libvector/libinit code do:

LFUNC_FA_(L_SetReqBackFill) \

together with all the other functions.


But I don't know why it is saving registers like that in a structure. Unless it is using that above the stack.

Imho because it was SASC only, with all that __saveds and small data models initially (so stack and stuff).


I can see I will have to take a look at the source code myself to see what's problem is and why it's tied itself to non-portable C style code. :-)

Currently not portability worry us, but making a working 68k-gcc library. When gcc version will produce us working-as-sasc-one-version, then we will remove all the non-portable things step by step.

You can grab initiall sasc source of library here:
svn://svn.code.sf.net/p/dopus5allamigas/code/trunk/Library/

And our current branch of library here:
svn://svn.code.sf.net/p/dopus5allamigas/code/branches/branch_v1/Library/

And you can follow discussion about here:
http://sourceforge.net/p/dopus5allamigas/discussion/dev/thread/576ca5ad/?page=0

AA

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
@kas1e ? Its a gcc/m68k

@kas1e

? Its a gcc/m68k inline asm

I refer to this:
"movl #"#val"," #reg"\n" \

A movl is an x86 instruction. On 68K it would be move.l. This should break in the compiler if targeting 68K.

We firstly want to migrate to 68k-gcc only

Okay I understand.

Only that one which i show, nowhere else (yep, hooks and string hooks).

I took a look at the code and now see what you mean!

As a comparison check out this library example from StormC4 from ADCD2.1:

  1. int AddTwo(register __d0 int a, register __d1 int b, register __a6 LibBase *base)
  2. {
  3. return base->last_result = a + b;
  4. }

Imho because it was SASC only, with all that __saveds and small data models initially (so stack and stuff).

That should have been enough but I see it also uses IPC for it's code modlues as well as the library. Still, a library would need access to globals so I thought SAS/C would do that without register hacking. I know it directly supports interupts which have similar requirements. Best move would be IMHO to replace register hacks with proper atrribute for saving/restoring global register and/or library base. And then find GCC way. Either way replace with define.

Unless it is really too far gone and creates its own globals for each task or something. That would be hard to manage! How on earth did they port it to Windows? :-O

Will check out links. :-)

salass00
salass00's picture
Offline
Last seen: 1 year 1 month ago
Joined: 2011-02-03 11:27
@hypex The assembler used by

@hypex

The assembler used by gcc, gas, uses MIT syntax which is somewhat different from the Motorola syntax which is used in Amiga assembler compilers.

See the section labeled "Syntax" here (you'll need to scroll down a bit to find it):
http://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_18.html

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
@salass00 Okay I see. Still,

@salass00

Okay I see. Still, it looks like the standard systax is still accepted. But if MIT systax is used regardless I would ave expetced a movel, not movl. 68K has no mov instruction, it has a move.

kas1e
kas1e's picture
Offline
Last seen: 1 year 5 months ago
Joined: 2010-11-30 15:30
@hypex Just a different

@hypex
Just a different syntax, different compilers, different ways.. make no problems for anyone who just want final results what kind of syntax is (and we of course test that kind of syntax already when i show replacement example before). Anyway, Xenic already make replacements and we currently test them. Maybe someday someone will in interest in them and will found via google that thread, so there is:

  1. /* compile = gcc -o test test.c */
  2.  
  3. #include <stdio.h>
  4.  
  5. void *value = NULL;
  6.  
  7. #define PUT_REG(reg,val) \
  8. ({ value = val; \
  9. \
  10. __asm__ __volatile__ \
  11. ( \
  12. "movl _value," #reg"\n" \
  13. ); \
  14. })
  15.  
  16. #define GET_REG(reg) \
  17. ({ \
  18. register unsigned long ret; \
  19. \
  20. __asm__ __volatile__ \
  21. ( \
  22. "movl %%" #reg ",%0\n": \
  23. "=r"(ret)::"cc" \
  24. ); \
  25. \
  26. ret; \
  27. })
  28.  
  29.  
  30. int main(int argc, char **argv)
  31. {
  32. char *string = "testing";
  33. char *result = NULL;
  34.  
  35. PUT_REG(a4,string);
  36. result = GET_REG(a4);
  37.  
  38. printf("result= %s\n", result);
  39.  
  40. }

I also have some help from Frank, and he says that it can be even just as :

----

  1. register unsigned long REG_A4 __asm("a4");
  2. register unsigned long REG_A6 __asm("a6");
  3.  
  4. #define getreg(x) x
  5. #define putreg(x,y) x = (y)

A4 is used as small data base register, when compiling a source in small data mode (sasc) But when you don't then this register is free for other tasks (gcc).

A6 will usually contain the library base. When it is no longer available, then you must find other ways to obtain it. I guess you only have to care about A6. When something needs A6, then you have to provide the library base.
----

So in end we even can comment them out imho and only provide "right" library base when its need it.

Log in or register to post comments