Welcome, Guest. Please login or register.

Author Topic: Threaded Code  (Read 6375 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Threaded Code
« on: November 24, 2010, 02:31:29 PM »
So here I am thinking about an idea... And it turns out my idea already has a name, "Threaded Code"!

My question is, is there any C/C++ legal way to jump to an address? A computed Goto if you will...

goto *someaddress;

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #1 on: November 24, 2010, 02:55:18 PM »
Quote from: ElPolloDiabl;594070
Don't no too much about C, but I read that it explicitly doesn't allow such things.
Yeah... I think I've found a gcc extention that allows it... But I'd prefer something more portable :(

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #2 on: November 24, 2010, 02:59:44 PM »
Quote from: skurk;594072
Yes, something like this should work

void (*app)() = (void(*))0x123456;

and then later

app();

I can't test this right now, but I'm pretty sure the above would jump to addres 0x123456.
No, that's a function pointer which will invoke the calling convention (saving registers etc) which would add a lot of overhead a threaded code Virtual Machine...

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #3 on: November 24, 2010, 03:06:09 PM »
Quote from: Karlos;594073
The most obvious legal way to do this is to use a table of function pointers.
I appreciate the advice (and from skurk too), but a function pointer is just too expensive in this regard... My VM needs to run on my 100mhz ARM M3 microcontroller... We have to think lightweight! But I also need it to be portable so I can test it on my test machine... An x86... So ARM Asm is going to be problematic...

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #4 on: November 24, 2010, 03:08:11 PM »
Quote from: Karlos;594076
Well the gcc extension is as portable as gcc is. If you keep your dubious computed branch target code to just one translation unit, you could always make it an exception in your makefile and have everything else all nice and ANSI.
Yeah, that's almost certainly the most intelligent way to do it! :)

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #5 on: November 24, 2010, 03:10:22 PM »
Quote from: bloodline;594074
No, that's a function pointer which will invoke the calling convention (saving registers etc) which would add a lot of overhead a threaded code Virtual Machine...


Quote from: skurk;594078
Oh, then I misunderstood your question. :-)


Not really, your advice was good, I didn't provide enough specification for you! As Karlos has also pointed out function pointers are the legal way to do this... I just don't want to save the registers for every function call!

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #6 on: November 24, 2010, 03:39:50 PM »
If I'm happy to stay with gcc, then this seems to be the winner:

http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html

Bit sucky really...

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #7 on: November 24, 2010, 06:16:46 PM »
Quote from: commodorejohn;594103
If you're just writing for ARM and testing on x86, couldn't you use a conditionally-compiled bit of assembler like:
Code: [Select]
#ifdef ARM
asm { /* whatever */}
#else
asm { /* x86 equivalent */}
#endif
or somesuch?
It's not the code paths that I have a problem with... it's maintaining two code paths :lol: and in ASM too... kinda defeats the point of using C in the first place ;)

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #8 on: November 24, 2010, 07:26:07 PM »
Quote from: itix;594110
Necessarily it is not saving the registers for every function call.  It is platform specific...
If I have a function that takes no arguments and returns nothing, and acts only on global variables... then will the compiler optimize for not saving any registers? I doubt it :(

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #9 on: November 24, 2010, 08:13:37 PM »
Quote from: Karlos;594120
That depends. If shovel it all into the same translation unit so it can see the scope of everything whilst it is compiling, you'd be surprised...
Unfortunately the ARM compiler I'm using doesn't allow me access to the asm (I support I could disassemble it...) so I can't see what's really going on...

But you are right though, I've seen some pretty incredible optimization done by a C complier before...

I'm rapidly losing interest in this idea... as my real life workload has just increased :(

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #10 on: November 24, 2010, 11:27:32 PM »
Quote from: yakumo9275;594170
protothreads / coroutines. But mostly, C was not built to do what you want to do. Look at a lot of Forth interpreters and see how they do it, they pioneered the threaded code model, but mostly the ones I've seen use this method are written in assembler.
Yeah, just a note to say I'm not talking about Multithreading (I don't want to run more than one task) I'm talking about a method of implementing a Virtual machine using a table of functions/subroutines... What little reading I have done has mostly been around forth... And yeah.. C really wasn't build for this :(

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #11 on: November 25, 2010, 12:02:23 AM »
Quote from: Karlos;594188
If it helps, I've built a "virtual processor" using function tables / giant switch case depending on compiler settings as an experiment. Can send you the source if it helps.

PM me if you are interested.
Very kind, but I already have that! When last discussed this topic I was convinced that a giant switch case was the way to go and you helpfully sent me your own experiments! My project never progressed very far it was just too slow for the task I had intended (basic DSP work)...

Now I'm playing with ARM microcontrollers I'm wondering if I can get them to do something rather fun... That is to say replace an ASIC in a circuit... Or maybe even an old 16bit CPU... ;)

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #12 on: November 25, 2010, 12:19:28 AM »
Quote from: Karlos;594202
Is it the one that has a test virtual program to generate the Mandelbrot set as a PPM file?
I don't recall any test code...

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #13 on: November 25, 2010, 01:05:24 AM »
Quote from: Karlos;594217
Then maybe the version you have is old? This one even had a whole bunch of evil C macros that allowed the VM code to be written within the C source:

Code: [Select]



void nativeAllocBuffer(VMCore* vm)
{
  // width/height in r2/r3
  // return buffer in r1
  int w = vm->getReg(_r2).s32();
  int h = vm->getReg(_r3).s32();
  vm->getReg(_r1).pU8() = new uint8[w*h];
  printf("Allocated buffer [%d x %d]\n", w, h);
}

void nativeFreeBuffer(VMCore* vm)
{
  // expects buffer in r1
  delete[] vm->getReg(_r1).pCh();
  vm->getReg(_r1).pCh() = 0;
  printf("Freed buffer\n");
}

void nativeWriteBuffer(VMCore* vm)
{
  // writes buffer in r1 to filename in r4
  // expects width/height in r2/r3
  const char* fileName = vm->getReg(_r16).pCh();
  int w = vm->getReg(_r2).s32();
  int h = vm->getReg(_r3).s32();
  if (fileName) {
    FILE *f = fopen(fileName, "wb");
    fprintf(f, "P5\n%d\n%d\n255\n", w, h);
    fwrite(vm->getReg(_r1).pCh(), 1, w*h, f);
    fclose(f);
    printf("Wrote buffer '%s'\n", fileName);
  }
}

void nativePrintCoords(VMCore* vm)
{
  printf(
    "Coords %4d, %4d (%.6f, %.6f)\n",
    (int)vm->getReg(_r7).s32(),
    (int)vm->getReg(_r5).s32(),
    vm->getReg(_r9).f32(),
    vm->getReg(_r4).f32()
  );
}

