--- gforth/doc/gforth.ds 2000/07/21 17:38:58 1.62 +++ gforth/doc/gforth.ds 2000/07/24 18:59:58 1.63 @@ -309,6 +309,12 @@ Defining Words * Aliases:: * Supplying names:: +User-defined Defining Words + +* CREATE..DOES> applications:: +* CREATE..DOES> details:: +* Advanced does> usage example:: + Interpretation and Compilation Semantics * Combined words:: @@ -351,6 +357,16 @@ Programming Tools * Assertions:: Making your programs self-checking. * Singlestep Debugger:: Executing your program word by word. +Assembler and Code Words + +* Code and ;code:: +* Common Assembler:: Assembler Syntax +* Common Disassembler:: +* 386 Assembler:: Deviations and special cases +* Alpha Assembler:: Deviations and special cases +* MIPS assembler:: Deviations and special cases +* Other assemblers:: How to write them + Locals * Gforth locals:: @@ -6274,7 +6290,7 @@ locals declarations for stack effect spe @menu * CREATE..DOES> applications:: * CREATE..DOES> details:: -* Advanced does> usage:: +* Advanced does> usage example:: @end menu @node CREATE..DOES> applications, CREATE..DOES> details, User-defined Defining Words, User-defined Defining Words @@ -6324,7 +6340,7 @@ DOES> ( n2 -- n1+n2 ) -2 curry+ 2- @end example -@node CREATE..DOES> details, Advanced does> usage, CREATE..DOES> applications, User-defined Defining Words +@node CREATE..DOES> details, Advanced does> usage example, CREATE..DOES> applications, User-defined Defining Words @subsubsection The gory details of @code{CREATE..DOES>} @cindex @code{CREATE} ... @code{DOES>}, details @@ -6382,9 +6398,122 @@ CREATE name EXECUTE ( ... -- ... ) doc->body -@node Advanced does> usage, , CREATE..DOES> details, User-defined Defining Words -@subsubsection Advanced does> usage +@node Advanced does> usage example, , CREATE..DOES> details, User-defined Defining Words +@subsubsection Advanced does> usage example + +The MIPS disassembler (@file{arch/mips/disasm.fs}) contains many words +for disassembling instructions, that follow a very repetetive scheme: + +@example +:noname @var{disasm-operands} s" @var{inst-name}" type ; +@var{entry-num} cells @var{table} + ! +@end example + +Of course, this inspires the idea to factor out the commonalities to +allow a definition like + +@example +@var{disasm-operands} @var{entry-num} @var{table} define-inst @var{inst-name} +@end example + +The parameters @var{disasm-operands} and @var{table} are usually +correlated. Moreover, there existed code defining instructions like +this: + +@example +@var{entry-num} @var{inst-format} @var{inst-name} +@end example + +This code comes from the assembler and resides in +@file{arch/mips/insts.fs}. + +So I had to define the @var{inst-format} words that performed the scheme +above when executed. At first I chose to use run-time code-generation: + +@example +: @var{inst-format} ( entry-num "name" -- ; compiled code: addr w -- ) + :noname Postpone @var{disasm-operands} + name Postpone sliteral Postpone type Postpone ; + swap cells @var{table} + ! ; +@end example + +Note that this supplies the other two parameters of the scheme above. +An alternative would have been to write this using +@code{create}/@code{does>}: + +@example +: @var{inst-format} ( entry-num "name" -- ) + here name string, ( entry-num c-addr ) \ parse and save "name" + noname create , ( entry-num ) + lastxt swap cells @var{table} + ! +does> ( addr w -- ) + \ disassemble instruction w at addr + @@ >r + @var{disasm-operands} + r> count type ; +@end example + +Somehow the first solution is simpler, mainly because it's simpler to +shift a string from definition-time to use-time with @code{sliteral} +than with @code{string,} and friends. + +I wrote a lot of words following this scheme and soon thought about +factoring out the commonalities among them. Note that this uses a +two-level defining word, i.e., a word that defines ordinary defining +words. + +This time a solution involving @code{postpone} and friends seemed more +difficult (try it as an exercise), so I decided to use a +@code{create}/@code{does>} word; since I was already at it, I also used +@code{create}/@code{does>} for the lower level (try using +@code{postpone} etc. as an exercise), resulting in the following +definition: + +@example +: define-format ( disasm-xt table-xt -- ) + \ define an instruction format that uses disasm-xt for + \ disassembling and enters the defined instructions into table + \ table-xt + create 2, +does> ( u "inst" -- ) + \ defines an anonymous word for disassembling instruction inst, + \ and enters it as u-th entry into table-xt + 2@@ swap here name string, ( u table-xt disasm-xt c-addr ) \ remember string + noname create 2, \ define anonymous word + execute lastxt swap ! \ enter xt of defined word into table-xt +does> ( addr w -- ) + \ disassemble instruction w at addr + 2@@ >r ( addr w disasm-xt R: c-addr ) + execute ( R: c-addr ) \ disassemble operands + r> count type ; \ print name +@end example + +Note that the tables here (in contrast to above) do the @code{cells +} +by themselves (that's why you have to pass an xt). This word is used in +the following way: + +@example +' @var{disasm-operands} ' @var{table} define-format @var{inst-format} +@end example + +In terms of currying, this kind of two-level defining word provides the +parameters in three stages: first @var{disasm-operands} and @var{table}, +then @var{entry-num} and @var{inst-name}, finally @code{addr w}, i.e., +the instruction to be disassembled. + +Of course this did not quite fit all the instruction format names used +in @file{insts.fs}, so I had to define a few wrappers that conditioned +the parameters into the right form. + +If you have trouble following this section, don't worry. First, this is +involved and takes time (and probably some playing around) to +understand; second, this is the first two-level +@code{create}/@code{does>} word I have written in seventeen years of +Forth; and if I did not have @file{insts.fs} to start with, I may well +have elected to use just a one-level defining word (with some repeating +of parameters when using the defining word). So it is not necessary to +understand this, but it may improve your understanding of Forth. @node Deferred words, Aliases, User-defined Defining Words, Defining Words @@ -8882,8 +9011,8 @@ suite that contains all instructions. O easy. For actual coding you can take a look at @file{arch/mips/disasm.fs} to get some ideas on how to use data for both the assembler and disassembler, avoiding redundancy and some potential -bugs. You can also look at that file (and @pxref{Advanced does> usage}) -to get ideas how to factor a disassembler. +bugs. You can also look at that file (and @pxref{Advanced does> usage +example}) to get ideas how to factor a disassembler. Start with the disassembler, because it's easier to reuse data from the disassembler for the assembler than the other way round.