r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[rebcode] Rebcode discussion

Steeve
20-Feb-2007
[1760]
my parser was just a proof of concept, i agree there is a lot of 
optimizations to do
BrianH
20-Feb-2007
[1761]
If you are really evil, you could fill a BRAB block with the offsets 
of every Z80 operation into the offsets of their equivalent rebcode 
operations and turn every branch into an address calculation, a BRA 
to a label before the BRAB, then the BRAB.
Steeve
20-Feb-2007
[1762]
hmm...
BrianH
20-Feb-2007
[1763]
It would mean a 64K element BRAB block for every 64K set of memory, 
in addition to the size of the generated code.
Steeve
20-Feb-2007
[1764]
hurg !!!
BrianH
20-Feb-2007
[1765]
You can't run REBOL on a cell phone, you know. Everything else has 
plenty of RAM :)
Steeve
20-Feb-2007
[1766]
yes but it's not ROM but RAM, and evil programms can rewrite opcodes
BrianH
20-Feb-2007
[1767]
So, you can keep track of which areas of RAM have code in them and 
fix up the rebcode offsets when they are modified.
Steeve
20-Feb-2007
[1768]
yes Brian, all is possible ;-)
BrianH
20-Feb-2007
[1769x4]
You can even implement memory protection by filling the areas of 
the BRAB block that correspond to inappropriate areas of RAM with 
branch offsets to error-handling code.
That could be the default value to fill the BRAB block with. For 
that matter, if the error handling code directly follows the BRAB 
block you can use the value 0 to fill the BRAB block with by default.
You can even do this incrementally by filling in the code block as 
you go along and fixing up the offsets in the BRAB block as you generate 
the code that they point to..
The code generator can be your default code too, so code will get 
generated on the fly.
Steeve
20-Feb-2007
[1773]
yep, i follow u
BrianH
20-Feb-2007
[1774]
There is no reason that the generated rebcode need be in the same 
order in its block that the original code is in its context. The 
BRAB block adds a layer of indirection, making the memory virtual.
Steeve
20-Feb-2007
[1775]
yes, i agree
BrianH
20-Feb-2007
[1776]
If you generate it as you go along, the rebcode will be generated 
in the order that it is executed.
Steeve
20-Feb-2007
[1777]
it's the case currently
BrianH
20-Feb-2007
[1778]
If you keep the Z80 memory in a binary! and make changes to it, whenever 
code at an offset already covered by the BRAB block is modified you 
would change that offset in the BRAB block to the default and mark 
the associated section of the rebcode as free. That way the next 
time you branch to that offset it would retranslate the Z80 to rebcode 
and put that rebcode in the first free spot big enough. You could 
even break up your code into blocks of around the same size and branch 
between them, to reduce fragmentation.
Steeve
20-Feb-2007
[1779]
hmmm
BrianH
20-Feb-2007
[1780x3]
You will likely have some rebcode that corresponds to the same areas 
of Z80 memory more than once, but memory is cheap on every platform 
REBOL runs on, particularly compared to a Z80.
You can have all of your generated code segments be added as snippets 
of the same length if you wrap them in a block surrounded by the 
same code. For that matter, only that code block would need to be 
changed when changing the generated rebcode. You could even handle 
the freelist with ease by swapping marker code into free areas.
That would handle fragmentation issues in your generated code block 
with ease.
Steeve
20-Feb-2007
[1783x3]
and if i include my snipset in conditionnal block s, i will not have 
to recalculate offset of segments ?
or into a loop 1 block! ?
all snipsets will have the same relative offset
BrianH
20-Feb-2007
[1786]
Or an ift block! where the t value would be set by freelist settings 
or something.
Steeve
20-Feb-2007
[1787x3]
yep
it could be usefull to interrupt the execution at any point
after a break point for example
BrianH
20-Feb-2007
[1790x2]
If you fill in the whole rebcode block with code snippets of fixed 
length and then just swap in the code blocks you want, you wouldn't 
even need to alter the BRAB block - you could just change the code 
block references. For that matter, multiple references to the same 
code block could be just that, rather than copies, saving memory.
The main code block could be generated too, and all of your Z80 rebcode 
could be generated, and you could do the assembly yourself during 
the generation using code based on the standard assembler.
Steeve
20-Feb-2007
[1792]
hmmm
BrianH
20-Feb-2007
[1793]
The important part to duplicate from the assembler is the binding 
code. You won't have to duplicate the label fixup code, as you will 
be doing your own fixups. You might want to use label statements 
as markers for your own purposes though.
Steeve
20-Feb-2007
[1794]
yep
BrianH
20-Feb-2007
[1795]
If you go with the fixed main code block prefilled with snippets, 
the unchanging length of that block would lend stability to the rebcode 
interpreter. REBOL tends to crash if modifications to code that it 
is running at the time increase the length of the code block enough 
to force a reallocation of that block.
Steeve
20-Feb-2007
[1796x2]
ok , noted
ok, noted
BrianH
20-Feb-2007
[1798]
If you have each snippet be just this:
    IFT []
    BRA top

