#ifndef __LC3_H__
#define __LC3_H__
/*
* "Copyright (c) 2012 by Fritz Sieker."
* based on ideas/code by Steven S. Lumetta
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written
* agreement is hereby granted, provided that the above copyright notice
* and the following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND THE AUTHOR NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*/
/** @file lc3.h
* @brief definitions of the LC3 instruction set architecture (ISA) (do not modify)
* @details This defines the details of the LC3 instruction set architecture
* (ISA). It is a separate file so that it can be shared by both an assembler
* and a simulator.
*
* @author Fritz Sieker
*/
#include
/** A handy way of declaring global variables in a header file */
#ifndef LC3_VAR
#define LC3_VAR extern
#endif
#include "symbol.h"
/** prototype for handy function to duplicate a string */
char* strdup(const char *);
/** LC3 words are 16 bits */
#define LC3_WORD unsigned short
/** The LC3 defines a memory accessed by a 16 bit address */
#define LC3_MEM_SIZE 65536
/** The LC3 contains 8 general purpose register, named R0..R7 */
#define LC3_NUM_REGS 8
/** Return address stored in R7 */
#define RETURN_ADDR_REG 7
/** Global flag defining whether using .obj file or .hex file */
LC3_VAR int inHex;
/** Global variable holding symbol table */
LC3_VAR sym_table_t* lc3_sym_tab;
/** The LC3 opcodes and pseudo-ops. The codes of OP_BR .. OP_TRAP corresponds
* exactly to the numeric values assigned to the 16 LC3 instructions. The
* codes assigned to the pseudo-ops is arbitrary. PCi is the incremented PC
*/
typedef enum opcode {
OP_INVALID = -1, /**< -1: invalid opcode */
OP_BR, /**< 0: PC = PCi + PCoffset9 if condition is met */
OP_ADD, /**< 1: DR = SR1 + SR2 or DR = SR1 + imm5 */
OP_LD, /**< 2: DR = mem[PCi + PCoffset9] */
OP_ST, /**< 3: mem[PCi + PCoffset9] = SR */
OP_JSR_JSRR, /**< 4: R7 = PCi and (PC = SR or PC = PCi + PCoffest9) */
OP_AND, /**< 5: DR = SR1 & SR2 */
OP_LDR, /**< 6: DR = mem[BaseR + offset6] */
OP_STR, /**< 7: mem[BaseR + offset6] = SR */
OP_RTI, /**< 8: PC = R7, exit supervisor mode */
OP_NOT, /**< 9: DR = ~SR1 */
OP_LDI, /**< 10: DR = mem[mem[PCi + PCoffset9]] */
OP_STI, /**< 11: mem[mem[PCi + offset9]] = SR */
OP_JMP_RET, /**< 12: PC = R7 (RET) or PC = Rx (JMP Rx) */
OP_RESERVED, /**< 13: Currently not used */
OP_LEA, /**< 14: DR = PCi + PCoffset9 */
OP_TRAP, /**< 15: R7 = PCi, PC = mem[mem[trap]], enter sys mode */
OP_ORIG, /**< 16: memory location where code is loaded */
OP_END, /**< 17: end of propgram - only comments may follow */
OP_BLKW, /**< 18: allocate N words of storage initialized with 0 */
OP_FILL, /**< 19: allocate 1 word of storage initialed with operand */
OP_STRINGZ, /**< 20: allocate N+1 words of storage initialized with
string and null terminator (1 char per word) */
OP_GETC, /**< 21: Read character from keyboard, no echo (trap x20) */
OP_OUT, /**< 22: Write one character (trap x21) */
OP_PUTS, /**< 23: Write null terminated string (trap x22) */
OP_IN, /**< 24: Print prompt and read/echo character (trap x23) */
OP_PUTSP, /**< 25: Write packed null terminated string (trap x24) */
OP_HALT, /**< 26: Halt execution (trap x25) */
OP_GETS, /**< 27: Read string from kbd, store in memory (trap x26) */
OP_ZERO, /**< 28: DR = 0 (AND DR,DR,#0) */
OP_COPY, /**< 29: DR = SR1 (ADD DR,SR1,#0) */
OP_NEG, /**< 30: DR = -DR (NOT DR,DR and ADD DR,DR,#1) */
NUM_OPCODES /**< 31: Initialized by compiler */
} opcode_t;
/** A bit field used to define the types of operands an individual
* LC3 instruction may have. Each value represents a different bit in
* the final result. When you see C code like this, it is likely that
* an integer value is used to represent an "array" of up to 32 boolean
* values. Each value is accessed with a mask that extracts the bit of
* interest. See the inst_format_t below.
*/
typedef enum operand {
FMT_R1 = 0x001, /**< DR or SR */
FMT_R2 = 0x002, /**< SR1 or BaseR */
FMT_R3 = 0x004, /**< SR2 */
FMT_CC = 0x008, /**< condition codes */
FMT_IMM5 = 0x010, /**< imm5 */
FMT_IMM6 = 0x020, /**< offset6 */
FMT_VEC8 = 0x040, /**< trapvect8 */
FMT_ASC8 = 0x080, /**< 8-bit ASCII */
FMT_IMM9 = 0x100, /**< label (or address from imm9) */
FMT_IMM11 = 0x200, /**< label (or address from imm11) */
FMT_IMM16 = 0x400, /**< full instruction in hex */
FMT_STR = 0x800 /**< operand is string literal */
} operand_t;
/** Define a combinatin of operands an opcode may have. For example, the
* the BR, LD, LDI, ST and STI instructions all have two parameters. The
* first is a register, the second is a nine bit offset. This form stores
* multiple boolean values in a single integer values by using individual
* bits to encode information.
*/
typedef enum operands {
FMT_ = 0,
FMT_RRR = (FMT_R1 | FMT_R2 | FMT_R3),
FMT_RRI5 = (FMT_R1 | FMT_R2 | FMT_IMM5),
FMT_CL = (FMT_CC | FMT_IMM9),
FMT_R = FMT_R2,
FMT_I11 = FMT_IMM11,
FMT_RL = (FMT_R1 | FMT_IMM9),
FMT_RRI6 = (FMT_R1 | FMT_R2 | FMT_IMM6),
FMT_RR = (FMT_R1 | FMT_R2),
FMT_V = FMT_VEC8,
FMT_A = FMT_ASC8,
FMT_16 = FMT_IMM16
} operands_t;
/** This structure stores the information for one form of an instruction.
* Several instructions have multiple forms, but most have only one.
*/
typedef struct inst_format {
char* name; /**< human readable name (e.g. "ADD") */
operands_t operands; /**< operands for this operation (e.g. FMT_RRR) */
int prototype; /**< bits that are constant in this instruction */
} inst_format_t;
/** This structure stores the information about a single instruction.
* See the usage in lc3.c where the information for each LC3 instruction
* is defined.
*/
typedef struct LC3_inst {
int formBit; /**< -1 if instruction has only one format,
else bit that differentiates format. */
inst_format_t forms[2]; /**< syntax for both possible forms */
} LC3_inst_t;
/** Get the information for an instruction, given its opcode This is simply
* an access into an array of values initialized with the information for
* each of the LC3's sixteen instructions and additional pseudo-ops.
* @param opcode - the opcode of the instruction/pseudo-op of interest
* @return - a pointer to the sytax information for this instruction or NULL
*/
LC3_inst_t* lc3_get_inst_info (opcode_t opcode);
/** Read an LC3 word (16 bits) from a file and return the value
* @param f - the object file
* @return the value, or -1 on EOF
*/
int lc3_read_LC3_word (FILE *f);
/** Write an LC3 word to a file in binary or hex
* @param f - the file to write to
* @param val - the value to write
*/
void lc3_write_LC3_word (FILE* f, int val);
#endif /* __LC3_H__ */