_VM_CODE(makeFractal)
{
  // r1 = pixel data address
  // r2 = width in pixels
  // r3 = height in pixels
  // r4 = cY (float pos, starting at yMin)
  // r5 = y (int) pixel
  // r6 = xMin (float)
  // r7 = cX (float pos, starting at xMin)
  // r8 = fStep
  // r9 = x (int) pixel
  // r10 = iStep (1)

  _save       (_mr1)           // 2 : save r1
  _ldq        (0, _r5)         // 1 : y (r5) = 0
  _ld_16_i32  (255, _r10)      // 2 : max iters

  // y-loop
  _ldq        (0, _r9)         // 1 : x = 0
  _move_32    (_r6, _r7)       // 1 : cX = xMin

  // x-loop                        do {

  _move_32    (_r7, _r11)            // 1 : zx = cX
  _move_32    (_r4, _r12)            // 1 : zy = cY
  _ldq        (0, _r13)              // 1 :  n = 0

                                      // do {

  _move_32    (_r11, _r14)           // 1
  _mul_f32    (_r11, _r14)           // 1 : zx2 = zx*zx
  _move_32    (_r12, _r15)           // 1
  _mul_f32    (_r12, _r15)           // 1 : zy2   = zy*zy

  _move_32    (_r7,  _r16)           // 1 : new_zx = cX
  _add_f32    (_r14, _r16)           // 1 : new_zx += zx2
  _sub_f32    (_r15, _r16)           // 1 : new_zx -= zy2

  _add_f32    (_r15, _r14)           // 1 : r14 = zx*zx + zy*zy (for loop test)

  _move_32    (_r11, _r15)           // 1 : tmp = zx
  _mul_f32    (_r12, _r15)           // 1 : tmp *= zy
  _add_f32    (_r15, _r15)           // 1 : tmp += tmp2
  _add_f32    (_r4,  _r15)           // 1 : tmp += cY (tmp = 2*zx*zy+cY)

  _move_32    (_r15, _r12)           // 1 : zy = tmp
  _move_32    (_r16, _r11)           // 1 : zx = new_zx
  _addi_16    (1, _r13)              // 2 : n++

  _ld_32_f32  (4.0f, _r16)             // 3
  _bgr_f32    (_r14, _r16, 2)          // 2
  _bls_32     (_r13, _r10, -23)        // 2

  _mul_u16    (_r13, _r13)             // 1
  _st_ripi_8  (_r13, _r1)              // 1 : out = n
  _add_f32    (_r8, _r7)               // 1 : cX += fStep
  _addi_16    (1, _r9)                 // 2 : x += iStep

  _bls_32     (_r9, _r2, -(6+23+3+1))    // 2 : } while (x < width)

  _add_f32    (_r8, _r4)                 // 1 : cY += fStep
  _addi_16    (1, _r5)                   // 2 : y += iStep
  _bls_32     (_r5, _r3, -(5+5+6+23+1))  // 2 : } while (y < height)

  _restore    (_mr1)                     // 1
  _ret
};

_VM_CODE(calculateRanges)
{
  // calculates xMin in r6, xMax in r7, step in r8
  _move_32    (_r5, _r6)
  _sub_f32    (_r4, _r6)         // r6 = r5-r4 (total y range)
  _s32to_f32  (_r2, _r7)         // r7 = (float) r2
  _move_32    (_r7, _r9)
  _mul_f32    (_r6, _r7)         // r7 *= r6
  _s32to_f32  (_r3, _r6)         // r6 = (float) r3
  _div_f32    (_r6, _r7)         // r7 /= r6
  _move_32    (_r7, _r8)
  _div_f32    (_r9, _r8)
  _ld_32_f32  (0.75f, _r6)
  _sub_f32    (_r7, _r6)
  _add_f32    (_r6, _r7)

  _ret
};


_VM_CODE(virtualProgram)          // a vm function
{
  _ld_16_i16  (512, _r2)
  _ld_16_i16  (512, _r3)
  _calln      (nativeAllocBuffer)
  _ld_32_f32  (-1.25f, _r4)       // yMin
  _ld_32_f32  (1.25f, _r5)        // yMax
  _call       (calculateRanges)
  _call       (makeFractal)
  _lda        (&quot;framebuffer.pgm&quot;, _r16)
  _calln      (nativeWriteBuffer)
  _calln      (nativeFreeBuffer)
  _ret
};
Old! I'll say... We were last talking about this in 2003... Hmmm ilike the c macros idea... That allows you to test the functions! :)

Offline bloodlineTopic starter

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12113
    • Show all replies
    • http://www.troubled-mind.com
Re: Threaded Code
« Reply #14 on: November 25, 2010, 01:13:02 AM »
Quote from: Karlos;594219
I can send you this version. It basically is a bit crap in that it compiles to a single executable containing the embedded test. The reason being, the final target was for a library which included all the necessary loading/linking stuff. It should compile on any posix compliant system.
Kind offer, but I don't have much time right now to develop this idea further :) but I am keen to disccus vm techniques so that as time permits I will have a clear idea of the issues and maybe build something! :idea:

Though right now I'm just fighting insomnia... I've got an early start tomorrow and for some reason that means I am unable to get the rest in need :(