home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol171 / m68k.doc < prev    next >
Encoding:
Text File  |  1985-02-10  |  32.4 KB  |  991 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.               ____________ì                          Introduction
  8.  
  9.  
  10.      If  you  have  an  8  bit  microcomputer system and want to
  11. experiment with the Motorola MC68000, this  cross  compiler  may
  12. interest you.    One  of  the  problems an experimenter faces in
  13. using a new microprocessor is how to develop  programs  for  it.
  14. One  solution  to  this  problem  is  to purchase a new computer
  15. system and a new set of software for each of the processors that
  16. interest you.  Clearly, this solution  is  expensive.    Another
  17. solution  is to use an existing computer and software to develop
  18. the programs for the new one.  Compilers which use  an  existing
  19. computer  to  produce  code for another machine are called cross
  20. compilers. Such  cross  compilers  (and  cross  assemblers)  are
  21. available  for  most  of  the  microprocessors  on  the  market.
  22. However, they  typically  run  on  a  large  mainframe  or  mini
  23. computer.  This  rules them out for many applications.  It would
  24. be nice to have a simple compiler that can be run on an existing
  25. microcomputer to generate code for the new processor.   That  is
  26. exactly  the  need  addressed  by  this  cross  compiler for the
  27. MC68000.
  28.  
  29.      I have chosen a subset of the FORTH language because it  is
  30. a powerful  language  that is simple to implement.  I decided to
  31. write the  compiler  in  FORTH  because  most  of  the  routines
  32. required  by the compiler are already present so the development
  33. time for the compiler is greatly reduced.  The  resulting  cross
  34. compiler  should be transportable to any computer which supports
  35. FORTH.  I am using this compiler for  scientific  work  where  I
  36. need  the  speed  of the MC68000 so the compiler does not have a
  37. lot of fancy data structures and I/O  routines.    These  things
  38. could  be added but the current configuration is adequate for my
  39. purposes.
  40.  
  41.      In this article I am assuming the reader is  familiar  with
  42. the FORTH  language.  Those not familiar with FORTH should get a
  43. copy of the excellent book "Starting FORTH" by Leo  Brodie.    I
  44. used  Starting  FORTH  as  a  reference  when  I  developed this
  45. compiler so  the  FORTH  words  that  are  implemented  work  as
  46. described there.    The  detailed  description  of the operators
  47. supported by the compiler is presented in assembly language,  so
  48. familiarity  with  the  MC68000  assembly language is needed for
  49. understanding the design of the compiler.  However,  it  is  not
  50. necessary to know assembly language to use the compiler.
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.                               Page 2
  71.  
  72.  
  73.  
  74.              ______ ______ì                         Memory Layout
  75.  
  76.  
  77.      Before considering the compiler it is necessary to know how
  78. the memory  of  the  MC68000  is  used.   The compiler uses four
  79. separate areas of MC68000 address space.  The pointers to  these
  80. areas  are  all  maintained in MC68000 registers so the user can
  81. allocate any area of memory for the various functions by setting
  82. up the registers  properly.    Thus,  it  is  not  necessary  to
  83. recompile the program to change the memory map.  These areas are
  84. described below.
  85.  
  86. 1.  Code pool
  87.  
  88.     Subroutine  definitions  place their output code in the code
  89.     pool and update  the  code  pool  pointer  variable  in  the
  90.     compiler (M68PCODE   in   listing  2,  screen  9).    During
  91.     execution of the resulting code, the MC68000 program counter
  92.     is the pointer to  this  area  of  memory.    Only  relative
  93.     addressing  is used so the code pool can be relocated simply
  94.     by moving the code and starting the program  at  the  proper
  95.     place.
  96.  
  97. 2.  Variable pool
  98.  
  99.     The  memory  used  by  variables  and  arrays  is  allocated
  100.     relative to the variable pool pointer (A5 in  the  MC68000).
  101.     The  compiler  word  M68ALLOT  is used to allocate space and
  102.     maintain even address alignment.  To  avoid  address  faults
  103.     the  value  placed in A5 must be even. With that restriction
  104.     the variable pool  may  be  placed  anywhere  in  memory  by
  105.     setting the  value  of  A5.   With an appropriate supervisor
  106.     program, it is possible to produce  reentrant  modules  with
  107.     this compiler by using A5 to assign a separate space for the
  108.     local variables each time the module is called.
  109.  
  110. 3.  Data stack
  111.  
  112.     The  memory  used by the data stack is pointed to by MC68000
  113.     register A6.    The  stack  is  maintained  using  the  auto
  114.     decrement  addressing mode to store information on the stack
  115.     and the auto increment addressing mode to remove information
  116.     from the stack.  For further information on the workings  of
  117.     the data stack see the stack operator section of listing 1.
  118.  
  119. 4.  Return stack
  120.  
  121.     The hardware stack is used for the return stack because most
  122.     of the return stack operations then become automatic.  A7 is
  123.     used as  the  pointer to the return stack.  Since there is a
  124.     supervisor and a user hardware stack pointer it is  possible
  125.     to use modules generated by this compiler for both interrupt
  126.     service routines and user programs.
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.                               Page 3
  137.  
  138.  
  139.  
  140.               ________ ___________ì                      Compiler Description
  141.  
  142.  
  143.      The  FORTH  subset  that  I  implemented  was  chosen for a
  144. particular hardware  configuration  but  could  be  expanded  if
  145. different I/O  were required.  I assume that you have a computer
  146. with a FORTH system running on it.  In the following  discussion
  147. I will  refer  to this computer as the host.  I also assume that
  148. the MC68000 is used as a coprocessor.  This  assumption  greatly
  149. reduces   the   complexity  of  the  subset  that  needs  to  be
  150. implemented.  All functions which interact with the terminal can
  151. be left out, also all the interaction with the operating  system
  152. and periferals   can   be  handeled  by  the  host.    A  simple
  153. bidirectional communication channel  is  all  that  is  required
  154. between the  host  and  the MC68000.  I have chosen to implement
  155. the arithmetic, stack,  memory  access,  and  control  operators
  156. found in  most  FORTH  systems.   I/O routines for data transfer
  157. between the MC68000 and  the  host  can  be  written  using  the
  158. primitives provided since the MC68000 uses memory mapped I/O.
  159.  
  160.      The compiler generates machine code so there is no need for
  161. an inner  interpreter.    The MC68000 provides the capability of
  162. writing position independent code, so all of the  code  produced
  163. by  this  compiler  is  position  independent  unless  the  user
  164. explicitly forces it to be otherwise.  Since the  code  is  kept
  165. separate  from the variable and stack space, the output from the
  166. compiler can be put into ROM.  It is sometimes desirable to  use
  167. programs generated with this compiler in host environments other
  168. than FORTH so I have provided a simple output scheme that allows
  169. the output code to be sent to any device supported by the host.
  170.  
  171.      To  avoid  conflict with the FORTH definitions in the host,
  172. most of the compiler is in a separate  vocabulary  (named  M68K)
  173. that is   accessed   only  through  the  defining  words.    All
  174. definitions created with the compiler are also  placed  in  this
  175. vocabulary  to  prevent accidental reference to them while using
  176. the host development system.  Some of the words normally used in
  177. FORTH have been given different names to  avoid  conflicts  with
  178. the host  definitions.    These  differences  will  be discussed
  179. later.
  180.  
  181.      There are two basic types of definitions  produced  by  the
  182. compiler, macros  and  subroutines.    Macro  definitions do not
  183. generate any output code but when referenced they store the code
  184. implememting  the  macro  in  the  definition  currently   being
  185. compiled.   Subroutine  definitions  generate  output  code when
  186. defined and  generate  a  subroutine  call  when  referenced  in
  187. another subroutine  definition.    A  macro  definition  may  be
  188. referenced in another macro or in a subroutine definition but  a
  189. subroutine may  not  be  referenced  in a macro definition.  The
  190. macro definition is the basic building block in the compiler, so
  191. I  will  discuss  it  in  detail  before  considering  constant,
  192. variable, and array definitions.
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.                               Page 4
  203.  
  204.  
  205.  
  206.      A  macro  is  created  in  the  same  way  as a FORTH colon
  207. definition except that :M68MAC and ;M68MAC are used in place  of
  208. the :  and  ; of a FORTH definition.  The body of the definition
  209. consists of executable MC68000 machine  code  or  references  to
  210. macros, variables, constants, and arrays.  For examples of macro
  211. definitions  see  screens  33-43  in  listing 2 and the examples
  212. below.
  213.  
  214.      When a macro is defined the M68K vocabulary is activated, a
  215. FORTH header is created in the dictionary of the host, and space
  216. is reserved for the code length.  The host FORTH is in execution
  217. mode so any words referenced in the body of a  macro  definition
  218. are executed   immediatly.      When  the  macro  definition  is
  219. terminated, the length of the code segment  is  stored  and  the
  220. FORTH vocabulary  is  reactivated.   Any subsequent reference to
  221. the macro copies the code contained within the macro  body  into
  222. the  host  dictionary  at the location HERE, then the dictionary
  223. pointer is updated to point to the memory location following the
  224. code.
  225.  
  226.      To illustrate this process consider the definition  of  the
  227. macro 2* shown in figure 1.  First, :M68MAC is used to start the
  228. definition,  create  the  FORTH header for 2* (Note.. I am being
  229. deliberately vague about the form of  the  header  because  that
  230. depends  on  the particular implementation of FORTH being used),
  231. and allocate space for the code length.  Next the macro  DUP  is
  232. called,  it  copies  the code for performing a DUP function into
  233. the host  dictionary  at  the  location  HERE  and  updates  the
  234. dictionary pointer  by  two.    Then  the  macro + is called, it
  235. copies its code into the dictionary and updates  the  dictionary
  236. pointer  by  four.  Finally,  ;M68MAC  is  used to terminate the
  237. definition and compute and store the macro  length  in  the  two
  238. bytes following  the  header.    In  this case the length is six
  239. bytes.
  240.  
  241.      Single and  double  precision  constants  are  compiled  as
  242. macros containing a single MC68000 instruction to push the value
  243. of the constant onto the data stack.  The word M68CON is used to
  244. define a  single  precision  constant as shown in figure 2.  The
  245. value of the constant is taken from the host stack and stored in
  246. the macro as part of a move immediate instruction  (see  listing
  247. 1).  The word M68DCON is the same except that a double precision
  248. value is involved.
  249.  
  250.      Variables  are  defined  as single precision constants that
  251. push the variable pool relative address onto the stack  for  use
  252. with the  fetch  and  store  operations.  Note that the variable
  253. pool relative address  is  a  16  bit  signed  integer,  so  the
  254. variable pool  can be no longer than 32K bytes.  The word M68VAR
  255. defines a single precision variable while the  word  M68DVAR  is
  256. for double precision.
  257.  
  258.      Arrays  are  defined  as macros that take the index off the
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.                               Page 5
  269.  
  270.  
  271.  
  272. stack and compute the variable pool  relative  address  of  that
  273. element and  leave  the  result  on  the  stack.    The compiler
  274. supports arrays  whose  elements  can  be  either  byte,  single
  275. precision, or  double precision.  The words M68CARY, M68ARY, and
  276. M68DARY respectively define these data types.  Figure  3  is  an
  277. example  of  the  definition  of  a  byte  array containing five
  278. elements.  The variable pool pointer is shown before  and  after
  279. the  definition  of  the array. Note that the compiler maintains
  280. alignment on word boundaries to avoid  address  exceptions  when
  281. the code is executed.
  282.  
  283.      When  a  subroutine  is  defined,  the  M68K  vocabulary is
  284. activated and a FORTH header is created in the dictionary of the
  285. host.  The code pool relative address of the subroutine is  then
  286. stored as  the  first entry of the definition.  Compilation then
  287. proceeds in the same way as in a macro  definition  except  that
  288. references to subroutine definitions are also allowed.  When the
  289. definition is terminated a return from subroutine instruction is
  290. compiled,  the  code  pool pointer M68PCODE is updated, then the
  291. code is sent to the output file and deleted from the dictionary.
  292. This leaves only the header and the code pool  relative  address
  293. of the  subroutine  in  the dictionary.  Subsequent reference to
  294. the subroutine uses the code pool relative  address  to  compute
  295. the   relative  address  required  in  a  branch  to  subroutine
  296. instruction.  Note that the branch instructions on  the  MC68000
  297. restrict your program to 32K bytes because all of the subroutine
  298. calls are back branches, forward referencing is not supported in
  299. this compiler.
  300.  
  301.      Since  the  code  pool  relative address of a subroutine is
  302. stored at the start of  the  definition,  a  subroutine  may  be
  303. referenced recursively.    However,  care must be exercised when
  304. doing this.  Subroutine calls do not create local  variables  so
  305. any  subroutine  which  stores  a  value  in  a variable may not
  306. operate properly when recursively called.  I  recommend  keeping
  307. all variables  on  the stack in recursive subroutines.  When you
  308. do this make sure the data stack is large enough.  There  is  no
  309. check  for  stack overflow so something will be clobbered if the
  310. data stack space is too small.
  311.  
  312.      To  illustrate  the  process  of  subroutine   compilation,
  313. consider the  example  in  figure  4.  The word :M68K is used to
  314. start the definition and create the FORTH header  for  4*,  this
  315. also  sets the code pool relative address of 4* (in this case it
  316. is zero).  Next, the macro 2* is called twice (the macro 2* that
  317. is refered to here is the one defined in figure 1  not  the  one
  318. actually  implemented  in the compiler which is more efficient).
  319. Each time 2* is called the code implementing it is stored in the
  320. host dictionary and the dictionary pointer  is  updated.    Then
  321. ;M68K  is  used  to  terminate  the  definition  by  compiling a
  322. subroutine  return  instruction,  adding  the  length   of   the
  323. subroutine  to  the  code  pool pointer, copying the code to the
  324. output file, and deleting the code from the dictionary.
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.                               Page 6
  335.  
  336.  
  337.  
  338.               ____________ì                          Installation
  339.  
  340.  
  341.      To  install  the  compiler  you  need either a fig FORTH or
  342. FORTH-79 system.  The installation on a  FORTH-79  system  is  a
  343. little more involved so I will cover the fig installation first.
  344. Listing  2  contains  the  complete source for the compiler, you
  345. must somehow get these 35 screens into your FORTH system.    For
  346. $25  I  will  provide an 8" single density CP/M disk with all of
  347. the source code for the compiler and this article.   The  source
  348. code  on  the  disk  will  be  in  a  screen  file  supported by
  349. Laboratory Microsystems Z80-FORTH,  and  also  as  a  text  file
  350. containing a listing of the screens.  By the time you read this,
  351. the  source may be available from a couple of user groups and/or
  352. RCPM systems.
  353.  
  354.      A few words in the compiler  must  be  customized  to  your
  355. system.   In  screen  12  is  a word called HIGH-BYTE, this word
  356. takes the top entry off the stack and  returns  the  high  byte.
  357. This  definition  must  be  replaced with the code to accomplish
  358. this task, it may be necessary to use a code definition on  your
  359. system.   The  word M68OUT in screen 18 must be designed to send
  360. the generated code to whatever output device or file  you  want,
  361. refer  to  the  note  in  that screen. The word M68OUT currently
  362. prints the code on the screen.  If you want to use the  external
  363. reference  capability  you will need to modify the definition in
  364. screen 20 to send the output where you want it.  If you  do  not
  365. want that feature then simply delete screen 20 entirely.
  366.  
  367.      The compiler  is  loaded  in  three  sections.    The basic
  368. compiler and error checking routines  are  loaded  from  screens
  369. 8-24.   The  program  control  and looping operations with their
  370. associated error checking are contained in screens 25-33.    The
  371. macros  that  implement  the operators supported by the compiler
  372. are in screens 34-43.
  373.  
  374.      For a FORTH-79 system the above applies but some additional
  375. work needs to be done.  I have used the  fig  FORTH  word  ENDIF
  376. instead  of  the  FORTH-79 word THEN so on a FORTH-79 system the
  377. definition of ENDIF given in listing 2 screen 44 should be used.
  378. I have also used the fig word <BUILDS in a <BUILDS  ...    DOES>
  379. construction.   See  screen  44 for a discussion of a definition
  380. for <BUILDS.  With these two definitions the compiler should run
  381. on a FORTH-79 system.  However, I cannot guarantee that this  is
  382. the  case  since  my  system  is  a  combination  fig FORTH with
  383. FORTH-79 extension so my testing may not have picked up  all  of
  384. the problems.    If  you have difficulty with this either get in
  385. touch with me or send in a letter to the editor.
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.                               Page 7
  401.  
  402.  
  403.  
  404.                _____ ___ ________ì                       Using the Compiler
  405.  
  406.  
  407.      Before explaining how to use the compiler I want  to  point
  408. out some  of the difficulties you will encounter.  Although this
  409. compiler uses a subset of FORTH you will find  that  most  FORTH
  410. programs  will  have  to  be  modified  before the compiler will
  411. accept them.  Obviously, constructions which are  not  supported
  412. by  the  compiler must be removed and/or replaced, but also many
  413. programming techniques used in FORTH will not work  because  the
  414. output  code  is nothing like the indirect threaded code used in
  415. most FORTH  implementations.    Therefore,  such  practices   as
  416. modifying the values of constants on the fly will not work, also
  417. you  cannot compile things into the dictionary at run time since
  418. there is no dictionary.  The compiler runs as  a  collection  of
  419. words  in  the  host  FORTH  system but I have not rewritten the
  420. FORTH word NUMBER to be sensitive  to  the  state  of  the  M68K
  421. compiler  so  a number contained within a definition will not be
  422. compiled into the definition automatically.  Instead it goes  on
  423. the host stack and must be compiled into the definition with the
  424. word  LITERAL  (or  DLITERAL  in  the case of double precision).
  425. Also note that you must use at least one  subroutine  definition
  426. to get  the code sent to the output file.  I think this will all
  427. become clear as I go through the example in listing 3.
  428.  
  429.      Listing 3, screen 8 shows the  FORTH  implementation  of  a
  430. benchmark program.  This will be used as a reference to show how
  431. the FORTH  code  must be modified to compile properly.  Screen 9
  432. shows the same program for the M68K compiler.  The  first  thing
  433. to notice is the difference in the definitions of the constants.
  434. The number  0  is  used  several times in the program.  To avoid
  435. using LITERAL so many times, I defined a constant #0 in the M68K
  436. vocabulary and used that wherever 0 was used.  The name 0  could
  437. have  been  chosen  for this constant since it is redefined only
  438. when the M68K vocabulary is active, but that may have  made  the
  439. example more  confusing.   The constant SIZE is used in two ways
  440. in the  program.    SIZE  is  used  as  a  FORTH  constant  when
  441. allocating  array  space  and  as  an  M68K  constant within the
  442. definition of DO-PRIME.  It is defined twice, once in the  FORTH
  443. vocabulary  using CONSTANT and once in the M68K vocabulary using
  444. M68CON.  The definition  of  the  variable  FLAGS  is  a  little
  445. different   from   screen  8,  the  M68K  compiler  follows  the
  446. convention in Starting FORTH and does  not  provide  initialized
  447. variables.  Note that the constants 1 and 3 used inside DO-PRIME
  448. are  compiled  using  LITERAL as all numbers inside a definition
  449. must be if they are not defined as  constants.    The  resulting
  450. code  for  either  a  constant or literal is identical, only the
  451. compilation process is different.  I used :M68MAC to define  DO-
  452. PRIME  because  I  wanted  the  entire  program  to  be a single
  453. subroutine.   Screen  10  contains  an  initialization   routine
  454. required  to set the pointers used by the code, it also contains
  455. a subroutine TEST which causes the output code to be  generated.
  456. TEST  also  causes  the  benchmark  to  be  iterated 10 times to
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.                               Page 8
  467.  
  468.  
  469.  
  470. conform to the requirements of Gilbreath's test.  Note that  the
  471. prime  count  cannot be printed as in the FORTH version so it is
  472. simply droped from the stack.  One might think  that  the  prime
  473. count could be eliminated from the program itself but that would
  474. give  a  false  representation  of  the  execution  time  of the
  475. benchmark.  Screen 11 is  the  same  program  as  screen  9  but
  476. rewritten  to  use  the  array  features  of the compiler and to
  477. remove a couple of the inefficiencies built  into  the  original
  478. program.  Screen 12 is identical to screen 10 and is here simply
  479. to  compile screen 11 without using an indirect LOAD. Also shown
  480. in listing 3 is an assembly language version  of  the  benchmark
  481. program used  for timing and code size comparisons.  The results
  482. of the benchmark are shown in figure 5.    Note  that  a  fairly
  483. heavy  penalty  is  paid  for  using  a stack oriented language.
  484. However, I think the programming convenience is worth it in most
  485. cases.
  486.  
  487.      Figure 6 is a description of the  words  that  perform  the
  488. compilation operations.    The  list  is  organized functionally
  489. rather than alphabetically. The word described is listed to  the
  490. left  followed  by the host stack image, over to the right is an
  491. example of the proper usage of the word.  Listing 1 contains the
  492. assembly language source for the FORTH words supported  by  this
  493. compiler.   In that listing there is also a short description of
  494. the supported words.  The reader should refer  to  that  listing
  495. and  Starting  FORTH  to clear up any confusion concerning these
  496. definitions.   Note  that  listing  1  also  describes   several
  497. operators that  are  not  standard  FORTH.   Operators for doing
  498. absolute memory references are described in the memory  and  I/O
  499. section.   Absolute  subroutine calls and jumps are described in
  500. the control operations section.
  501.  
  502.      There is no easy way to debug  programs  written  for  this
  503. compiler so I recommend the following development procedure.
  504.  
  505. 1.  Write and debug the program in FORTH.
  506.  
  507.     Your  FORTH  development  system provides a good environment
  508.     for debugging programs that you develop for  this  compiler.
  509.     It  is  very  important  at  this  stage  to avoid using any
  510.     operations not supported by the  compiler  since  they  will
  511.     just have  to  be  removed  later.    You should avoid using
  512.     embedded literals in your definitions since they are  rather
  513.     messy to take care of later.
  514.  
  515. 2.  Translate the program into a form acceptable to the
  516.     compiler.
  517.  
  518.     If   you  have  avoided  using  embedded  literals  in  your
  519.     definitions, the only changes should be replacing the :  and
  520.     ; as  appropriate.   The embedded literals can be taken care
  521.     of by defining each one as a  constant  or  using  the  word
  522.     LITERAL (or DLITERAL).
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.                               Page 9
  533.  
  534.  
  535.  
  536.  
  537. 3.  Compile the program and load it into your MC68000 computer.
  538.  
  539.     Make  sure  that  registers  A5, A6, and A7 are set properly
  540.     (either by a supervisor program, by hand, or using the  load
  541.     instructions provided in the compiler).
  542.  
  543. 4.  The program should now operate properly.
  544.  
  545.     If  not, step 2 is the most likely place to find the errors.
  546.     I have frequently encountered errors  in  resolving  program
  547.     control structures.  These errors occour because an embedded
  548.     literal has not been compiled.  This type of error is picked
  549.     up in the compile phase so no incorrect code is produced.
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.                              Page 10
  599.  
  600.  
  601.  
  602.              _____ ________ì                         Final Comments
  603.  
  604.  
  605.      This   compiler   could   form  the  basis  for  a  modular
  606. programming environment for the  MC68000  microprocessor.    The
  607. modifications necessary  would not be very complicated.  To make
  608. the compiler generate modular code a new word will  have  to  be
  609. added to  the basic compiler.  This word should reset all of the
  610. compiler variables in screen  9  to  their  original  state  and
  611. generate  an appropriate header so the operating system can load
  612. and execute the module.  Another word to terminate a module  and
  613. check  for  errors  will be required, the error checking code in
  614. the existing compiler can be used as a guide.    Note  that  the
  615. absolute  addressing  operators  will  have  to  be used for all
  616. global variables. I recommend that global variables  be  avoided
  617. and  that  all  parameters  passed from one module to another be
  618. passed on the data stack.
  619.  
  620.      I would like to see floating point arithmetic added to  the
  621. compiler but  I do not think I will do it anytime soon.  I would
  622. also like to have a MC68000 assembler built into the compiler so
  623. that machine code does not have to be typed in hex.  I encourage
  624. anyone who is interested to work on these extensions and publish
  625. their work in Dr. Dobb's for the rest of us to use.
  626.  
  627.      Please  note  that  I  have  copyrighted   this   compiler.
  628. However,  I  am  releasing  it  for  personal  use and nonprofit
  629. distribution.  If you sell my compiler as an integral part of  a
  630. commercial software  package I expect a small royalty.  Any code
  631. produced by the compiler may be sold  without  notifying  me  or
  632. paying royalties.    Other  than that feel free to use it as you
  633. see fit and give it to whomever you like.  You may also want  to
  634. send  it  on  to your favorite user group, all I ask is that you
  635. acknowlege the source.
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.                 FIGURES                      Page 11
  665.  
  666.  
  667.  
  668.  
  669.  
  670. :M68MAC 2* DUP + ;M68MAC
  671.  
  672.       _______
  673.      |   2*  |       Dictionary header for the macro 2*
  674.      |_______|
  675.      | 00 06 |       Length of macro code segment
  676.      |_______|
  677.      | 3D 16 |       MC68000 machine code for DUP
  678.      |_______|
  679.      | 30 1E |       MC68000 machine code for +
  680.      | D1 56 |
  681.      |_______|
  682.  
  683.  
  684. Figure 1: Example of a macro definition and the resulting 
  685.       dictionary entry.
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696. 5 M68CON #5          ( Defines the constant #5 )
  697.  
  698.       _______
  699.      |   #5  |       Dictionary header for the macro #5
  700.      |_______|
  701.      | 00 04 |       Length of macro code segment
  702.      |_______|
  703.      | 3D 3C |       MOVE.W  #5,-(A6)
  704.      | 00 05 |       Pushes the value 5 onto data stack
  705.      |_______|
  706.  
  707.  
  708. Figure 2: Example of a constant definition and the
  709.       resulting dictionary entry.
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.                 FIGURES                      Page 12
  731.  
  732.  
  733.  
  734.  
  735.  
  736. 5 M68CARY EXAMP      ( Defines the byte array EXAMP )
  737.  
  738.       _______
  739.      | EXAMP |       Dictionary header for the macro EXAMP
  740.      |_______|
  741.      | 00 06 |       Length of macro code segment
  742.      |_______|
  743.      | 30 3C |       Code to add the variable pool relative
  744.      | 00 20 |       address of the array ( 20 hex ) to the
  745.      | D1 56 |       index value on the data stack.
  746.      |_______|
  747.  
  748. Variable pool pointer:
  749. Before = 0020;  After = 0026
  750.  
  751. Figure 3: Example of an array definition, the resulting 
  752.       dictionary entry, and the effect on the variable 
  753.       pool pointer.  Note all values are in hex.
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764. :M68K 4* 2* 2* ;M68K
  765.  
  766.       _______
  767.      |   4*  |       Dictionary header for the subroutine 4*
  768.      |_______|
  769.      | 00 00 |       Relative address of subroutine
  770.      |_______|
  771.  
  772. Code pool pointer:
  773. Before = 0000;  After = 000E
  774.  
  775. Code sent to the output file:
  776.  
  777.     2*        |         2*        | RTS instruction
  778. __________________|___________________|________________
  779. 3D 16 30 1E D1 56 | 3D 16 30 1E D1 56 | 4E 75
  780.  
  781.  
  782. Figure 4: Example of a subroutine definition, the resulting
  783.       dictionary entry, and the output code.
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.                 FIGURES                      Page 13
  797.  
  798.  
  799.  
  800.  
  801.  
  802. Source     Code size    Time (10 iter.)    Comments
  803. ___________________________________________________________________________
  804. Screen 8   109 Bytes    85 sec             Z80 FORTH @ 3.5Mhz
  805. Screen 9   220 Bytes    8.7 sec            68000 @ 10Mhz with 2 wait states
  806. Screen 11  216 Bytes    8.1 sec            68000 @ 10Mhz with 2 wait states
  807. Assembler   74 Bytes    2.1 sec            68000 @ 10Mhz with 2 wait states
  808.  
  809.  
  810. Figure 5: Results of benchmark tests shown in listing 3.
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.                 FIGURES                      Page 14
  863.  
  864.  
  865.  
  866.  
  867.  
  868. :M68K   ( -- )                                  :M68K xxxx
  869.  
  870.     Creates a header for the subroutine  word  xxxx  in  the
  871.     M68K  vocabulary  and  sets  the  variables M68ENTRY and
  872.     M68PFA.   Reference  to   xxxx   within   a   subroutine
  873.     definition generates a branch to subroutine using the PC
  874.     relative addressing  mode.    The  word xxxx may only be
  875.     referenced within a subroutine definition.    Any  other
  876.     usage will produce an error message.  So long as no side
  877.     effects   occour,   the  word  xxxx  may  be  referenced
  878.     recursively.  Note that the code may  be  put  into  ROM
  879.     because  the  stack  and variable space is kept separate
  880.     from the code.
  881.  
  882. ;M68K   ( -- )
  883.  
  884.     Terminates the construction of a  subroutine  definition
  885.     and sends the code to the output file.  The code for the
  886.     subroutine  is deleted from the host dictionary after it
  887.     is written out and only the code pool  relative  address
  888.     of the subroutine is retained.
  889.  
  890. :M68MAC ( -- )                                  :M68MAC xxxx
  891.  
  892.     Creates  a  header  for  the macro word xxxx in the M68K
  893.     vocabulary  and  sets  the  compiler  variable   M68PFA.
  894.     Reference   to  xxxx  within  a  definition  copies  the
  895.     compiled code into the host dictionary.   A  macro  word
  896.     may be referenced within the definition of another macro
  897.     word or within the definition of a subroutine word.
  898.  
  899. ;M68MAC ( -- )
  900.  
  901.     Terminates  the  construction  of  a  macro  type  word,
  902.     encloses the code, and updates the compiler variables.
  903.  
  904. M68CON  ( n -- )                                n M68CON xxxx
  905.  
  906.     Defines a macro word xxxx that pushes the value  n  onto
  907.     the stack when xxxx is executed.  The value n must be on
  908.     the host stack when M68CON is referenced.
  909.  
  910. M68DCON ( d -- )                                d M68DCON xxxx
  911.  
  912.     Defines  a  double precision constant in the same way as
  913.     M68CON.
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921. Figure 6: Description of compiling words
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.                 FIGURES                      Page 15
  929.  
  930.  
  931.  
  932.  
  933.  
  934. M68ALLOT ( n -- )                               n M68ALLOT
  935.  
  936.     Allocates n bytes of  space  in  the  variable  pool  by
  937.     updating  the  variable  pool  pointer variable M68PVAR.
  938.     Note.. this word maintains even byte alignment  so  that
  939.     address  exceptions  will  not  occour  on 16 and 32 bit
  940.     memory references.  Also note that it is an error if the
  941.     variable pool becomes longer  than  32K  bytes  but  the
  942.     compiler  will not report this as an error, so incorrect
  943.     code would be generated.
  944.  
  945. M68VAR  ( -- )                                  M68VAR xxxx
  946.  
  947.     Defines a single precision variable by using the pointer
  948.     M68PVAR as the parameter n  for  M68CON.    The  pointer
  949.     M68PVAR  is  then  updated  by two bytes using M68ALLOT.
  950.     Execution of the word  xxxx  leaves  the  variable  pool
  951.     relative  address  of  the  variable  on  the top of the
  952.     stack.
  953.  
  954. M68DVAR ( -- )                                  M68DVAR xxxx
  955.  
  956.     Defines a double precision variable in the same  way  as
  957.     M68VAR  except  that  the  pointer M68PVAR is updated by
  958.     four bytes.
  959.  
  960. M68ARY  ( n -- )                                n M68ARY xxxx
  961.  
  962.     Defines a single precision array xxxx that is n elements
  963.     long. The word xxxx is defined as a macro that takes  an
  964.     element  number  off the top of the stack and leaves the
  965.     variable pool relative address of that element.
  966.  
  967. M68CARY ( n -- )                                n M68CARY xxxx
  968.  
  969.     Defines a byte array in the same manner as M68ARY.
  970.  
  971. M68DARY ( n -- )                                n M68DARY xxxx
  972.  
  973.     Defines a double precision array in the same  manner  as
  974.     M68ARY.
  975.  
  976. EXTERNAL ( -- )                                 EXTERNAL xxxx
  977.  
  978.     Creates  an  external  reference xxxx which contains the
  979.     code pool relative address of the last  subroutine  word
  980.     that was  defined.    This word may be customized by the
  981.     user to produce a file containing an external  reference
  982.     list.   Currently,  this word creates a constant xxxx in
  983.     the FORTH vocabulary of the host.
  984.  
  985.  
  986.  
  987. Figure 6: Description of compiling words (continued)
  988.  
  989.  
  990.  
  991.