/* assembler.4th - postforth assembler Copyright [C] 2004 John Comeau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or [at your option] any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This is the assembler for the postforth bootstrap - since nothing else is defined yet, this will have no clever way of deciphering opcode args, and so will have nonstandard mnemonics to specify whether the args are regs, memory, or immediate. This data was taken from various sources, on- and offline. If programs don't work right, it will possibly be due to errors in my data entry here. */ /* first define some constants */ /* obviously CONSTANT would be smaller and more efficient, but at this point simplicity of source is more important */ : EAX 2# 000 LIT, ; : EBX 2# 011 LIT, ; : ESI 2# 110 LIT, ; : EDI 2# 111 LIT, ; : AL 2# 000 LIT, ; : DS:[EAX] 2# 00000 LIT, ; : DS:[ESI] 2# 00110 LIT, ; : DS:[EDI] 2# 00111 LIT, ; : DS:[EAX+d8] 2# 01000 LIT, ; : DS:[ESI+d8] 2# 01110 LIT, ; : DS:[EDI+d8] 2# 01111 LIT, ; /* most opcodes will be used as: source destination opcode */ : JMPRI, /* ( reg -- ) (P jamp-ar-ai ) */ 2# 11111111 LIT, ' C, , /* compile first byte of opcode */ 2# 11100000 LIT, ' | , /* OR next byte with register bits */ ' C, , ; : JMPMI, /* ( mem -- ) (P jamp-em-ai ) */ 2# 11111111 LIT, ' C, , /* compile first byte of opcode */ 2# 01000 LIT, ' /MOD , /* split memory arg into mod and r/m */ 10# 6 LIT, ' << , /* shift mod bits into top two bits of byte */ ' | , /* join mod-r/m again */ 2# 100000 LIT, ' | , ' C, , /* complete 2nd byte of opcode */ ; : LODSL, /* ( -- ) (P lo:d-es-el ) */ /* load string longword - [ESI] -> EAX, then ESI is autoincremented */ 2# 10101101 LIT, ' C, , /* just compile the opcode */ ; : STOSL, /* ( -- ) (P stos-el ) */ /* store string longword - [EDI] <- EAX, then EDI is autoincremented */ 2# 10101010 LIT, ' C, , /* just compile the opcode */ ; : RET, /* ( -- ) (P ret ) */ /* return from subroutine - EIP <- [ESP], then ESP is autodecremented */ 2# 11000011 LIT, ' C, , /* just compile the opcode */ ; : CALLMI, /* ( addr -- ) (P kol-em-ai ) */ /* call subroutine - [ESP] <- EIP, then EIP <- addr */ 2# 11101000 LIT, ' C, , /* first compile the opcode */ ' HERE , ' - , ' , , /* then the offset */ ; : CALL, /* ( addr -- ) (P kol ) */ ' CALLMI, , ; /* just an alias for CALLMI */ : PUSHLR, /* ( -- ) (P push-el-ar ) */ /* push argument onto stack [real machine stack, not FORTH stack] */ 2# 01010000 LIT, ' | , /* OR with register */ ' C, , ; : PUSHL, /* ( -- ) (P push-el ) */ ' PUSHLR, , ; /* alias for PUSHLR, */ : POPLR, /* ( -- ) (P pop-el-ar ) */ /* pop argument from stack [real machine stack, not FORTH stack] */ 2# 01011000 LIT, ' | , /* OR with register */ ' C, , ; : POPL, /* ( -- ) (P pop-el ) */ ' POPLR, , ; /* alias for POPLR, */ : MOVLRR, /* ( -- ) (P muv-el-ar-ar ) */ /* move long value from one register to another */ 2# 10001001 LIT, ' C, , /* compile first byte of opcode */ ' SWAP , /* get source operand on TOS */ 10# 3 LIT, ' << , /* shift into position */ ' | , /* OR with destination... */ 2# 11000000 LIT, ' | , /* then with 2nd byte of opcode */ ' C, , /* finally, compile 2nd byte */ ; : MOVMR, /* ( -- ) (P muv-em-ar ) */ 2# 10001011 LIT, ' C, , /* compile first byte of opcode */ ' SWAP , /* get source operand on TOS */ 10# 3 LIT, ' << , /* shift into position */ ' | , /* OR with destination */ ' C, , /* compile 2nd byte of opcode */ ;