/* qm - The Quadruple Machine Copyright (C) 2004 Antti-Juhani Kaijanaho Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef QM_DS_H #define QM_DS_H #include #include #include "compat.h" #include "types.h" /* Data structures shared by the quadruple machine and its assembler. * WARNING: These are unportable between releases of the QM and QM-ASM * as well as between compilers used and systems where they run. */ /* Instruction is four words: first (lowest) word: opcode + addressing mode second word: opr1 address/immediate third word: opr2 address/immediate fourth word: opr3 address/immediate Opcode / addressing mode word: bits 0-5 opcode bits 6-8 operand type bit 9 reserved bits 10-16 opr1 addressing mode bits 17-23 opr2 addressing mode bits 24-30 opr3 addressing mode bit 31 reserved */ /* Instructions opcodes */ #define OP_HALT 0x00000000UL /* halt */ #define OP_SYSCALL 0x00000001UL /* syscall n */ #define OP_MOVE 0x00000002UL /* opr1 <- opr2 */ #define OP_ADD 0x00000003UL /* opr1 <- opr2 + opr3 */ #define OP_SUB 0x00000004UL /* opr1 <- opr2 - opr3 */ #define OP_MUL 0x00000005UL /* opr1 <- opr2 * opr3 */ #define OP_DIV 0x00000006UL /* opr1 <- opr2 / opr3 */ #define OP_MOD 0x00000007UL /* opr1 <- opr2 mod opr3 */ #define OP_AND 0x00000008UL /* opr1 <- opr2 and opr3 */ #define OP_OR 0x00000009UL /* opr1 <- opr2 or opr3 */ #define OP_XOR 0x0000000AUL /* opr1 <- opr2 xor opr3 */ #define OP_NOT 0x0000000BUL /* opr1 <- not opr2 */ #define OP_STAR 0x0000000CUL /* opr1 <- AR */ #define OP_STSP 0x0000000DUL /* opr1 <- SP */ #define OP_STFP 0x0000000EUL /* opr1 <- FP */ #define OP_STZL 0x0000000FUL /* opr1 <- ZL */ #define OP_LDAR 0x00000011UL /* AR <- opr1 */ #define OP_LDSP 0x00000012UL /* SP <- opr1 */ #define OP_LDFP 0x00000013UL /* FP <- opr1 */ #define OP_LDZL 0x00000014UL /* ZL <- opr1 */ #define OP_MVARSP 0x00000015UL /* SP <- AR */ #define OP_MVARFP 0x00000016UL /* FP <- AR */ #define OP_MVARZL 0x00000017UL /* ZL <- AR */ #define OP_MVSPAR 0x00000018UL /* AR <- SP */ #define OP_MVSPFP 0x00000019UL /* FP <- SP */ #define OP_MVSPZL 0x0000001AUL /* ZL <- SP */ #define OP_MVFPAR 0x0000001BUL /* AR <- FP */ #define OP_MVFPSP 0x0000001CUL /* SP <- FP */ #define OP_MVFPZL 0x0000001DUL /* ZL <- FP */ #define OP_MVZLAR 0x0000001EUL /* AR <- ZL */ #define OP_MVZLSP 0x0000001FUL /* SP <- ZL */ #define OP_MVZLFP 0x00000020UL /* FP <- ZL */ #define OP_INCSP 0x00000021UL /* SP <- SP + n */ #define OP_DECSP 0x00000022UL /* SP <- SP - n */ #define OP_EQ 0x00000023UL /* if opr1 = opr2 goto opr3 */ #define OP_LT 0x00000024UL /* if opr1 < opr2 goto opr3 */ #define OP_LE 0x00000025UL /* if opr1 <= opr2 goto opr3 */ #define OP_GT 0x00000026UL /* if opr1 > opr2 goto opr3 */ #define OP_GE 0x00000027UL /* if opr1 >= opr2 goto opr3 */ #define OP_NE 0x00000028UL /* if opr1 != opr2 goto opr3 */ #define OP_JMP 0x00000029UL /* goto opr1 */ /**/ #define FL_WU 0x00000000UL /* unsigned word */ #define FL_WS 0x00000040UL /* signed word */ #define FL_HU 0x00000080UL /* unsigned half-word */ #define FL_HS 0x000000C0UL /* signed half-word */ #define FL_BU 0x00000100UL /* unsigned byte */ #define FL_BS 0x00000140UL /* signed byte */ #define FL_FS 0x00000180UL /* single-precision floating-point */ #define FL_FD 0x000001C0UL /* double-precision floating-point */ #define AM_IMM 0x00000001UL /* constant, immediate data in opr word */ #define AM_ABS 0x00000002UL /* [address], address is in opr word */ #define AM_FPPD 0x00000003UL /* [FP+n], n is in opr word */ #define AM_FPND 0x00000004UL /* [FP-n], n is in opr word */ #define AM_SPPD 0x00000005UL /* [SP+n], n is in opr word */ #define AM_SPND 0x00000006UL /* [SP-n], n is in opr word */ #define AM_ARPD 0x00000007UL /* [AR+n], n is in opr word */ #define AM_ARND 0x00000008UL /* [AR-n], n is in opr word */ #define OP_MASK 0x0000003FUL #define FL_MASK 0x000001C0UL #define C_OPR1(op) ((op) >> 10 & 0x7f) #define C_OPR2(op) ((op) >> 17 & 0x7f) #define C_OPR3(op) ((op) >> 24 & 0x7f) #define MK_OPR(op,fl,opr1,opr2,opr3) \ (0UL | (op) | (fl) | (opr1) << 10 | (opr2) << 17 | (opr3) << 24) static inline int little_endian(void) { int x = 1; return *(char *)&x == 1; } static inline void pack(byte_t ba[4], word_t w) { ba[0] = w & 0xffUL; ba[1] = (w >> 8) & 0xffUL; ba[2] = (w >> 16) & 0xffUL; ba[3] = (w >> 24) & 0xffUL; } static inline word_t unpack(byte_t const ba[4]) { int w; if (little_endian()) { assert(sizeof(word_t) == 4); return (word_t)ba; } w = 0UL | ba[3] << 24 | ba[2] << 16 | ba[1] << 8 | ba[0]; } static inline void pack_double(byte_t ba[8], double d) { assert(sizeof (double) == 8); memcpy(ba, (byte_t *)&d, sizeof(double)); if (!little_endian()) { size_t i; for (i = 0; i < 8; i++) { ba[8-i-1] = ba[i]; } } } static inline double unpack_double(byte_t const ba[8]) { assert(sizeof (double) == 8); if (little_endian()) { return (double) *ba; } else { byte_t bb[8]; bb[7] = ba[0]; bb[6] = ba[1]; bb[5] = ba[2]; bb[4] = ba[3]; bb[3] = ba[4]; bb[2] = ba[5]; bb[1] = ba[6]; bb[0] = ba[7]; return (double) *bb; } } #define QM_MAGIC 0xC06C6BE4ul struct exe_hdr { word_t magic; /* QM_MAGIC */ word_t text_start; word_t text_length; word_t data_start; word_t data_length; word_t bss_length; word_t start_addr; word_t crc32; /* of this struct, including any padding by the * compiler, excluding this member... */ }; #endif /* QM_DS_H */