then the size of the main code block could be minimized, and the 
state of the T flag at the beginning of each snippet could control 
conditional execution.
Steeve
20-Feb-2007
[1799]
if think i will choose this option
BrianH
20-Feb-2007
[1800x5]
Then, you would just change the reference to the block to be something 
else when you fill in the snippet.
All of the infrastructure code would be at the top of the main code 
block, and the code that gets called every time before the BRAB would 
be after a LABEL top statement. Any calculations that affect the 
pc would go in the generated rebcode blocks.
You would use the built-in assembler to fixup the top references 
at the end of every code snippet to the proper offsets.
This approach would end up with the size of your generated interpreter 
adding up to one 64k element block for the BRAB target block, one 
main block of 64k*4 + (some fixed number for overhead code) elements, 
and the size of any rebcode blocks generated from Z80 code between 
branches. Your source would be much smaller, or course.
Well, that's all I have time for right now. I hope I helped!
Steeve
20-Feb-2007
[1805]
many thanks
Coccinelle
22-Feb-2007
[1806]
Question Steeve, if you parse the Z80 opcode to produce rebcode, 
how do you handle Self Modifying Code  opcode, for example this one 
which is used to save a and restore it later :
   ld (Restore + 1), a
   .. (Do some stuff)
   Restore:	ld  a, 12h

This sample is a common optimization technic used in the 80's
Steeve
22-Feb-2007
[1807x2]
yeah yeah, that is not a problem anymore, i changed my way, now with 
rebcode i do pure emulation.
soon i will post a proto
Coccinelle
23-Feb-2007
[1809]
peut-être que cela te serait utile :
; Patch to rebcode assembler

; - Add setl opcode -> setl: ["Set variable to label offset (0 based 
offset)" word! word!]
; - very usefull to call sub routine

system/internal/rebcode*: make system/internal/rebcode* [
    fix-bl: func [block /local labels here label][
	    labels: make block! 16 
	    block-action: :fix-bl 
	    if debug? [print "=== Fixing binding and labels... ==="] 
	    parse block [
	        some [
	            here: 
	            subblock-rule (here/1: bind here/1 words) 
	            | 

             'label word! (here/1: bind here/1 words insert insert tail labels 
             here/2 index? here) 
                |
                'setl word! word!
	            | 
	            opcode-rule (here/1: bind here/1 words) 
	            | 
                skip (print "LA" error here)
	        ]
	    ] 
	    parse block [
	        some [
	            here: 
	            ['bra word! | 'brat word! | 'braf word!] (
	                fix-label labels at here 2 here 0
	            ) 
	            | 
	            'brab into [some word!] word! (
	                label: here/2 
	                forall label [
	                    fix-label labels label here -1
	                ]
	            ) 
	            | 
	            'brab word! word! (
	                fix-label labels at here 2 here -1
	            ) 
	            |
	            'setl word! word! (
	            	here/1: 'set
	            	here/1: bind here/1 words
	            	here/3: -1 + any [
	            		select labels to word! here/3

               error/with here join "Missing label '" [here/3 ":"]
            		]
	            )
	            | 
	            opcode-rule 
	            | 
                skip (print "ICI" error here)
	        ]
	    ]
    ]
	system/internal/assemble: func [
	    "REBCODE Assembler" 
	    body 
	    /local frame here do-blks labels tmp rule
	][
	    body: second :body 
	    fix-bl body
	]
]