version 1.5, 2003/08/25 14:17:49
|
version 1.11, 2010/12/31 18:09:02
|
Line 1
|
Line 1
|
\ generic.fs implements generic assembler definitions 13aug97jaw |
\ generic.fs implements generic assembler definitions 13aug97jaw |
|
|
\ Copyright (C) 1998,2000,2003 Free Software Foundation, Inc. |
\ Copyright (C) 1998,2000,2003,2007,2010 Free Software Foundation, Inc. |
|
|
\ This file is part of Gforth. |
\ This file is part of Gforth. |
|
|
\ Gforth is free software; you can redistribute it and/or |
\ Gforth is free software; you can redistribute it and/or |
\ modify it under the terms of the GNU General Public License |
\ modify it under the terms of the GNU General Public License |
\ as published by the Free Software Foundation; either version 2 |
\ as published by the Free Software Foundation, either version 3 |
\ of the License, or (at your option) any later version. |
\ of the License, or (at your option) any later version. |
|
|
\ This program is distributed in the hope that it will be useful, |
\ This program is distributed in the hope that it will be useful, |
Line 15
|
Line 15
|
\ GNU General Public License for more details. |
\ GNU General Public License for more details. |
|
|
\ You should have received a copy of the GNU General Public License |
\ You should have received a copy of the GNU General Public License |
\ along with this program; if not, write to the Free Software |
\ along with this program. If not, see http://www.gnu.org/licenses/. |
\ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
|
|
|
\ These are generic routines to build up a table-driven assembler |
\ These are generic routines to build up a table-driven assembler |
\ fo any modern (RISC)-CPU |
\ fo any modern (RISC)-CPU |
Line 25
|
Line 24
|
\ |
\ |
\ 13aug97jaw-14aug97 Initial Version -> V0.5 |
\ 13aug97jaw-14aug97 Initial Version -> V0.5 |
\ ToDo: operand count checking |
\ ToDo: operand count checking |
\ |
\ |
|
\ 24apr10dk Added documentation |
|
|
\ general definitions |
\ general definitions |
|
|
: clearstack depth 0 ?DO drop LOOP ; |
: clearstack ( k*x -- ) depth 0 ?DO drop LOOP ; |
|
|
\ redefinitions to avoid conflicts |
\ redefinitions to avoid conflicts |
|
|
Line 57 Create modes modes# cells allot \ Modes
|
Line 57 Create modes modes# cells allot \ Modes
|
Variable Start-Depth |
Variable Start-Depth |
Variable Mode# |
Variable Mode# |
|
|
: reset |
: reset ( -- ) |
|
\G End an opcode / star a new opcode. |
modes modes# cells erase |
modes modes# cells erase |
1 Mode# ! |
1 Mode# ! |
depth Start-Depth ! ; |
depth Start-Depth ! ; |
|
|
: Mode! ( n -- ) |
: Mode! ( x -- ) |
|
\G Set current operand's mode to X |
Modes Mode# @ cells + ! ; |
Modes Mode# @ cells + ! ; |
|
|
: +Mode! ( n -- ) |
: +Mode! ( x -- ) |
|
\G Logically OR X to current operand's mode |
Modes Mode# @ cells + tuck @ or swap ! ; |
Modes Mode# @ cells + tuck @ or swap ! ; |
|
|
: 0Mode! ( n -- ) |
: 0Mode! ( x -- ) |
|
\G Set mode of operand #0. Use operand #0 for an (optional) operands that |
|
\G can be placed anywhere, e.g. condition codes or operand lengths .B .W .L |
|
\G etc. |
Modes ! ; |
Modes ! ; |
|
|
: , |
: , ( -- ) |
|
\G Advance to next operand |
1 Mode# +! ; |
1 Mode# +! ; |
|
|
: Mode |
: Mode ( x "name" -- ) |
|
\G Define a new mode that logically ors X to current mode when executed |
Create dic, DOES> @ +Mode! ; |
Create dic, DOES> @ +Mode! ; |
|
|
: 0Mode |
: 0Mode ( x "name" -- ) |
|
\G Define a new mode that sets operand #0 when executed |
Create dic, DOES> @ 0Mode! ; |
Create dic, DOES> @ 0Mode! ; |
|
|
: Reg |
: Reg ( xt x "name" -- ) |
|
\G Define a parametrized mode, that executes mode XT, then puts X onto the |
|
\G stack |
Create dic, dic, DOES> dup perform cell+ @ ; |
Create dic, dic, DOES> dup perform cell+ @ ; |
|
|
\ --------- Instruction Latch |
\ --------- Instruction Latch |
Line 89 Create I-Latch 10 chars allot
|
Line 100 Create I-Latch 10 chars allot
|
Variable I-Len |
Variable I-Len |
|
|
: opc! ( adr len -- ) |
: opc! ( adr len -- ) |
|
\G Logically OR string of bytes into instruction latch |
dup I-Len @ max I-Len ! |
dup I-Len @ max I-Len ! |
I-Latch -rot bounds DO I c@ over c@ or over c! char+ LOOP drop ; |
I-Latch -rot bounds ?DO I c@ over c@ or over c! char+ LOOP drop ; |
|
|
: I-Init 0 I-Len ! I-Latch 10 erase ; |
: I-Init ( -- ) 0 I-Len ! I-Latch 10 erase ; |
: I-Flush I-Latch I-len @ bounds DO i c@ X c, LOOP reset ; |
: I-Flush ( -- ) |
|
\G Append contents of instruction latch to dictionary |
|
I-Latch I-len @ bounds DO i c@ X c, LOOP reset ; |
|
|
: (g!) ( val addr n -1/1 -- ) |
: (g!) ( val addr n -1/1 -- ) |
dup 0< IF rot 2 pick + 1- -rot THEN |
dup 0< IF rot 2 pick + 1- -rot THEN |
Line 109 Variable I-Len
|
Line 123 Variable I-Len
|
|
|
Variable ByteDirection \ -1 = big endian; 1 = little endian |
Variable ByteDirection \ -1 = big endian; 1 = little endian |
|
|
: g@ ByteDirection @ (g@) ; |
: g@ ( addr n -- val ) |
: g! ByteDirection @ (g!) ; |
\G read n-byte integer from addr using current endianess |
|
ByteDirection @ (g@) ; |
|
: g! ( val addr n -- ) |
|
\G write n-byte integer to addr using current endianess |
|
ByteDirection @ (g!) ; |
|
|
\ ---------------- Tables |
\ ---------------- Tables |
|
|
Line 126 Variable ByteDirection \ -1 = big endian
|
Line 144 Variable ByteDirection \ -1 = big endian
|
Describ 4 cells + perform \ to flush the instruction |
Describ 4 cells + perform \ to flush the instruction |
; |
; |
|
|
: 1st-mc ( addr -- flag ) |
: 1st-mc ( addr -- flag ) |
|
\G mnemonic check? check for matching operands. if matching, execute code |
|
\G to encode mode and operands and return true, else return false |
dup >modes modes Mode-Compare |
dup >modes modes Mode-Compare |
IF Table-Exec |
IF Table-Exec |
true |
true |
Line 134 Variable ByteDirection \ -1 = big endian
|
Line 154 Variable ByteDirection \ -1 = big endian
|
THEN ; |
THEN ; |
|
|
: 1st-always ( addr -- flag ) |
: 1st-always ( addr -- flag ) |
|
\G Undconditionally encode operands and/or instruction used for instructions |
|
\G that do not have any operands. Return true i.e. make the assembler stop |
|
\G looking for more instruction variants |
Table-Exec true ; |
Table-Exec true ; |
|
|
: 1st-thru |
: 1st-thru |
|
\G Unconditionally encode, but return false to make assembler execute next |
|
\G table rows also. |
dup Table-Exec false ; |
dup Table-Exec false ; |
|
|
: 2nd-opc! |
: 2nd-opc! ( -- ) |
|
\G encode opcode by ORing data column of current instruction row into |
|
\G instruction latch |
Describ >data count opc! ; |
Describ >data count opc! ; |
|
|
: opcode, |
: opcode, ( "<NNN> ..." -- ) |
|
\G Append a counted string to dictionary, reading in every character as |
|
\G space-terminated numbers form the parser until the end of line is |
|
\G reached. |
here 0 c, |
here 0 c, |
BEGIN bl word count dup WHILE s>number drop c, |
BEGIN bl word count dup WHILE s>number drop c, |
REPEAT 2drop here over - 1- swap c! ; |
REPEAT 2drop here over - 1- swap c! ; |
|
|
: modes, |
: modes, ( -- ) |
|
\G append contents of MODES to dictionary |
modes# 0 DO I cells modes + @ dic, LOOP ; |
modes# 0 DO I cells modes + @ dic, LOOP ; |
|
|
0 Value Table-Link |
0 Value Table-Link |
|
|
: Table |
: Table ( "name" -- ) |
|
\G create table that lists allowed operand/mode combinations for opcode |
|
\G "name". Note that during assembling, table will be scanned in reverse |
|
\G order! |
Reset |
Reset |
Create here to Table-Link 0 dic, |
Create here to Table-Link 0 dic, |
DOES> I-Init |
DOES> I-Init |
Line 162 Variable ByteDirection \ -1 = big endian
|
Line 196 Variable ByteDirection \ -1 = big endian
|
?EXIT |
?EXIT |
REPEAT -1 ABORT" no valid mode!" |
REPEAT -1 ABORT" no valid mode!" |
; |
; |
|
|
: Follows |
: Follows ( "name" -- ) |
|
\G Link current instruction's table to execute all rows of table "name" |
|
\G (after executing all rows already defined). Do not add any more rows to |
|
\G current table, after executing Follows. Else you're going to modify |
|
\G "name"'s table! |
' >body @ Table-Link @ ! ; |
' >body @ Table-Link @ ! ; |
|
|
: opc, |
: opc, ( k*x "<NNN> ..." -- ) |
|
\G Append current modes and opcode given byte-wise on current input line to |
|
\G dictionary. Clear forth stack to remove any data provided by the |
|
\G otherwise unused operands that wer used to set up the modes array. |
modes, opcode, clearstack reset ; |
modes, opcode, clearstack reset ; |
|
|
: (Opc() |
: (Opc() ( k*x xt "<NNN> ..." -- ) |
\ Opcode with Operands |
\G Fill table row for opcode with Operands. XT will be executed by the |
|
\G assembler for encoding the operands using data from the stack. |
['] 1st-mc dic, |
['] 1st-mc dic, |
['] 2nd-opc! dic, |
['] 2nd-opc! dic, |
dic, |
dic, |
['] I-Flush dic, |
['] I-Flush dic, |
opc, ; |
opc, ; |
|
|
: (Opc) |
: (Opc) ( k*x xt "<NNN> ..." -- ) |
\ Opcode without Operands |
\ Opcode without Operands |
['] 1st-always dic, |
['] 1st-always dic, |
['] 2nd-opc! dic, |
['] 2nd-opc! dic, |
Line 185 Variable ByteDirection \ -1 = big endian
|
Line 227 Variable ByteDirection \ -1 = big endian
|
['] I-Flush dic, |
['] I-Flush dic, |
opc, ; |
opc, ; |
|
|
: Opc( |
: Opc( ( k*x xt "<NNN> ..." -- ) |
\ Opcode with Operands |
\G Append a new table row for an opcode with Operands. Use your assembler |
|
\G operands to fill the MODES array with data showing how the opcode is |
|
\G used. Only the types of operands are recorded, any operand parameters |
|
\G passed on the stack are dropped. The opcode's instruction code is read |
|
\G as 8-bit numbers from the current input line and stored as counted string |
|
\G in the table's opcode column |
|
\G |
|
\G When assembling an instruction, the assembler checks for matching |
|
\G operands. If this row matches, first XT is called to consume operands |
|
\G parameters from the stack and encode them into the instruction latch. |
|
\G Then the opcode column is ORed to the instruction latch and the assembler |
|
\G quits assembly of the current instruction. |
Table-Link linked |
Table-Link linked |
(Opc() ; |
(Opc() ; |
|
|
: Opc |
: Opc ( k*x "<NNN> ..." -- ) |
\ Opcode without Operands |
\G Append a new table row for an opcode without operand parameters. |
|
\G |
|
\G When assembling an instruction, and the assembler reaches this row, it |
|
\G will assume the opcode is fully assembled and quits assembly of the |
|
\G instruction, after endcoding the opcode. |
Table-Link linked |
Table-Link linked |
(Opc) ; |
(Opc) ; |
|
|
: Opc+ |
: Opc+ ( k*x "<NNN> ..." -- ) |
\ Additional Opcode |
\G Append a new table row that encodes part of an opcode, but falls through |
|
\G to following lines. |
Table-Link linked |
Table-Link linked |
['] 1st-thru dic, |
['] 1st-thru dic, |
['] 2nd-opc! dic, |
['] 2nd-opc! dic, |
Line 204 Variable ByteDirection \ -1 = big endian
|
Line 262 Variable ByteDirection \ -1 = big endian
|
['] Noop dic, |
['] Noop dic, |
opc, ; |
opc, ; |
|
|
: Opc(+ |
: Opc(+ ( k*x xt "<NNN> ..." -- ) |
\ Additional Opcode with Operands |
\G Like OPC+ but for a table row that has operands |
Table-Link linked |
Table-Link linked |
['] 1st-thru dic, |
['] 1st-thru dic, |
['] 2nd-opc! dic, |
['] 2nd-opc! dic, |
Line 215 Variable ByteDirection \ -1 = big endian
|
Line 273 Variable ByteDirection \ -1 = big endian
|
|
|
: End-Table ; |
: End-Table ; |
|
|
: alone |
: alone ( k*x "<NNN> ..." -- ) |
|
\G Create a single-row instruction table for an instruction without operands. |
Create 0 dic, ( Dummy Linkfield ) (opc) |
Create 0 dic, ( Dummy Linkfield ) (opc) |
DOES> dup cell+ perform 0= ABORT" must work always!" ; |
DOES> dup cell+ perform 0= ABORT" must work always!" ; |
|
|
: alone( |
: alone( ( k*x xt "<NNN> ..." -- ) |
|
\G Create a single-row instruction table for an instruction with operands. |
Create 0 dic, ( Dummy Linkfield ) (opc() |
Create 0 dic, ( Dummy Linkfield ) (opc() |
DOES> dup cell+ perform 0= ABORT" must work always!" ; |
DOES> dup cell+ perform 0= ABORT" must work always!" ; |
|
|
|
|
|
\ Configure Emacs forth-mode to keep this file's formatting |
|
0 [IF] |
|
Local Variables: |
|
forth-indent-level: 2 |
|
forth-local-indent-words: |
|
(((";") (0 . -2) (0 . -2)) |
|
(("does>") (0 . 0) (0 . 0))) |
|
End: |
|
[THEN] |