From a769f65a13db5546e427989d85f9646303f4fa32 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Tue, 8 Dec 2020 10:42:10 -0500 Subject: - Implemented support for the Orthogonal extension into both the assembler, and the emulator. I finally figured out how I could get support for the Ortho extension implemented into the old assembler. The only reason for doing this, is to buy me some while I start work on the new assembler, and to help me get an idea for how to do the same in the new assembler. --- asmmon.h | 166 ++++++-- assemble.c | 587 +++++++++++++++++++++----- disasm.c | 429 +++++++++++++++---- disasm.h | 71 ++++ enums.h | 159 ++++++- lexer.c | 388 ++++++++++------- lexer.h | 161 ++++++- opcode.h | 15 + programs/sub-suite/declare.s | 6 +- programs/sub-suite/lexer.s | 2 +- programs/sub-suite/libc.s | 81 ++-- programs/sub-suite/shift_line.c | 79 ++++ programs/sub-suite/subasm.s | 69 +-- programs/sub-suite/subeditor.s | 158 +++---- programs/sub-suite/subsuite.s | 1 + programs/sub-suite/utils.s | 105 +++-- sux.c | 44 +- sux.h | 904 ++++++++++++++++++++++++++++++---------- test/ortho.s | 35 ++ test/struct.s | 7 + 20 files changed, 2669 insertions(+), 798 deletions(-) create mode 100644 programs/sub-suite/shift_line.c create mode 100644 test/ortho.s diff --git a/asmmon.h b/asmmon.h index 6f4e5f5..7ed879b 100644 --- a/asmmon.h +++ b/asmmon.h @@ -4,17 +4,18 @@ #define MAX_TOK 0x1000 -typedef struct tok token ; -typedef struct ln line ; -typedef struct sym symbol ; -typedef struct fix fixup ; -typedef struct inst instruction; +typedef struct tok token ; +typedef struct ln line ; +typedef struct sym symbol ; +typedef struct fix fixup ; +typedef struct inst instruction ; struct tok { - token *next; /* Pointer to the next token. */ - uint8_t id; /* Token ID. */ - uint8_t type; /* Token type ID. */ + token *next; /* Pointer to the next token. */ + uint8_t id; /* Token ID. */ + uint8_t type; /* Token type ID. */ + uint8_t subtype; /* Token subtype ID. */ uint8_t tab; /* Number of tabs. */ uint8_t space; /* Number of spaces. */ @@ -118,6 +119,11 @@ enum token { TOK_BREG, TOK_OPCODE, TOK_EXTOP, + TOK_ORTHO, + TOK_REG, + TOK_MEM, + TOK_CC, + TOK_OS, TOK_RS, TOK_OF, TOK_COMMENT, @@ -128,7 +134,6 @@ enum token { TOK_STRUCT, TOK_UNION, TOK_MEMBER - }; enum pre_token { @@ -150,6 +155,11 @@ enum pre_token { PTOK_Y, PTOK_S, PTOK_P, + PTOK_A, + PTOK_C, + PTOK_D, + PTOK_F, + PTOK_R, PTOK_DQUOTE, PTOK_SQUOTE, PTOK_HASH, @@ -169,6 +179,7 @@ enum expr { EXPR_OR, EXPR_LSHFT, EXPR_RSHFT, + EXPR_MUL, EXPR_NONE }; @@ -193,6 +204,8 @@ enum addrmode { AM_AIND = (1 << 17), AM_AINDY = (1 << 18), AM_AINDX = (1 << 19), + AM_ORTHO = (1 << 20), + AM_ORTHO2 = (1 << 21) }; enum ind { @@ -231,6 +244,30 @@ enum eind { CPY_EIND }; +enum baseext_ortho { + OP_LEA, + OP_PEA, + OP_ADD, + OP_SUB, + OP_NOT, + OP_CLZ, + OP_CLO, + OP_SWP, + OP_PCN +}; + +static const uint8_t ext_ortho_ops[9] = { + [OP_LEA] = 0x63, + [OP_PEA] = 0x0C, + [OP_ADD] = 0x03, + [OP_SUB] = 0x23, + [OP_NOT] = 0x44, + [OP_CLZ] = 0xC4, + [OP_CLO] = 0xE4, + [OP_SWP] = 0x2C, + [OP_PCN] = 0x43 +}; + static const uint8_t ind_ops[20] = { [CMP_IND] = CMP_IN, [CMP_IDY] = CMP_IY, @@ -268,9 +305,9 @@ static const uint8_t eind_base_ops[10] = { }; static const instruction inst[OPNUM] = { - [ADC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x01}, - [AND] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x41}, - [ASR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x62}, + [ADC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x01}, + [AND] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x41}, + [ASR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x62}, [BCC] = {(AM_REL), 0xA0}, [BCS] = {(AM_REL), 0x90}, [BEQ] = {(AM_REL), 0xB0}, @@ -284,18 +321,18 @@ static const instruction inst[OPNUM] = { [CLC] = {(AM_IMPL), 0x09}, [CLI] = {(AM_IMPL), 0x29}, [CLV] = {(AM_IMPL), 0x49}, - [CMP] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_BREG|AM_INDX2|AM_EIND), 0x82}, + [CMP] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_BREG|AM_INDX2|AM_EIND|AM_ORTHO), 0x82}, [CPB] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_INDX2|AM_EIND2), 0x04}, [CPS] = {(AM_IMPL), 0x00}, [CPX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x24}, [CPY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x44}, [DEB] = {(AM_IMPL), 0x99}, - [DEC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2), 0x84}, + [DEC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2|AM_ORTHO2), 0x84}, [DEX] = {(AM_IMPL), 0xB9}, [DEY] = {(AM_IMPL), 0x79}, - [DIV] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x42}, + [DIV] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x42}, [INB] = {(AM_IMPL), 0xA9}, - [INC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2), 0xA4}, + [INC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2|AM_ORTHO2), 0xA4}, [INX] = {(AM_IMPL), 0xC9}, [INY] = {(AM_IMPL), 0x89}, [JMP] = {(AM_ABS|AM_IND|AM_ZM2|AM_EIND), 0x00}, @@ -304,9 +341,9 @@ static const instruction inst[OPNUM] = { [LDB] = {(AM_IMM|AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND), 0xE2}, [LDX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x64}, [LDY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND), 0xA2}, - [LSL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xA1}, - [LSR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xC1}, - [MUL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x22}, + [LSL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0xA1}, + [LSR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0xC1}, + [MUL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x22}, [NOP] = {(AM_IMPL), 0xEA}, [ORA] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x61}, [PHA] = {(AM_IMPL), 0x8E}, @@ -319,11 +356,11 @@ static const instruction inst[OPNUM] = { [PLP] = {(AM_IMPL), 0x7E}, [PLX] = {(AM_IMPL), 0xFE}, [PLY] = {(AM_IMPL), 0xDE}, - [ROL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xE1}, - [ROR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x02}, + [ROL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0xE1}, + [ROR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x02}, [RTI] = {(AM_IMPL), 0x60}, [RTS] = {(AM_IMPL), 0x50}, - [SBC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x21}, + [SBC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x21}, [SEC] = {(AM_IMPL), 0x19}, [SEI] = {(AM_IMPL), 0x39}, [STA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND2), 0x28}, @@ -341,19 +378,19 @@ static const instruction inst[OPNUM] = { [TYA] = {(AM_IMPL), 0x3A}, [TYX] = {(AM_IMPL), 0x6A}, [WAI] = {(AM_IMPL), 0x59}, - [XOR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x81} + [XOR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND|AM_ORTHO), 0x81} }; static const instruction ext_inst[EXT_OPNUM] = { - [LEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY), 0x03}, - [PEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY), 0x23}, - [ADD] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x06}, - [SUB] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x26}, + [LEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY|AM_ORTHO), 0x03}, + [PEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY|AM_ORTHO2), 0x23}, + [ADD] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND|AM_ORTHO), 0x06}, + [SUB] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND|AM_ORTHO), 0x26}, [ADE] = {(AM_IMM|AM_ZM|AM_ABS), 0x46}, [SBE] = {(AM_IMM|AM_ZM|AM_ABS), 0x66}, [ADS] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x86}, [SBS] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0xA6}, - [NOT] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND), 0xC6}, + [NOT] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND|AM_ORTHO2), 0xC6}, [LLM] = {(AM_ZM|AM_ABS|AM_EIND), 0x48}, [LRM] = {(AM_ZM|AM_ABS|AM_EIND), 0x68}, [RLM] = {(AM_ZM|AM_ABS|AM_EIND), 0x88}, @@ -373,12 +410,12 @@ static const instruction ext_inst[EXT_OPNUM] = { [STZ] = {(AM_ZM|AM_ABS|AM_EIND), 0xE0}, [SCO] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x60}, [ECO] = {(AM_ZM|AM_ABS|AM_EIND), 0x80}, - [CLZ] = {(AM_ZM|AM_ABS|AM_EIND), 0x05}, - [CLO] = {(AM_ZM|AM_ABS|AM_EIND), 0x25}, + [CLZ] = {(AM_ZM|AM_ABS|AM_EIND|AM_ORTHO2), 0x05}, + [CLO] = {(AM_ZM|AM_ABS|AM_EIND|AM_ORTHO2), 0x25}, [BIT] = {(AM_ZM|AM_ABS|AM_EIND), 0x45}, [MMV] = {(AM_IMPL), 0xCB}, - [SWP] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND), 0xE6}, - [PCN] = {(AM_ZM|AM_ABS|AM_EIND), 0xE8}, + [SWP] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND|AM_ORTHO2), 0xE6}, + [PCN] = {(AM_ZM|AM_ABS|AM_EIND|AM_ORTHO), 0xE8}, [REP] = {(AM_REL), 0xBD}, [REQ] = {(AM_REL), 0xCD}, [RNE] = {(AM_REL), 0xDD}, @@ -396,6 +433,25 @@ static const instruction ext_inst[EXT_OPNUM] = { [SNE] = {(AM_EIND2), 0xBD} }; +static const instruction ortho_inst[ORTHO_OPNUM] = { + [MNG] = {(AM_ORTHO), 0x00}, + [MPO] = {(AM_ORTHO), 0x20}, + [MCS] = {(AM_ORTHO), 0x40}, + [MCC] = {(AM_ORTHO), 0x60}, + [MEQ] = {(AM_ORTHO), 0x80}, + [MNE] = {(AM_ORTHO), 0xA0}, + [MVS] = {(AM_ORTHO), 0xC0}, + [MVC] = {(AM_ORTHO), 0xE0}, + [OR ] = {(AM_ORTHO), 0x61}, + [MOV] = {(AM_ORTHO), 0xA2}, + [IML] = {(AM_ORTHO), 0xC2}, + [IDV] = {(AM_ORTHO), 0xE2}, + [PSH] = {(AM_ORTHO2), 0x04}, + [PUL] = {(AM_ORTHO2), 0x24}, + [NEG] = {(AM_ORTHO2), 0x64}, + [SET] = {(AM_ORTHO2), 0x05} +}; + static const char *dir_t[11] = { [ 0] = "org", [ 1] = "byte", @@ -417,7 +473,7 @@ static const char *rs_t[4] = { [3] = ".q" }; -static const char *lex_tok[23] = { +static const char *lex_tok[] = { [TOK_DIR ] = "TOK_DIR", [TOK_LOCAL ] = "TOK_LOCAL", [TOK_LABEL ] = "TOK_LABEL", @@ -431,6 +487,11 @@ static const char *lex_tok[23] = { [TOK_BREG ] = "TOK_BREG", [TOK_OPCODE ] = "TOK_OPCODE", [TOK_EXTOP ] = "TOK_EXTOP", + [TOK_ORTHO ] = "TOK_ORTHO", + [TOK_REG ] = "TOK_REG", + [TOK_MEM ] = "TOK_MEM", + [TOK_CC ] = "TOK_CC", + [TOK_OS ] = "TOK_OS", [TOK_RS ] = "TOK_RS", [TOK_OF ] = "TOK_OF", [TOK_COMMENT] = "TOK_COMMENT", @@ -461,6 +522,11 @@ static const char *adrmode[] = { [AINDX] = "AINDX", [AINDY] = "AINDY", [EIND ] = "EIND" +/* [ZMR ] = "ZMR", + [ZINDR] = "ZINDR", + [ZRIND] = "ZRIND", + [AINDR] = "AINDR", + [AINDY] = "ARIND",*/ }; static const char *mne[OPNUM] = { @@ -592,6 +658,36 @@ static const char *ext_mne[EXT_OPNUM] = { [SNE] = "SNE" }; +static const char *ortho_mne[ORTHO_OPNUM] = { + [MNG] = "MNG", + [MPO] = "MPO", + [MCS] = "MCS", + [MCC] = "MCC", + [MEQ] = "MEQ", + [MNE] = "MNE", + [MVS] = "MVS", + [MVC] = "MVC", + [OR ] = "OR", + [MOV] = "MOV", + [IML] = "IML", + [IDV] = "IDV", + [PSH] = "PSH", + [PUL] = "PUL", + [NEG] = "NEG", + [SET] = "SET" +}; + +static const char *set_cc[8] = { + "NG", + "PO", + "CS", + "CC", + "EQ", + "NE", + "VS", + "VC" +}; + static const char *instdesc[OPNUM] = { [ADC] = "ADd accumulator, with operand, Carry if needed.", [AND] = "Bitwise AND accumulator, with operand.", @@ -708,8 +804,8 @@ extern uint8_t isfixup; extern line *find_line(uint32_t ln, uint8_t dbg); extern uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg); -extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg); -extern token *skip_expr(token *t, uint8_t dbg); +extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg); +extern token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg); extern uint64_t parse_tokens(token *tm, line **l, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg); extern token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t value, char *str, symbol *s); extern void assemble(line *ln, bytecount *bc, uint8_t dbg); diff --git a/assemble.c b/assemble.c index 297be87..87d0464 100644 --- a/assemble.c +++ b/assemble.c @@ -82,6 +82,21 @@ uint8_t get_eind(uint8_t mne, uint8_t dbg) { return 0xFF; } +uint8_t get_ext_ortho(uint8_t mne, uint8_t dbg) { + switch (mne) { + case LEA: return OP_LEA; + case PEA: return OP_PEA; + case ADD: return OP_ADD; + case SUB: return OP_SUB; + case NOT: return OP_NOT; + case CLZ: return OP_CLZ; + case CLO: return OP_CLO; + case SWP: return OP_SWP; + case PCN: return OP_PCN; + } + return 0xFF; +} + static void write_value(uint64_t value, uint64_t address, uint8_t size) { if (address < mem_size) { size = (size > 7) ? 7 : size; @@ -98,16 +113,23 @@ static void write_value(uint64_t value, uint64_t address, uint8_t size) { } } -uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { +uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) { uint64_t value = 0; uint64_t tmp_val = 0; uint8_t type = EXPR_NONE; uint8_t isstart = 1; + int done = 0; do { if (t->id == TOK_EXPR) { type = t->type; t = t->next; } + if (stop_comma && t->subtype == TOK_CSV) { + done = 1; + } + if (stop_comma && t->id == TOK_REG) { + break; + } switch (t->id) { case TOK_HEX: case TOK_DEC: @@ -119,6 +141,10 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { tmp_val = (t->sym) ? t->sym->val : addr; t = t->next; break; + default: tmp_val = 0; + } + if (end_expr != 0xFF && type == end_expr) { + break; } switch (type) { case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break; @@ -150,13 +176,19 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { if (dbg) { printf("get_val(): Value: $%"PRIX64", Expression type: $%X, Expression Value: $%"PRIX64".\n", value, type, tmp_val); } - } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); + } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg)); return value; } -token *skip_expr(token *t, uint8_t dbg) { +token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) { + int done = 0; + int is_reg = 0; do { - t = (t->id == TOK_EXPR) ? t->next : t; + is_reg = (t && t->next && t->next->id == TOK_REG); + t = (t->id == TOK_EXPR && !is_reg) ? t->next : t; + if (is_reg || (stop_comma && (t->subtype == TOK_CSV))) { + done = 1; + } switch (t->id) { case TOK_HEX : case TOK_DEC : @@ -165,7 +197,10 @@ token *skip_expr(token *t, uint8_t dbg) { case TOK_SYM : case TOK_LABEL: t = t->next; break; } - } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); + if (end_expr != 0xFF && t->id == TOK_EXPR && t->type == end_expr) { + break; + } + } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg)); return t; } @@ -227,7 +262,7 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg case DIR_QWORD : member_size = 8; break; case DIR_UNION : case DIR_STRUCT: member_size = handle_struct(&l, address, offset, dbg); break; - case DIR_RES : member_size = get_val(t, address, 3, dbg); t = skip_expr(t, dbg); break; + case DIR_RES : member_size = get_val(t, address, 3, 0xFF, 0, dbg); t = skip_expr(t, 0xFF, 0, dbg); break; } if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) { member->val = offset; @@ -270,7 +305,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre case TOK_CHAR: case TOK_SYM: case TOK_LABEL: - val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg); + val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), 0xFF, 0, dbg); switch (type) { case DIR_QWORD: tmp = 8; break; case DIR_DWORD: tmp = 4; break; @@ -281,7 +316,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre tmpaddr += tmp; bc->datasize += tmp; if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) { - t = skip_expr(t, dbg); + t = skip_expr(t, 0xFF, 0, dbg); } break; case TOK_STRING: @@ -323,9 +358,13 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre return tmpaddr; } -static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, uint64_t value, uint64_t address, uint8_t size, uint8_t isasm, uint8_t dbg) { +static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, operand *op, uint64_t address, uint8_t *op_size, uint8_t isasm, uint8_t dbg) { uint8_t inst_size = 0; + uint8_t op_ins_size[2]; union reg ins; + union reg op_ins[2]; + memset(op_ins_size, 0, sizeof(op_ins_size)); + memset(op_ins, 0, sizeof(op_ins_size)); if (prefix & 3) { ins.u8[inst_size++] = prefix; } @@ -333,16 +372,216 @@ static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, ui ins.u8[inst_size++] = ext_prefix; } ins.u8[inst_size++] = opcode; + if (ext_prefix == 0x1D) { + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + ins.u8[inst_size] |= (op[i].id << (!i*4)); + } + inst_size++; + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + int is_sib = 0; + if (op[i].type == 1) { + int reg = 0; + switch (op[i].id) { + case MEM_SIB : op_ins[i].u8[op_ins_size[i]++] = op[i].scale; /* Falls through. */ + case MEM_ABSR : + case MEM_ARIND: + case MEM_AINDR: + case MEM_ZMR : + case MEM_ZRIND: + case MEM_ZINDR: + case MEM_RIND : + op_ins[i].u8[op_ins_size[i]] = op[i].rind[reg]; + reg = (op[i].rind[1] != 0xFF); + op_ins[i].u8[op_ins_size[i]++] |= op[i].rind[reg] << 4; + break; + } + } + } + } if (isasm) { + if (dbg) { + printf("$%04"PRIX64":\t", address); + for (int i = 0; i < inst_size; i++) { + printf("%02X", ins.u8[i]); + if (i < inst_size-1) { + putchar(' '); + } + } + } write_value(ins.u64, address, inst_size-1); - if (size) { - write_value(value, address+inst_size, size-1); + } + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + if (op[i].type == 1) { + if (ext_prefix == 0x1D && op_ins_size[i]) { + if (isasm) { + if (dbg) { + putchar(' '); + for (int j = 0; j < op_ins_size[i]; j++) { + printf("%02X", op_ins[i].u8[j]); + if (j < op_ins_size[i]-1) { + putchar(' '); + } + } + } + write_value(op_ins[i].u64, address+inst_size, op_ins_size[i]-1); + } + inst_size += op_ins_size[i]; + } + if (op_size[i] && (ext_prefix != 0x1D || (ext_prefix == 0x1D && op[i].id != MEM_SIB && op[i].id != MEM_RIND))) { + if (isasm) { + if (dbg) { + uint8_t *tmp = (uint8_t *)&op[i].value; + putchar(' '); + for (int j = 0; j < op_size[i]; j++) { + printf("%02X", tmp[j]); + if (j < op_size[i]-1) { + putchar(' '); + } + } + } + write_value(op[i].value, address+inst_size, op_size[i]-1); + } + inst_size += op_size[i]; + } } } - inst_size += size; + if (isasm && dbg) { + putchar('\n'); + } return inst_size; } +token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t dbg) { + uint8_t op_type; + uint8_t op_inst; + /*switch (t->id) { + case TOK_OPCODE: + case TOK_EXTOP : + case TOK_ORTHO : + op_type = t->id; + op_inst = t->byte; + t = t->next; + break; + }*/ + int i = 0; + int old_i = -1; + uint8_t expr_type = 0xFF; + uint8_t stop_comma = 0; + uint64_t value = 0; + uint8_t reg = 0; + uint8_t got_value = 0; + uint8_t is_sib = 0; + uint8_t brack_done = 0; + uint8_t is_comma = 0; + token *tmp = t; + /*for (; tmp; tmp = tmp->next) { + printf("t: %p, t->id: $%X, t->id: %s, t->subtype: $%X, t->subtype: %s\n", tmp, tmp->id, (tmp->id <= TOK_MEMBER) ? lex_tok[tmp->id] : "TOK_NONE", tmp->subtype, (tmp->subtype == TOK_IND || tmp->subtype == TOK_CSV) ? lex_tok[tmp->subtype] : "TOK_NONE"); + }*/ + + for (; t && i < 2; t = t->next) { + if (t->subtype == TOK_IND) { + brack_done = 1; + } + switch (t->id) { + case TOK_HEX : + case TOK_DEC : + case TOK_BIN : + case TOK_SYM : + case TOK_CHAR : + case TOK_LABEL: + if (!got_value) { + expr_type = (expr_type == 0xFF && t->next && t->next->id == TOK_EXPR) ? t->next->type : expr_type; + switch (expr_type) { + default : stop_comma = 1; break; + case EXPR_MUL : stop_comma = 0; break; + } + is_sib = (!stop_comma && op[i].type && op[i].id == MEM_IND); + value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + op[i].value = (!is_sib) ? value : op[i].value; + got_value = 1; + } else { + op[i].value = (!is_sib) ? value : op[i].value; + got_value = 0; + } + if ((op[i].type == 1 && op[i].id == MEM_RIND) || (!op[i].type)) { + op[i].is_ind = (op[i].type == 1 && op[i].id == MEM_RIND); + op[i].type = 1; + op[i].rind[0] = (op[i].rind[0] == 0xFF) ? op[i].id : op[i].rind[0]; + op[i].id = MEM_ZMR; + } + is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); + is_comma = (is_comma >= 2) ? 0 : is_comma; + /* Falls Through. */ + case TOK_MEM: + is_comma = (t->id == TOK_MEM) ? 0 : is_comma; + if (old_i != i) { + op[i].type = 1; /* Set type to memory. */ + op[i].id = (t->id == TOK_MEM) ? t->type : 0xFF; + op[i].id = (is_sib) ? MEM_SIB : op[i].id; + op[i].scale = (is_sib) ? value : op[i].scale; + old_i = i; + } else { + if (!op[i].type && !is_sib) { + op[i].type = 1; + op[i].id = MEM_ZMR; + } + } + if (got_value && !is_comma) { + if (t && t->subtype != TOK_CSV) { + t = skip_expr(t, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + } + } + i += is_comma; + if (old_i != i) { + got_value = 0; + } + break; + case TOK_REG: + if (old_i != i) { + op[i].type = 0; /* Set type to register. */ + op[i].id = t->type; + old_i = i; + } else { + if (op[i].type == 1) { + if (op[i].id == MEM_IND) { + op[i].id = (!brack_done && got_value) ? MEM_ZRIND : MEM_RIND; + op[i].id = (brack_done && got_value) ? MEM_ZINDR : op[i].id; + brack_done = 0; + } else { + op[i].id = (got_value) ? MEM_ZMR : op[i].id; + } + op[i].rind[reg] = t->type; + reg++; + reg = (reg > 1) ? 0 : reg; + } + } + is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); + is_comma = (is_comma >= 2) ? 0 : is_comma; + i += is_comma; + break; + case TOK_EXPR: + expr_type = t->type; + switch (expr_type) { + default : stop_comma = 1; break; + case EXPR_MUL : stop_comma = 0; break; + } + if (!got_value) { + if (t->next && t->next->id != TOK_REG) { + value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + got_value = 1; + } + } else { + got_value = 0; + } + break; + } + if (!t) { + break; + } + } + return t; +} + uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) { union reg val; uint8_t opsize; @@ -352,44 +591,66 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t ext_prefix = 0; uint8_t type; uint32_t am = 0; - uint8_t tmp = 0; + uint8_t op_size[2]; uint8_t prefix = 0; uint8_t rs = 0; uint8_t of = 0; uint8_t tmp_prefix = 0; uint8_t inst_size = 0; + int is_ortho = 0; val.u64 = 0; instruction ins; - - for (; t; t = t->next) { - if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) { + operand op[2]; + memset(op, 0xFF, sizeof(op)); + op_size[0] = 0; + op_size[1] = 0; + if (t) { + if (t->id == TOK_OPCODE || t->id == TOK_EXTOP || t->id == TOK_ORTHO) { id = t->id; instr = t->byte; type = t->type; } else { - break; + return address; } - tmp = 0; + /*tmp = 0;*/ opsize = 1; opcode = 0; if (t->next) { rs = get_rs(t->next, dbg); t = (rs != 0xFF) ? t->next : t; if (t->next) { - of = get_of(t->next, dbg); - t = (of != 0xFF) ? t->next : t; + is_ortho = (t->next->id == TOK_OS); + t = (is_ortho) ? t->next : t; + if (t->next) { + of = get_of(t->next, dbg); + t = (of != 0xFF) ? t->next : t; + } } } + get_operands(t, op, address, rs, dbg); + if (dbg) { + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + printf("%i: op.type: %u, op.id: $%X, op.scale; $%X, op.rind[0]: $%X, op.rind[1]: $%X, op.value: $%"PRIX64"\n", i, op[i].type, op[i].id, op[i].scale, op[i].rind[0], op[i].rind[1], op[i].value); + } + } + uint8_t is_eind = (op[0].type == 1 && op[0].id == MEM_RIND && op[0].rind[0] == REG_E); + uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM); + uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y)); + of = (is_mem && (op[0].id == MEM_RIND || op[0].id == MEM_ZMR) && op[0].rind[0] == REG_SP) ? 1 : of; if (rs != 0xFF || of != 0xFF) { tmp_prefix = (rs != 0xFF) ? (rs << 0) : tmp_prefix; tmp_prefix |= (of != 0xFF) ? (of << 2) : tmp_prefix; } prefix = (tmp_prefix) ? ((tmp_prefix << 4) | 3) : 0; uint8_t isincdec = (instr == INC || instr == DEC); - uint8_t isimplied = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF); - ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr]; + uint8_t isimplied = (op[0].type == 0xFF); + switch (id) { + case TOK_OPCODE: ins = inst[instr]; break; + case TOK_EXTOP : ins = ext_inst[instr]; break; + case TOK_ORTHO : ins = ortho_inst[instr]; break; + } am = ins.am; - if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) { + if (id == TOK_EXTOP || (id == TOK_OPCODE && is_eind)) { ext_prefix = 0x0D; } if ((am & AM_IMPL) && isimplied) { @@ -398,12 +659,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, if (ins.am & AM_REL) { type = REL; } - if (t->next) { - t = t->next; - } - if (type != BREG && type != EIND) { - val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg); - } } opcode = ins.op; uint64_t saveaddr = address; @@ -411,62 +666,73 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t i = 0; uint8_t j = 1; uint8_t type2 = 0xFF; - switch (type) { - case BREG: - case IMPL: - case EIND: - if (id == TOK_OPCODE && instr == CPS) { - rs = 0; - } - if ((am & (AM_IMPL|AM_BREG|AM_EIND|AM_EIND2))) { - if ((type == EIND) && (am & AM_EIND|AM_EIND2)) { - int eind_type = ((am & AM_EIND2) != 0); - switch (eind_type) { - case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break; - case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break; - } - } - opcode = (am & AM_BREG) ? opcode+0x14 : opcode; - } - break; - case REL: - case IMM: - if (am & (AM_IMM|AM_REL)) { - rs = (rs != 0xFF) ? rs : 0; - tmp = (1 << rs); - if (type == REL) { - uint64_t max_sign = 0; - uint8_t offset = 1; - uint64_t tmp_val; - tmp_val = val.u64; - offset += (prefix != 0); - tmp_val -= offset+tmp; - tmp_val -= address; - switch (rs) { - default: max_sign = (int8_t )(1 << 7); break; - case 1 : max_sign = (int16_t)(1 << 15); break; - case 2 : max_sign = (int32_t)(1 << 31); break; - case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break; - } - if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) { - offset += (!rs); - rs += (rs <= 3); - tmp = (1 << rs); - tmp_val = val.u64; - tmp_val -= offset+tmp; - tmp_val -= address; - prefix = ((rs << 4) | 3); - } - val.u64 = tmp_val; + if (!is_ortho) { + is_ortho = (id == TOK_ORTHO); + } + int is_valid = 1; + if (!is_ortho && (is_mem || is_idx)) { + switch (op[0].id) { + case MEM_AINDR: + case MEM_ZINDR: + case MEM_ARIND: + case MEM_ZRIND: + case MEM_SIB : is_valid = 0; break; + case MEM_ZMR : + case MEM_ABSR : + case MEM_RIND : + default : + if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) { + is_valid = 0; + } else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) { + is_valid = (of != 0xFF || op[0].rind[0] == REG_SP); + } else if (is_mem && op[1].type == 1) { + is_valid = 0; } - } - break; - default: + break; + } + } else if (is_ortho) { + is_valid = 0; + } + if (type == IMPL && (am & AM_IMPL)) { + if (id == TOK_OPCODE && instr == CPS) { + rs = 0; + } + opcode = opcode; + is_ortho = 0; + } else if (type == REL) { + rs = (rs != 0xFF) ? rs : 0; + op_size[0] = (1 << rs); + uint64_t max_sign = 0; + uint8_t offset = 1; + uint64_t tmp_val; + tmp_val = op[0].value; + offset += (prefix != 0); + tmp_val -= offset+op_size[0]; + tmp_val -= address; + switch (rs) { + default: max_sign = (int8_t )(1 << 7); break; + case 1 : max_sign = (int16_t)(1 << 15); break; + case 2 : max_sign = (int32_t)(1 << 31); break; + case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break; + } + if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) { + offset += (!rs); + rs += (rs <= 3); + op_size[0] = (1 << rs); + tmp_val = op[i].value; + tmp_val -= offset+op_size[0]; + tmp_val -= address; + prefix = ((rs << 4) | 3); + } + op[0].value = tmp_val; + is_ortho = 0; + } else if (id != TOK_ORTHO) { + if (!is_eind && is_valid && (is_mem || is_idx)) { if (of != 0xFF) { i = 8; for (; i <= 64; i += 8, j++) { max_val |= ((uint64_t)1 << (i-1)); - if ((int64_t)val.u64 >= ~(int64_t)(max_val) || (int64_t)val.u64 <= (int64_t)(max_val)) { + if ((int64_t)op[0].value >= ~(int64_t)(max_val) || (int64_t)op[0].value <= (int64_t)(max_val)) { opsize = j; break; } @@ -474,12 +740,20 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } else { for (; i <= 64; i += 8, j++) { max_val |= (0xFF << i); - if (val.u64 <= max_val) { + if (op[0].value <= max_val) { opsize = j; break; } } } + if (is_idx) { + switch (op[1].id) { + case REG_X: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDX : ZMX; break; + case REG_Y: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDY : ZMY; break; + } + } else { + type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? IND : 0xFF; + } type2 = type; if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) { switch (opsize-1) { @@ -520,71 +794,192 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, opcode += 0x04; } else if (am & AM_ZM2) { opcode += 0x20; + } else { + is_ortho = 1; } break; case ZMX: if (am & AM_ZMX) { opcode += (id == TOK_OPCODE) ? 0x06 : 0x54; + } else { + is_ortho = 1; } break; case ZMY: if (am & AM_ZMY) { opcode += 0x14; + } else { + is_ortho = 1; } break; case INDX: if (am & AM_INDX) { opcode += (id == TOK_OPCODE) ? 0x16 : 0x94; break; + } else { + is_ortho = 1; } /* Falls Through. */ case IND: case INDY: if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) { opcode = ind_ops[get_ind(instr, type, dbg)]; - } else { + } else if (id = TOK_EXTOP) { opcode += (type == IND) ? 0x44 : 0x84; + } else { + is_ortho = 1; } break; case ABS: if (am & AM_ABS) { opcode += 0x10; + } else { + is_ortho = 1; } break; case ABSX: if (am & AM_ABX) { opcode += 0x50; + } else { + is_ortho = 1; } break; case ABSY: if (am & AM_ABY) { opcode += 0x00; + } else { + is_ortho = 1; } break; case AIND: if (am & AM_AIND) { opcode += 0x40; + } else { + is_ortho = 1; } break; case AINDX: if (am & AM_AINDX) { opcode += 0x90; + } else { + is_ortho = 1; } break; case AINDY: if (am & AM_AINDY) { opcode += 0x80; + } else { + is_ortho = 1; } break; } - tmp = opsize; + op_size[0] = opsize; } - break; + + } else if (op[1].type == 0xFF) { + if (!op[0].type) { + if (op[0].id == REG_B && (am & AM_BREG)) { + opcode += 0x14; + } else if (op[0].id == REG_A && (am & AM_IMPL)) { + opcode = opcode; + } else { + is_ortho = 1; + } + } else { + if (is_eind && (am & AM_EIND|AM_EIND2)) { + int eind_type = ((am & AM_EIND2) != 0); + switch (eind_type) { + case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break; + case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break; + } + } else if ((op[0].id == MEM_IMM) && (am & AM_IMM)) { + rs = (rs != 0xFF) ? rs : 0; + op_size[0] = (1 << rs); + } else { + is_ortho = 1; + } + } + } else { + is_ortho = 1; + } + } + if (is_ortho) { + ext_prefix = 0x1D; + if (id == TOK_EXTOP) { + opcode = ext_ortho_ops[get_ext_ortho(instr, dbg)]; + } + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + int i2 = 0; + int j = 0; + (op[i].type == 1) ? (opcode |= (1 << (3+!i))) : (opcode &= ~(1 << (3+!i))); + if (op[i].type == 1 && (am & AM_ORTHO|AM_ORTHO2)) { + switch (op[i].id) { + case MEM_RIND: break; + case MEM_IMM: + rs = (rs != 0xFF) ? rs : 0; + op_size[i] = (1 << rs); + break; + case MEM_ZRIND: + case MEM_ZINDR: + case MEM_ZMR: + case MEM_IND: + default: + if (of != 0xFF) { + max_val = 0; + for (i2 = 8, j = 1; i2 <= 64; i2 += 8, j++) { + max_val |= ((uint64_t)1 << (i2-1)); + if ((int64_t)op[i].value >= ~(int64_t)(max_val) || (int64_t)op[i].value <= (int64_t)(max_val)) { + opsize = j; + break; + } + } + } else { + max_val = 0; + for (i2 = 0, j = 1; i2 <= 64; i2 += 8, j++) { + max_val |= (0xFF << i2); + if (op[i].value <= max_val) { + opsize = j; + break; + } + } + } + switch (opsize-1) { + case 0: case 2: case 5: case 3: type = ZM ; break; + case 1: case 4: case 6: case 7: type = ABS; break; + } + switch (op[i].id) { + case MEM_IND : op[i].id = (type == ABS) ? MEM_AIND : op[i].id; break; + case MEM_ZMR : op[i].id = (type == ABS) ? MEM_ABSR : op[i].id; break; + case MEM_ZRIND: op[i].id = (type == ABS) ? MEM_ARIND : op[i].id; break; + case MEM_ZINDR: op[i].id = (type == ABS) ? MEM_AINDR : op[i].id; break; + case 0xFF : op[i].id = (type == ABS) ? MEM_ABS : MEM_ZM; break; + } + if (opsize) { + uint8_t is_abs = (type == ABS); + if (!is_abs) { + switch (opsize) { + case 2: opsize = 3; break; + case 5: opsize = 6; break; + } + } + prefix |= amp[opsize-1]; + } + op_size[i] = opsize; + if (isasm /*&& dbg*/) { + printf("op_size[%i]: %i, opsize: %u\n", i, op_size[i], opsize); + } + break; + } + } + } } - inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg); + inst_size = write_inst(prefix, ext_prefix, opcode, op, address, op_size, isasm, /*dbg*/isasm); address += inst_size; bc->progsize += inst_size; + if (isasm /*&& dbg*/) { + printf("inst_size: $%X, bc->progsize: $%"PRIX64"\n", inst_size, bc->progsize); + } } return address; } @@ -596,14 +991,15 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t switch (t->type) { case DIR_STRUCT: case DIR_UNION : handle_struct(l, address, 0, dbg); break; - case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break; - case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break; + case DIR_RES: t = t->next; address += get_val(t, address, 3, 0xFF, 0, dbg); break; + case DIR_ORG: t = t->next; address = get_val(t, address, 3, 0xFF, 0, dbg); break; case DIR_BYTE: case DIR_WORD: case DIR_DWORD: case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break; } break; + case TOK_ORTHO : case TOK_EXTOP : case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break; case TOK_COMMENT: break; @@ -618,6 +1014,7 @@ token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t new_tok->id = id; new_tok->type = type; + new_tok->subtype = 0xFF; new_tok->tab = tab; new_tok->space = space; @@ -806,29 +1203,13 @@ void fix_symtree(line *l) { if ((!is_structsym) || (isanon && is_structsym)) { isanon++; } - } else if (t->type == DIR_ENDSTRUCT || t->type == DIR_ENDUNION) { - is_struct--; - int skip = 0; - if (isanon > 0) { - if ((cur_sym->up && !cur_sym->up->isanon) || (sym_struct && sym_struct->isanon)) { - isanon--; - } - skip = (!isanon); - } - if ((int)(is_struct-isanon) > 0 && !skip && cur_sym->up) { - for (sym_struct = s->up; sym_struct->prev && !sym_struct->isanon; sym_struct = sym_struct->prev); - s = s->up; - cur_sym = (cur_sym->up != NULL) ? cur_sym->up : s; - } } break; } - lt = t; } } } - static inline void free_tokens(token *t) { token *tok; if (t != NULL) { diff --git a/disasm.c b/disasm.c index 8c16db6..74dac5f 100644 --- a/disasm.c +++ b/disasm.c @@ -2,6 +2,16 @@ #include "disasm.h" #include +#define ORTHO_1CC(mne, cc) \ + mne##_R##cc: case mne##_M##cc + +#define ORTHO_1OP(mne) \ + mne##_R: case mne##_M + +#define ORTHO_2OP(mne) \ + mne##_RR: case mne##_RM: case mne##_MR: case mne##_MM + + void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread) { for (uint8_t i = (24*thread)+2; i <= 24*(thread+1); i++) { wmove(scr, i, 0); @@ -24,9 +34,271 @@ void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread) { wprintw(scr, ", inst: "); } -void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t thread) { +static uint64_t get_offset(uint64_t value, uint8_t size, char **sign) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; + uint64_t mask = (-(uint64_t)1 >> ((8 - size) * 8)); + mask &= (1 << (msb-1)); + *sign = ((value >> (msb-1)) & 1) ? "-" : "+"; + if (*sign[0] == '-') { + value &= mask; + value = -(value+1); + } + return value; +} + +/* Checks if the opcode, and operands required an ortho suffix. */ +static int is_os(uint8_t opcode, operand *op) { + uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM); + uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y)); + int is_valid = 1; + int is_sp = 0; + if (is_mem || is_idx) { + switch (op[0].id) { + case MEM_AINDR: + case MEM_ZINDR: + case MEM_ARIND: + case MEM_ZRIND: + case MEM_SIB : is_valid = 0; break; + case MEM_ZMR : + case MEM_ABSR : + case MEM_RIND : + default : + if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) { + is_valid = 0; + } else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) { + is_valid = (op[0].rind[0] == REG_SP); + is_sp = (op[0].rind[0] == REG_SP); + } else if (is_mem && op[1].type == 1) { + is_valid = 0; + } + break; + } + } + switch (opcode) { + case ORTHO_2OP(CMP): return (is_idx && is_valid && ((is_sp && op[0].id == MEM_RIND) || (!is_sp && op[0].id == MEM_IND))); + case ORTHO_2OP(LEA): return (is_idx && is_valid); + } + return 0; +} + +static int is_1cc(uint8_t opcode) { + switch (opcode) { + case ORTHO_1CC(SET, NG): + case ORTHO_1CC(SET, PO): + case ORTHO_1CC(SET, CS): + case ORTHO_1CC(SET, CC): + case ORTHO_1CC(SET, EQ): + case ORTHO_1CC(SET, NE): + case ORTHO_1CC(SET, VS): + case ORTHO_1CC(SET, VC): return 1; + } + return 0; +} + +static int is_1op(uint8_t opcode) { + switch (opcode) { + case ORTHO_1OP(PSH): + case ORTHO_1OP(PEA): + case ORTHO_1OP(PUL): + case ORTHO_1OP(SWP): + case ORTHO_1OP(NOT): + case ORTHO_1OP(NEG): + case ORTHO_1OP(DEC): + case ORTHO_1OP(INC): + case ORTHO_1OP(CLZ): + case ORTHO_1OP(CLO): return 1; + } + return 0; +} + +static int is_2op(uint8_t opcode) { + switch (opcode) { + case ORTHO_2OP(MNG): + case ORTHO_2OP(ADC): + case ORTHO_2OP(ROR): + case ORTHO_2OP(ADD): + case ORTHO_2OP(MPO): + case ORTHO_2OP(SBC): + case ORTHO_2OP(MUL): + case ORTHO_2OP(SUB): + case ORTHO_2OP(MCS): + case ORTHO_2OP(AND): + case ORTHO_2OP(DIV): + case ORTHO_2OP(PCN): + case ORTHO_2OP(MCC): + case ORTHO_2OP(OR ): + case ORTHO_2OP(ASR): + case ORTHO_2OP(LEA): + case ORTHO_2OP(MEQ): + case ORTHO_2OP(XOR): + case ORTHO_2OP(CMP): + case ORTHO_2OP(MNE): + case ORTHO_2OP(LSL): + case ORTHO_2OP(MOV): + case ORTHO_2OP(MVS): + case ORTHO_2OP(LSR): + case ORTHO_2OP(IML): + case ORTHO_2OP(MVC): + case ORTHO_2OP(ROL): + case ORTHO_2OP(IDV): return 1; + } + return 0; +} + +static void disasm_ortho(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t prefix2, uint64_t *value, char *inst_name, char *postfix, operand *op, uint8_t rs, uint8_t thread) { + char opr[2][256]; + char address[2][17]; + char *rind[2] = {"", ""}; + char *sign[2] = {"", ""}; + char *ind[2] = {"", ""}; + char idx[2][33]; + char scale[2][5]; + char *reg[2] = {"", ""}; + memset(opr, 0, sizeof(opr)); + memset(address, 0, sizeof(address)); + memset(idx, 0, sizeof(idx)); + memset(scale, 0, sizeof(scale)); + for (int i = 0; i < 2; i++) { + int is_ind = 0; + int is_rind = 0; + if (op[i].type) { + uint8_t addr_size = get_ortho_addrsize(prefix, op[i].id); + if (addr_size != 0xFF) { + uint64_t value = get_offset(op[i].value, addr_size+1, &sign[i]); + sprintf(address[i], "$%0*"PRIX64, (addr_size+1)*2, value); + } + if (op[i].id == MEM_SIB) { + sprintf(scale[i], "%u*", op[i].scale+1); + } + switch (op[i].id) { + case MEM_ABSR : + case MEM_ZMR : + case MEM_AINDR: + case MEM_AIND : + case MEM_ZINDR: + case MEM_ARIND: + case MEM_ZRIND: + case MEM_SIB : + case MEM_RIND : is_rind = 1; break; + } + if (is_rind) { + for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) { + switch (op[i].rind[j]) { + case REG_A : rind[j] = "A"; break; + case REG_B : rind[j] = "B"; break; + case REG_X : rind[j] = "X"; break; + case REG_Y : rind[j] = "Y"; break; + case REG_E : rind[j] = "E"; break; + case REG_C : rind[j] = "C"; break; + case REG_D : rind[j] = "D"; break; + case REG_S : rind[j] = "S"; break; + case REG_F : rind[j] = "F"; break; + case REG_SP : rind[j] = "SP"; break; + case REG_BP : rind[j] = "BP"; break; + case REG_R11: rind[j] = "R11"; break; + case REG_R12: rind[j] = "R12"; break; + case REG_R13: rind[j] = "R13"; break; + case REG_R14: rind[j] = "R14"; break; + case REG_R15: rind[j] = "R15"; break; + } + } + } + sprintf(idx[i], "%s%s%s%s", scale[i], rind[0], (op[i].rind[1] != 0xFF) ? "+" : "", rind[1]); + switch (op[i].id) { + case MEM_AINDR: + case MEM_AIND : + case MEM_ZINDR: + case MEM_IND : is_ind = 1; break; + case MEM_ARIND: + case MEM_ZRIND: + case MEM_SIB : + case MEM_RIND : is_ind = 2; break; + case MEM_IMM : is_ind = 3; break; + } + if (!is_rind) { + sign[i] = ""; + } + } else { + is_ind = 4; + switch (op[i].id) { + case REG_A : reg[i] = "A"; break; + case REG_B : reg[i] = "B"; break; + case REG_X : reg[i] = "X"; break; + case REG_Y : reg[i] = "Y"; break; + case REG_E : reg[i] = "E"; break; + case REG_C : reg[i] = "C"; break; + case REG_D : reg[i] = "D"; break; + case REG_S : reg[i] = "S"; break; + case REG_F : reg[i] = "F"; break; + case REG_SP : reg[i] = "SP"; break; + case REG_BP : reg[i] = "BP"; break; + case REG_R11: reg[i] = "R11"; break; + case REG_R12: reg[i] = "R12"; break; + case REG_R13: reg[i] = "R13"; break; + case REG_R14: reg[i] = "R14"; break; + case REG_R15: reg[i] = "R15"; break; + } + } + switch (is_ind) { + case 0: sprintf(opr[i], "%s%s%s", idx[i], sign[i], address[i]); break; + case 1: sprintf(opr[i], "%s%s(%s)", idx[i], sign[i], address[i]); break; + case 2: sprintf(opr[i], "(%s%s%s)", idx[i], sign[i], address[i]); break; + case 3: sprintf(opr[i], "#$%*"PRIX64, rs*2, op[i].value); break; + case 4: sprintf(opr[i], "%s", reg[i]); break; + } + } + char *cc = ""; + char *op2 = ""; + int op_count; + char *os = ""; /* Ortho Suffix. */ + if (is_os(opcode, op)) { + os = (postfix && postfix[0] == '.') ? "O" : ".O"; + } + if (is_1cc(opcode) || is_2op(opcode)) { + op_count = 2; + } else if (is_1op(opcode)) { + op_count = 1; + } + if (is_1cc(opcode)) { + switch (opcode) { + case ORTHO_1CC(SET, NG): cc = "NG"; break; + case ORTHO_1CC(SET, PO): cc = "PO"; break; + case ORTHO_1CC(SET, CS): cc = "CS"; break; + case ORTHO_1CC(SET, CC): cc = "CC"; break; + case ORTHO_1CC(SET, EQ): cc = "EQ"; break; + case ORTHO_1CC(SET, NE): cc = "NE"; break; + case ORTHO_1CC(SET, VS): cc = "VS"; break; + case ORTHO_1CC(SET, VC): cc = "VC"; break; + } + op2 = cc; + } else if (is_2op(opcode)) { + op2 = opr[1]; + } + wprintw(scr, "%s%s%s %s%s %s", inst_name, postfix, os, opr[0], (op_count == 2) ? "," : "", op2); + wmove(scr, 29, 0); + wclrtoeol(scr); + for (int i = 0; i < 2; i++) { + if (op[i].type) { + sprintf(address[i], "$%04"PRIX64, value[i]); + } else { + sprintf(address[i], "none"); + } + } + wprintw(scr, "destination address: %s, source address: %s", address[0], address[1]); +} + + +void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t *op_type, uint8_t *op_id, uint8_t thread) { uint64_t value; - uint64_t address = get_addr(cpu, opcode, prefix, ext_prefix, 0, 0, thread); + uint64_t address = 0; + operand ortho_op[2]; + uint64_t ortho_addr[2] = {0, 0}; + if (ext_prefix != 0x1D) { + address = get_addr(cpu, opcode, prefix, ext_prefix, 0, 0, thread); + } else { + get_ortho_addr(cpu, prefix, cpu->pc, ortho_op, ortho_addr, op_type, op_id, 0, 0, thread); + } uint8_t rs = (prefix >> 4) & 3; char *postfix; char *of; @@ -38,15 +310,6 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint mask.u64 = 0; const char *inst_name; uint8_t inst_type; - if ((ext_prefix & 0xD) == 0xD) { - switch (ext_prefix >> 4) { - case 0x0: inst_name = ext_opname[opcode]; inst_type = ext_optype[opcode]; break; - } - } else { - inst_name = opname[opcode]; - inst_type = optype[opcode]; - } - memcpy(op, inst_name, 3); op[3] = 0; switch (rs) { case 0: postfix = ""; break; @@ -62,74 +325,92 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint case 1 : of = "SP"; break; case 2 : of = "PC"; break; } - uint8_t addrsize = 0; - char *idx; - switch (inst_type) { - case AIND : case IND : idx = ")"; break; - case AINDX: case INDX: idx = ", x)"; break; - case AINDY: case INDY: idx = "), y"; break; - case ABSX : case ZMX : idx = ", x"; break; - case ABSY : case ZMY : idx = ", y"; break; - default: idx = ""; break; - } - switch (inst_type) { - case ZM : - case ZMX : - case ZMY : - case IND : - case INDX : - case INDY : addrsize = get_addrsize(prefix, ZM); break; - case ABS : - case AIND : - case AINDX: - case AINDY: - case ABSX : - case ABSY : addrsize = get_addrsize(prefix, ABS); break; - case IMM : - case REL : addrsize = (1 << rs)-1; break; - } - mask.u64 = (-(uint64_t)1 >> ((7 - addrsize) * 8)); - value = read_value(cpu, 0, cpu->pc, addrsize, 0, 0); - if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || inst_type == REL) { - switch (addrsize) { - case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break; - case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break; - case 2 : - case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break; - case 4 : - case 5 : - case 6 : - case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break; + if (ext_prefix != 0x1D) { + if ((ext_prefix & 0xF) == 0xD) { + switch (ext_prefix >> 4) { + case 0x0: inst_name = ext_opname[opcode]; inst_type = ext_optype[opcode]; break; + } + } else { + inst_name = opname[opcode]; + inst_type = optype[opcode]; + } + memcpy(op, inst_name, 3); + + char *idx; + uint8_t addrsize = 0; + switch (inst_type) { + case AIND : case IND : idx = ")"; break; + case AINDX: case INDX: idx = ", x)"; break; + case AINDY: case INDY: idx = "), y"; break; + case ABSX : case ZMX : idx = ", x"; break; + case ABSY : case ZMY : idx = ", y"; break; + default: idx = ""; break; + } + switch (inst_type) { + case ZM : + case ZMX : + case ZMY : + case IND : + case INDX : + case INDY : addrsize = get_addrsize(prefix, ZM); break; + case ABS : + case AIND : + case AINDX: + case AINDY: + case ABSX : + case ABSY : addrsize = get_addrsize(prefix, ABS); break; + case IMM : + case REL : addrsize = (1 << rs)-1; break; + } + mask.u64 = (-(uint64_t)1 >> ((7 - addrsize) * 8)); + value = read_value(cpu, 0, cpu->pc, addrsize, 0, 0); + if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || inst_type == REL) { + switch (addrsize) { + case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break; + case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break; + case 2 : + case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break; + case 4 : + case 5 : + case 6 : + case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break; + } + value = (sign[0] == '-') ? (~value + 1) & mask.u64 : value; } - value = (sign[0] == '-') ? (~value + 1) & mask.u64 : value; - } - switch (inst_type) { - case EIND : - case BREG : - case IMPL : wprintw(scr, "%s%s" , inst_name, postfix); break; - case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break; - case AIND : - case AINDX: - case AINDY: - case IND : - case INDX : - case INDY : ind = "("; /* Falls through. */ - case ZMX : - case ZMY : - case ABSX : - case ABSY : - case ZM : - case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value, idx); break; - case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value); break; + switch (inst_type) { + case BREG : + case IMPL : wprintw(scr, "%s%s" , inst_name, postfix); break; + case EIND : wprintw(scr, "%s%s (E)" , op, postfix); break; + case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break; + case AIND : + case AINDX: + case AINDY: + case IND : + case INDX : + case INDY : ind = "("; /* Falls through. */ + case ZMX : + case ZMY : + case ABSX : + case ABSY : + case ZM : + case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value, idx); break; + case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value); break; + } + } else { + inst_name = ortho_opname[opcode]; + memcpy(op, inst_name, 3); + disasm_ortho(cpu, opcode, prefix, prefix2, ortho_addr, op, postfix, ortho_op, rs, thread); } if (address == TX_ADDR || address == RX_ADDR) { wmove(scr, 27, 0); wprintw(scr, "TX_ADDR: $%02X, RX_ADDR: $%02X", addr[TX_ADDR], addr[RX_ADDR]); } - wmove(scr, 29, 0); - wclrtoeol(scr); - wprintw(scr, "address: $%04"PRIX64, address); + if (ext_prefix != 0x1D) { + wmove(scr, 29, 0); + wclrtoeol(scr); + wprintw(scr, "address: $%04"PRIX64, address); + } if (subdbg) { uint8_t ln = 33; uint16_t line_idx = 0; @@ -253,3 +534,7 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint } } + +#undef ORTHO_1CC +#undef ORTHO_1OP +#undef ORTHO_2OP diff --git a/disasm.h b/disasm.h index 6f978ce..3427592 100644 --- a/disasm.h +++ b/disasm.h @@ -335,3 +335,74 @@ static const char *ext_opname[0x100] = { [SWP_E ] = "SWP (E)", [PCN_E ] = "PCN (E)" }; + +#define ORTHO_1CC(mne, cc) \ + [mne##_R##cc] = #mne " r, " #cc, [mne##_M##cc] = #mne " m, " #cc + +#define ORTHO_1OP(mne) \ + [mne##_R] = #mne " r", [mne##_M] = #mne " m" + +#define ORTHO_2OP(mne) \ + [mne##_RR] = #mne " r, r", [mne##_RM] = #mne " r, m", [mne##_MR] = #mne " m, r", [mne##_MM] = #mne " m, m" + + +static const char *ortho_opname[] = { + /* 0x00-0x1C */ + ORTHO_2OP(MNG/**/), /* Move if NeGative. */ + ORTHO_2OP(ADC/**/), /* ADC Ortho. */ + ORTHO_2OP(ROR/**/), /* ROR Ortho. */ + ORTHO_2OP(ADD/**/), /* ADD Ortho. */ + ORTHO_1OP(PSH/**/), /* PuSH operand onto the stack. */ + ORTHO_1CC(SET, NG), /* SET if NeGative. */ + ORTHO_1OP(PEA/**/), /* PEA Ortho. */ + /* 0x20-0x3C */ + ORTHO_2OP(MPO/**/), /* Move if POsitive. */ + ORTHO_2OP(SBC/**/), /* SBC Ortho. */ + ORTHO_2OP(MUL/**/), /* MUL Ortho. */ + ORTHO_2OP(SUB/**/), /* SUB Ortho. */ + ORTHO_1OP(PUL/**/), /* PuLl operand off of the stack. */ + ORTHO_1CC(SET, PO), /* SET if POsitive. */ + ORTHO_1OP(SWP/**/), /* SWP Ortho. */ + /* 0x40-0x55 */ + ORTHO_2OP(MCS/**/), /* Move if Carry Set. */ + ORTHO_2OP(AND/**/), /* AND Ortho. */ + ORTHO_2OP(DIV/**/), /* DIV Ortho. */ + ORTHO_2OP(PCN/**/), /* PCN Ortho. */ + ORTHO_1OP(NOT/**/), /* NOT Ortho. */ + ORTHO_1CC(SET, CS), /* SET if Carry Set. */ + /* 0x60-0x75 */ + ORTHO_2OP(MCC/**/), /* Move if Carry Clear. */ + ORTHO_2OP(OR /**/), /* Bitwise OR. */ + ORTHO_2OP(ASR/**/), /* ASR Ortho. */ + ORTHO_2OP(LEA/**/), /* LEA Ortho. */ + ORTHO_1OP(NEG/**/), /* NEGate operand. */ + ORTHO_1CC(SET, CC), /* SET if Carry Clear. */ + /* 0x80-0x95 */ + ORTHO_2OP(MEQ/**/), /* Move if EQual. */ + ORTHO_2OP(XOR/**/), /* XOR Ortho. */ + ORTHO_2OP(CMP/**/), /* CMP Ortho. */ + ORTHO_1OP(DEC/**/), /* DEC Ortho. */ + ORTHO_1CC(SET, EQ), /* SET if EQual. */ + /* 0xA0-0xB5 */ + ORTHO_2OP(MNE/**/), /* Move if Not Equal. */ + ORTHO_2OP(LSL/**/), /* LSL Ortho. */ + ORTHO_2OP(MOV/**/), /* MOVe data from source, to destination. */ + ORTHO_1OP(INC/**/), /* INC Ortho. */ + ORTHO_1CC(SET, NE), /* SET if Not Equal. */ + /* 0xC0-0xD5 */ + ORTHO_2OP(MVS/**/), /* Move if oVerflow Set. */ + ORTHO_2OP(LSR/**/), /* LSR Ortho. */ + ORTHO_2OP(IML/**/), /* Integer MuLtiply. */ + ORTHO_1OP(CLZ/**/), /* CLZ Ortho. */ + ORTHO_1CC(SET, VS), /* SET if oVerflow Set. */ + /* 0xE0-0xF5 */ + ORTHO_2OP(MVC/**/), /* Move if oVerflow Clear. */ + ORTHO_2OP(ROL/**/), /* ROL Ortho. */ + ORTHO_2OP(IDV/**/), /* Integer DiVide. */ + ORTHO_1OP(CLO/**/), /* CLO Ortho. */ + ORTHO_1CC(SET, VC) /* SET if oVerflow Clear. */ +}; + +#undef ORTHO_1CC +#undef ORTHO_1OP +#undef ORTHO_2OP diff --git a/enums.h b/enums.h index bca5010..834566d 100644 --- a/enums.h +++ b/enums.h @@ -1,23 +1,59 @@ enum am { /* Part of Base ISA. */ - IMM, /* Immediate Data. */ - ZM, /* Zero Matrix. */ - ZMX, /* Zero Matrix, indexed with X. */ - ZMY, /* Zero Matrix, indexed with Y. */ - IND, /* Indirect. */ - INDX, /* Indexed Indirect. */ - INDY, /* Indirect Indexed. */ - ABS, /* Absolute. */ - REL, /* Relative to Program Counter. */ - BREG, /* B Register. */ - IMPL, /* Implied. */ + IMM, /* Immediate Data. */ + ZM, /* Zero Matrix. */ + ZMX, /* Zero Matrix, indexed with X. */ + ZMY, /* Zero Matrix, indexed with Y. */ + IND, /* Indirect. */ + INDX, /* Indexed Indirect. */ + INDY, /* Indirect Indexed. */ + ABS, /* Absolute. */ + REL, /* Relative to Program Counter. */ + BREG, /* B Register. */ + IMPL, /* Implied. */ /* Part of Base Extension. */ - ABSX, /* Absolute, Indexed with X. */ - ABSY, /* Absolute, Indexed with Y. */ - AIND, /* Absolute Indirect. */ - AINDX, /* Absolute Indexed Indirect. */ - AINDY, /* Absolute Indirect Indexed. */ - EIND, /* Effective Address Register, Indirect. */ + ABSX, /* Absolute, Indexed with X. */ + ABSY, /* Absolute, Indexed with Y. */ + AIND, /* Absolute Indirect. */ + AINDX, /* Absolute Indexed Indirect. */ + AINDY, /* Absolute Indirect Indexed. */ + EIND, /* Effective Address Register, Indirect. */ +}; + +/* Part of the Orthogonal Extension. */ +enum ortho_reg { + REG_A, + REG_B, + REG_X, + REG_Y, + REG_E, + REG_C, + REG_D, + REG_S, + REG_F, + REG_SP, + REG_BP, + REG_R11, + REG_R12, + REG_R13, + REG_R14, + REG_R15, +}; + +enum ortho_mem { + MEM_ABS, /* Absolute. */ + MEM_ZM, /* Zero Matrix. */ + MEM_ABSR, /* Absolute, Indexed with register. */ + MEM_ZMR, /* Zero Matrix, Indexed with register. */ + MEM_AIND, /* Absolute Indirect. */ + MEM_IND, /* Zero Matrix Indirect. */ + MEM_AINDR, /* Absolute, Indirect Indexed Register. */ + MEM_ZINDR, /* Zero Matrix, Indirect Indexed Register. */ + MEM_ARIND, /* Absolute, Indexed Indirect Register. */ + MEM_ZRIND, /* Zero Matrix, Indexed Indirect Register. */ + MEM_RIND, /* Register Indirect. */ + MEM_IMM, /* Immediate Data. */ + MEM_SIB = 0xE, /* Scale Index Base. */ }; enum mne { @@ -149,6 +185,25 @@ enum ext_mne { SNE }; +enum ortho_mne { + MNG, + MPO, + MCS, + MCC, + MEQ, + MNE, + MVS, + MVC, + OR , + MOV, + IML, + IDV, + PSH, + PUL, + NEG, + SET +}; + enum base_isa { CPS_IMP = 0x00, /* Clear Processor Status. */ ADC_IMM = 0x01, /* ADd with Carry. */ @@ -486,3 +541,73 @@ enum base_ext { SWP_E = 0xFA, /* SWP E Indirect. */ PCN_E = 0xFC /* PCN E Indirect. */ }; + +#define ORTHO_1CC(mne, base, cc) \ + mne##_R##cc = base, mne##_M##cc = base|0x10 + +#define ORTHO_1OP(mne, base) \ + mne##_R = base, mne##_M = base|0x10 + +#define ORTHO_2OP(mne, base) \ + mne##_RR = base, mne##_RM = base|0x08, mne##_MR = base|0x10, mne##_MM = base|0x18 + +enum ortho { + /* 0x00-0x1C */ + ORTHO_2OP(MNG, 0x00/**/), /* Move if NeGative. */ + ORTHO_2OP(ADC, 0x01/**/), /* ADC Ortho. */ + ORTHO_2OP(ROR, 0x02/**/), /* ROR Ortho. */ + ORTHO_2OP(ADD, 0x03/**/), /* ADD Ortho. */ + ORTHO_1OP(PSH, 0x04/**/), /* PuSH operand onto the stack. */ + ORTHO_1CC(SET, 0x05, NG), /* SET if NeGative. */ + ORTHO_1OP(PEA, 0x0C/**/), /* PEA Ortho. */ + /* 0x20-0x3C */ + ORTHO_2OP(MPO, 0x20/**/), /* Move if POsitive. */ + ORTHO_2OP(SBC, 0x21/**/), /* SBC Ortho. */ + ORTHO_2OP(MUL, 0x22/**/), /* MUL Ortho. */ + ORTHO_2OP(SUB, 0x23/**/), /* SUB Ortho. */ + ORTHO_1OP(PUL, 0x24/**/), /* PuLl operand off of the stack. */ + ORTHO_1CC(SET, 0x25, PO), /* SET if POsitive. */ + ORTHO_1OP(SWP, 0x2C/**/), /* SWP Ortho. */ + /* 0x40-0x55 */ + ORTHO_2OP(MCS, 0x40/**/), /* Move if Carry Set. */ + ORTHO_2OP(AND, 0x41/**/), /* AND Ortho. */ + ORTHO_2OP(DIV, 0x42/**/), /* DIV Ortho. */ + ORTHO_2OP(PCN, 0x43/**/), /* PCN Ortho. */ + ORTHO_1OP(NOT, 0x44/**/), /* NOT Ortho. */ + ORTHO_1CC(SET, 0x45, CS), /* SET if Carry Set. */ + /* 0x60-0x75 */ + ORTHO_2OP(MCC, 0x60/**/), /* Move if Carry Clear. */ + ORTHO_2OP(OR , 0x61/**/), /* Bitwise OR. */ + ORTHO_2OP(ASR, 0x62/**/), /* ASR Ortho. */ + ORTHO_2OP(LEA, 0x63/**/), /* LEA Ortho. */ + ORTHO_1OP(NEG, 0x64/**/), /* NEGate operand. */ + ORTHO_1CC(SET, 0x65, CC), /* SET if Carry Clear. */ + /* 0x80-0x95 */ + ORTHO_2OP(MEQ, 0x80/**/), /* Move if EQual. */ + ORTHO_2OP(XOR, 0x81/**/), /* XOR Ortho. */ + ORTHO_2OP(CMP, 0x82/**/), /* CMP Ortho. */ + ORTHO_1OP(DEC, 0x84/**/), /* DEC Ortho. */ + ORTHO_1CC(SET, 0x85, EQ), /* SET if EQual. */ + /* 0xA0-0xB5 */ + ORTHO_2OP(MNE, 0xA0/**/), /* Move if Not Equal. */ + ORTHO_2OP(LSL, 0xA1/**/), /* LSL Ortho. */ + ORTHO_2OP(MOV, 0xA2/**/), /* MOVe data from source, to destination. */ + ORTHO_1OP(INC, 0xA4/**/), /* INC Ortho. */ + ORTHO_1CC(SET, 0xA5, NE), /* SET if Not Equal. */ + /* 0xC0-0xD5 */ + ORTHO_2OP(MVS, 0xC0/**/), /* Move if oVerflow Set. */ + ORTHO_2OP(LSR, 0xC1/**/), /* LSR Ortho. */ + ORTHO_2OP(IML, 0xC2/**/), /* Integer MuLtiply. */ + ORTHO_1OP(CLZ, 0xC4/**/), /* CLZ Ortho. */ + ORTHO_1CC(SET, 0xC5, VS), /* SET if oVerflow Set. */ + /* 0xE0-0xF5 */ + ORTHO_2OP(MVC, 0xE0/**/), /* Move if oVerflow Clear. */ + ORTHO_2OP(ROL, 0xE1/**/), /* ROL Ortho. */ + ORTHO_2OP(IDV, 0xE2/**/), /* Integer DiVide. */ + ORTHO_1OP(CLO, 0xE4/**/), /* CLO Ortho. */ + ORTHO_1CC(SET, 0xE5, VC) /* SET if oVerflow Clear. */ +}; + +#undef ORTHO_1CC +#undef ORTHO_1OP +#undef ORTHO_2OP diff --git a/lexer.c b/lexer.c index f8280a0..873fe6d 100644 --- a/lexer.c +++ b/lexer.c @@ -131,8 +131,8 @@ symbol *find_member(char *name, symbol* root, uint8_t dbg) { return m; } } - for (; s->next && !s->down; s = s->next); - } while (s->down); + for (;s && s->next && !s->down; s = s->next); + } while (s && s->down); return NULL; } @@ -228,8 +228,95 @@ line *find_line(uint32_t ln, uint8_t dbg) { return l; } -uint8_t is_struct = 0; -uint8_t is_anon = 0; +int is_struct = 0; +int is_anon = 0; + +void create_struct(symbol *c_sym, line *l, token *t, token *lt, char *name, uint8_t dbg) { + uint8_t ismember = !(is_struct == 1 && lt && lt->id == TOK_DIR); + mksymbol(name, 0, 1, ismember, 0, 0, dbg); + if (isfixup) { + isfixup = reslv_fixups(dbg); + } + t->sym = get_sym(name, 0, t, ismember, dbg); + if (lt && lt->id == TOK_DIR) { + t->sym->isstruct = 1; + t->id = (lt->type == DIR_STRUCT) ? TOK_STRUCT : TOK_UNION; + tmp_line = l; + } else { + t->id = TOK_MEMBER; + t->sym->isanon = (is_anon > 0); + } + isfixup += (t->sym == NULL); + int is_top = (c_sym == NULL); + c_sym = (!ismember && !c_sym) ? last_sym : c_sym; + if (!ismember) { + if (!is_top) { + c_sym = t->sym; + locals = NULL; + last_loc = NULL; + } else { + c_sym->down = locals; + } + } else { + if (lt && lt->id == TOK_DIR) { + if (lt->type == DIR_UNION || lt->type == DIR_STRUCT) { + c_sym->down = locals; + c_sym->down->up = c_sym; + last_loc->up = c_sym; + c_sym = last_loc; + locals = NULL; + last_loc = NULL; + } + } + } + cur_sym = c_sym; +} + +void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) { + int skip = 0; + if (/*s_sym &&*/ is_anon > 0) { + if ((c_sym && c_sym->isanon) || (c_sym->up && !c_sym->up->isanon) || (c_sym && s_sym->isanon)) { + is_anon--; + } else if (is_struct <= 0) { + is_anon = 0; + } + skip = (!is_anon); + } + if (((is_struct-is_anon) > 0 && !skip) || (is_anon <= 0 && is_struct <= 0)) { + symbol *s; + for (s = locals; s; s = s->next) { + if (s->up == NULL) { + s->up = c_sym; + } + if (dbg) { + printf("s: %p, s->up: %p, c_sym: %p, last_loc: %p\n", s, s->up, c_sym, last_loc); + } + } + if (c_sym->down == NULL) { + c_sym->down = locals; + } + } + if ((is_anon <= 0 || is_struct <= 0)) { + for (s_sym = c_sym; /*s_sym &&*/ s_sym->prev && !s_sym->isanon; s_sym = s_sym->prev); + struct_sym = s_sym; + } + if ((is_struct-is_anon) > 0 && !skip) { + symbol *s = c_sym; + for (; s->prev; s = s->prev) { + if (s->up == NULL && c_sym->up) { + s->up = c_sym->up; + } + if (dbg) { + printf("s: %p, s->up: %p, c_sym->up: %p, last_loc: %p\n", s, s->up, c_sym->up, last_loc); + } + } + if (c_sym->up) { + cur_sym = c_sym->up; + } + for (locals = locals->up; locals->prev; locals = locals->prev); + for (last_loc = locals; last_loc->next; last_loc = last_loc->next); + } +} uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { char sym[0x100]; @@ -240,6 +327,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { uint16_t symid = 0; uint64_t value = 0; lex_type = 0xFF; + uint8_t lex_subtype = 0xFF; uint8_t k = 0; uint8_t k2 = 0; @@ -321,7 +409,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { uint8_t ptok = get_ptok(str[i], dbg); if (is_altok(ptok, dbg)) { offset++; - if ((ptok == PTOK_S && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C')) { + if (((ptok == PTOK_S || ptok == PTOK_B) && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C')) { offset++; } switch (get_ptok(str[i+offset], dbg)) { @@ -331,13 +419,36 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { case PTOK_Y : case PTOK_S : case PTOK_P : - case PTOK_ALPHA : - case PTOK_NUMBER: ptok = PTOK_ALPHA; break; + case PTOK_A : + case PTOK_C : + case PTOK_D : + case PTOK_F : + case PTOK_R : + case PTOK_ALPHA : ptok = PTOK_ALPHA; break; + case PTOK_NUMBER: + if (ptok == PTOK_R) { + char reg_num[3]; + int isnum; + for (isnum = 0; isdigit(str[i+offset]) && !(isdelm(str[i+offset], dbg) & 0x03) && isnum < 2; offset++, isnum++) { + reg_num[isnum] = str[i+offset]; + } + reg_num[isnum] = '\0'; + if (isnum == 2) { + int regnum = strtoul(reg_num, NULL, 10); + ptok = (regnum < 11 || regnum > 15) ? PTOK_ALPHA : ptok; + } else { + ptok = PTOK_ALPHA; + } + } else { + ptok = PTOK_ALPHA; + } + break; } - if ((ptok == PTOK_S && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) { + if ((ptok == PTOK_S && str[i+1] && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) { ptok = PTOK_ALPHA; } } + /*i = ptok_handler[ptok](str, i, lex_type, l, t, dbg);*/ switch (ptok) { case PTOK_DOT: i++; @@ -353,83 +464,53 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { for (j = 0; isdelm(str[i+j], dbg) & 16; j++); uint8_t ret = get_ptok(str[i+j], dbg); j = tmp; + if ((k == DIR_STRUCT || k == DIR_UNION) && (ret != PTOK_ALPHA || (is_anon && ret == PTOK_ALPHA))) { is_anon++; } is_struct += (k == DIR_STRUCT || k == DIR_UNION); is_struct -= (k == DIR_ENDSTRUCT || k == DIR_ENDUNION); if ((k == DIR_ENDSTRUCT || k == DIR_ENDUNION)) { - int skip = 0; - if ((int)is_anon > 0) { - if ((cur_sym && cur_sym->isanon) || (cur_sym->up && !cur_sym->up->isanon) || (struct_sym && struct_sym->isanon)) { - is_anon--; - } else if ((int)is_struct <= 0) { - is_anon = 0; - } - skip = (!is_anon); - } - if (((int)(is_struct-is_anon) > 0 && !skip) || ((int)is_anon <= 0 && (int)is_struct <= 0)) { - symbol *s; - for (s = locals; s; s = s->next) { - if (s->up == NULL) { - s->up = cur_sym; - } - if (dbg) { - printf("s: %p, s->up: %p, cur_sym: %p, last_loc: %p\n", s, s->up, cur_sym, last_loc); - } - } - if (cur_sym->down == NULL) { - cur_sym->down = locals; - } - } - if (((int)is_anon <= 0 || (int)is_struct <= 0)) { - for (struct_sym = cur_sym; struct_sym->prev && !struct_sym->isanon; struct_sym = struct_sym->prev); - } - if ((int)(is_struct-is_anon) > 0 && !skip) { - symbol *s = cur_sym; - for (; s->prev; s = s->prev) { - if (s->up == NULL && cur_sym->up) { - s->up = cur_sym->up; - } - if (dbg) { - printf("s: %p, s->up: %p, cur_sym->up: %p, last_loc: %p\n", s, s->up, cur_sym->up, last_loc); - } - } - if (cur_sym->up) { - cur_sym = cur_sym->up; - } - for (locals = locals->up; locals->prev; locals = locals->prev); - for (last_loc = locals; last_loc->next; last_loc = last_loc->next); - } + end_struct(cur_sym, struct_sym, dbg); } break; } } - l->count++; if (lex_type != TOK_DIR && lt && lt->id == TOK_SYM) { lex_type = TOK_MEMBER; i -= j; } else { + l->count++; t = make_token(lex_type, k, space, tab, 0, "", NULL); } } else { - lex_type = TOK_RS; - switch (tolower(lexeme[j-1])) { - case '2': - case 'w': - rs = 1; - break; - case '4': - case 'd': - rs = 2; - break; - case '8': - case 'q': - rs = 3; - break; + for (k = 0; !(isdelm(lexeme[k], dbg) & 17); k++) { + lex_type = TOK_RS; + switch (tolower(lexeme[k])) { + case '2': + case 'w': + rs = 1; + break; + case '4': + case 'd': + rs = 2; + break; + case '8': + case 'q': + rs = 3; + break; + case 'o': + /* Set Our token type to ortho suffix. */ + lex_type = TOK_OS; + break; + } + l->count++; + t = make_token(lex_type, rs, space, tab, 0, "", NULL); + if (t) { + lt = t; + t = t->next; + } } - l->count++; - t = make_token(lex_type, rs, space, tab, 0, "", NULL); isop = 0; } break; @@ -525,12 +606,20 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { break; case PTOK_LBRACK: case PTOK_HASH : - l->tok->type = (ptok == PTOK_LBRACK) ? IND : IMM; + /*l->tok->type = (ptok == PTOK_LBRACK) ? IND : IMM; + lex_type = (ptok == PTOK_LBRACK) ? TOK_IND : TOK_IMM;*/ + lex_type = TOK_MEM; + value = (ptok == PTOK_LBRACK) ? MEM_IND : MEM_IMM; + l->count++; + t = make_token(lex_type, value, space, tab, 0, "", NULL); lex_type = (ptok == PTOK_LBRACK) ? TOK_IND : TOK_IMM; + if (lex_subtype != 0xFF) { + lex_subtype = 0xFF; + } memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; - (t) ? (t->subspace = space) : (lt->subspace = space); - (t) ? (t->subtab = tab) : (lt->subtab = tab); + /*(t) ? (t->subspace = space) : (lt->subspace = space); + (t) ? (t->subtab = tab) : (lt->subtab = tab);*/ break; case PTOK_PLUS: case PTOK_MINUS: @@ -567,54 +656,83 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { lexeme[j] = ')'; lexeme[j+1] = '\0'; lexeme[j+2] = '\0'; + if (t && t->subtype == 0xFF) { + t->subtype = TOK_IND; + } else if (lt && lt->subtype == 0xFF) { + lt->subtype = TOK_IND; + } + (t) ? (t->subspace = space) : (lt->subspace = space); + (t) ? (t->subtab = tab) : (lt->subtab = tab); break; case PTOK_COMMA: i++; - if (lex_type != TOK_IND && lex_type != TOK_OF) { + if ((lex_type != TOK_IND && lex_type != TOK_OF)) { lex_type = TOK_CSV; } + lex_subtype = TOK_CSV; + if (t && t->subtype == 0xFF) { + t->subtype = TOK_CSV; + } else if (lt && lt->subtype == 0xFF) { + lt->subtype = TOK_CSV; + } + (t) ? (t->subspace = space) : (lt->subspace = space); + (t) ? (t->subtab = tab) : (lt->subtab = tab); lexeme[j] = ','; lexeme[j+1] = '\0'; lexeme[j+2] = '\0'; break; case PTOK_B: - lexeme[j] = str[i++]; - lexeme[j+1] = '\0'; - lexeme[j+2] = '\0'; - lex_type = TOK_BREG; - l->tok->type = BREG; - (t) ? (t->subspace = space) : (lt->subspace = space); - (t) ? (t->subtab = tab) : (lt->subtab = tab); - break; case PTOK_E: case PTOK_X: case PTOK_Y: - lexeme[j] = str[i++]; - lexeme[j+1] = '\0'; - lexeme[j+2] = '\0'; - if (lex_type != TOK_IND && lex_type != TOK_CSV) { - break; - } + case PTOK_S: + case PTOK_A: + case PTOK_C: + case PTOK_D: + case PTOK_F: + case PTOK_R: + lexeme[j+0] = str[i++]; + lexeme[j+1] = (ptok == PTOK_R || ((ptok == PTOK_S || ptok == PTOK_B) && get_ptok(str[i], dbg) == PTOK_P)) ? str[i++] : '\0'; + lexeme[j+2] = (ptok == PTOK_R) ? str[i++] : '\0'; + lexeme[j+3] = '\0'; + /*lex_subtype = (lex_type == TOK_CSV && lt && lt->subtype != TOK_CSV) ? lex_type : lex_subtype;*/ + lex_type = TOK_REG; switch (ptok) { - case PTOK_E: l->tok->type = (lex_type == TOK_IND) ? EIND : l->tok->type; break; - case PTOK_X: l->tok->type = (lex_type == TOK_IND) ? INDX : ZMX; break; - case PTOK_Y: l->tok->type = (lex_type == TOK_IND) ? INDY : ZMY; break; + case PTOK_A: value = REG_A; break; + case PTOK_X: value = REG_X; break; + case PTOK_Y: value = REG_Y; break; + case PTOK_E: value = REG_E; break; + case PTOK_C: value = REG_C; break; + case PTOK_D: value = REG_D; break; + case PTOK_S: + case PTOK_B: + if (get_ptok(lexeme[j+1], dbg) == PTOK_P) { + value = (ptok == PTOK_S) ? REG_SP : REG_BP; + } else { + value = (ptok == PTOK_S) ? REG_S : REG_B; + } + break; + case PTOK_F: value = REG_F; break; + case PTOK_R: value = strtoull(lexeme+j+1, NULL, 10); break; } + l->count++; + t = make_token(lex_type, value, space, tab, 0, "", NULL); + t->subtype = (t->subtype == 0xFF && lex_subtype != 0xFF) ? lex_subtype : t->subtype; + lex_subtype = 0xFF; + /*(t) ? (t->subspace = space) : (lt->subspace = space); + (t) ? (t->subtab = tab) : (lt->subtab = tab);*/ break; - case PTOK_S: case PTOK_P: lexeme[j] = str[i++]; - if (str[i] != ',') { - lexeme[j+1] = str[i++]; - } else { - lexeme[j+1] = '\0'; - } + lexeme[j+1] = (str[i] != ',') ? str[i++] : '\0'; lexeme[j+2] = '\0'; - switch (ptok) { + /*switch (ptok) { case PTOK_S: of = 1; break; case PTOK_P: of = 2; break; - } + }*/ + of = 2; lex_type = TOK_OF; + l->count++; t = make_token(lex_type, of, space, tab, 0, "", NULL); break; case PTOK_AT: @@ -700,18 +818,26 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { i += j; isch = 0; isop = 0; - if (j == 3 && str[i] != ':' && !is_struct) { - for (k = 0, k2 = 0; k < OPNUM || k2 < EXT_OPNUM; k++, k2++) { - int find_ext = (k2 < EXT_OPNUM); + if (j > 1 && j <= 3 && str[i] != ':' && !is_struct) { + for (k = 0; k < OPNUM; k++) { + int find_ext = (k < EXT_OPNUM); + int find_ortho = (k < ORTHO_OPNUM); int upper = toupper(lexeme[0]); - if (upper == mne[k][0] || (find_ext && upper == ext_mne[k2][0])) { + int isbase = (upper == mne[k][0]); + int isext = (find_ext && upper == ext_mne[k][0]); + int isortho = (find_ortho && upper == ortho_mne[k][0]); + + if (isbase || isext || isortho) { int is_base = !strcasecmp(lexeme, mne[k]); - int is_ext = (find_ext && !strcasecmp(lexeme, ext_mne[k2])); - if (is_base || is_ext) { - lex_type = (is_base && !is_ext) ? TOK_OPCODE : TOK_EXTOP; + int is_ext = (find_ext && !strcasecmp(lexeme, ext_mne[k])); + int is_ortho = (find_ortho && !strcasecmp(lexeme, ortho_mne[k])); + if (is_base || is_ext || is_ortho) { + lex_type = (is_base) ? TOK_OPCODE : lex_type; + lex_type = (is_ext) ? TOK_EXTOP : lex_type; + lex_type = (is_ortho) ? TOK_ORTHO : lex_type; isop = 1; l->count++; - t = make_token(lex_type, 0xFF, space, tab, (is_base && !is_ext) ? k : k2, "", NULL); + t = make_token(lex_type, 0xFF, space, tab, k, "", NULL); break; } } @@ -719,6 +845,18 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { } if (!isop) { uint8_t spaces = 0; + if (l->tok && l->tok->type == TOK_ORTHO && l->tok->byte == SET) { + for (k = 0; k < 8; k++) { + int upper = toupper(lexeme[0]); + if (upper == set_cc[k][0]) { + if (!strcasecmp(lexeme, set_cc[k])) { + lex_type = TOK_CC; + l->count++; + t = make_token(lex_type, 0xFF, space, tab, k, "", NULL); + } + } + } + } for (; isdelm(str[i+spaces], dbg) == 16; spaces++); uint8_t ret = get_ptok(str[i+spaces], dbg); if (ret == PTOK_COLON || ret == PTOK_EQU) { @@ -732,43 +870,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { printf("lex(): spaces: %u\n", spaces); } if (is_struct) { - islocal = !(is_struct == 1 && lt && lt->id == TOK_DIR); - mksymbol(sym, 0, 1, islocal, 0, 0, dbg); - if (isfixup) { - isfixup = reslv_fixups(dbg); - } - t->sym = get_sym(sym, 0, t, islocal, dbg); - if (lt && lt->id == TOK_DIR) { - t->sym->isstruct = 1; - t->id = (lt->type == DIR_STRUCT) ? TOK_STRUCT : TOK_UNION; - tmp_line = l; - } else { - t->id = TOK_MEMBER; - t->sym->isanon = (is_anon > 0); - } - isfixup += (t->sym == NULL); - int is_top = (cur_sym == NULL); - cur_sym = (!islocal && !cur_sym) ? last_sym : cur_sym; - if (!islocal) { - if (!is_top) { - cur_sym = t->sym; - locals = NULL; - last_loc = NULL; - } else { - cur_sym->down = locals; - } - } else { - if (lt && lt->id == TOK_DIR) { - if (lt->type == DIR_UNION || lt->type == DIR_STRUCT) { - cur_sym->down = locals; - cur_sym->down->up = cur_sym; - last_loc->up = cur_sym; - cur_sym = last_loc; - locals = NULL; - last_loc = NULL; - } - } - } + create_struct(cur_sym, l, t, lt, sym, dbg); islocal = 0; } else if ((str[i+spaces] != ':' && str[i+spaces] != '=')) { uint8_t sym_struct = 0; @@ -831,9 +933,9 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { case TOK_DEC : case TOK_CHAR: case TOK_EXPR: - s->val = get_val(tok, address, 3, dbg); + s->val = get_val(tok, address, 3, 0xFF, 0, dbg); if (tok->next) { - tok = skip_expr(tok, dbg); + tok = skip_expr(tok, 0xFF, 0, dbg); } break; } diff --git a/lexer.h b/lexer.h index dc478cd..8775187 100644 --- a/lexer.h +++ b/lexer.h @@ -1,4 +1,4 @@ -static inline uint8_t isdelm(char c, uint8_t dbg) { +static uint8_t isdelm(char c, uint8_t dbg) { switch (c) { default : return 0x00; case '\0': @@ -11,7 +11,7 @@ static inline uint8_t isdelm(char c, uint8_t dbg) { } } -static inline uint8_t isdelm2(char c, uint8_t dbg) { +static uint8_t isdelm2(char c, uint8_t dbg) { switch (c) { default : return 0; case ')' : @@ -32,7 +32,7 @@ static inline uint8_t isdelm2(char c, uint8_t dbg) { } } -static inline uint8_t get_ptok(char c, uint8_t dbg) { +static uint8_t get_ptok(char c, uint8_t dbg) { switch (c) { case '.' : return PTOK_DOT ; case '@' : return PTOK_AT ; @@ -52,6 +52,11 @@ static inline uint8_t get_ptok(char c, uint8_t dbg) { case 'Y': case 'y' : return PTOK_Y ; case 'S': case 's' : return PTOK_S ; case 'P': case 'p' : return PTOK_P ; + case 'A': case 'a' : return PTOK_A ; + case 'C': case 'c' : return PTOK_C ; + case 'D': case 'd' : return PTOK_D ; + case 'F': case 'f' : return PTOK_F ; + case 'R': case 'r' : return PTOK_R ; case '\"': return PTOK_DQUOTE ; case '\'': return PTOK_SQUOTE ; case '#' : return PTOK_HASH ; @@ -69,14 +74,160 @@ static inline uint8_t get_ptok(char c, uint8_t dbg) { } } -static inline uint8_t is_altok(uint8_t ptok, uint8_t dbg) { +static uint8_t is_altok(uint8_t ptok, uint8_t dbg) { switch (ptok) { case PTOK_B: case PTOK_E: case PTOK_X: case PTOK_Y: case PTOK_S: - case PTOK_P: return 1; + case PTOK_P: + case PTOK_A: + case PTOK_C: + case PTOK_D: + case PTOK_F: + case PTOK_R: return 1; default : return 0; } } + +#if 0 +static int handle_dot(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_at(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_colon(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_equ(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_plus(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_minus(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_gt(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_lt(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_pipe(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_lbrack(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_rbrack(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_comma(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_b(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_e(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_x(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_y(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_s(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_p(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_dquote(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_squote(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_hash(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_scolon(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_dollar(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_percent(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} +static int handle_number(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_alpha(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + +} + +static int handle_other(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg) { + return idx+1; +} + +typedef int (*ptok_func)(char *str, int idx, uint8_t lex_type, line *l, token *t, uint8_t dbg); + +static ptok_func ptok_handler[PTOK_OTHER+1] = { + [PTOK_DOT ] = handle_dot, + [PTOK_AT ] = handle_at, + [PTOK_COLON ] = handle_colon, + [PTOK_EQU ] = handle_equ, + [PTOK_PLUS ] = handle_plus, + [PTOK_MINUS ] = handle_minus, + [PTOK_GT ] = handle_gt, + [PTOK_LT ] = handle_lt, + [PTOK_PIPE ] = handle_pipe, + [PTOK_LBRACK ] = handle_lbrack, + [PTOK_RBRACK ] = handle_rbrack, + [PTOK_COMMA ] = handle_comma, + [PTOK_B ] = handle_b, + [PTOK_E ] = handle_e, + [PTOK_X ] = handle_x, + [PTOK_Y ] = handle_y, + [PTOK_S ] = handle_s, + [PTOK_P ] = handle_p, + [PTOK_DQUOTE ] = handle_dquote, + [PTOK_SQUOTE ] = handle_squote, + [PTOK_HASH ] = handle_hash, + [PTOK_SCOLON ] = handle_scolon, + [PTOK_DOLLAR ] = handle_dollar, + [PTOK_PERCENT] = handle_percent, + [PTOK_NUMBER ] = handle_number, + [PTOK_ALPHA ] = handle_alpha, + [PTOK_OTHER ] = handle_other +}; +#endif diff --git a/opcode.h b/opcode.h index 40b832f..1e5d820 100644 --- a/opcode.h +++ b/opcode.h @@ -11,6 +11,7 @@ #define OPNUM 74 #define EXT_OPNUM 49 +#define ORTHO_OPNUM 16 #define C (1 << 0) /* Carry flag. */ #define Z (1 << 1) /* Zero flag. */ @@ -57,11 +58,25 @@ struct sux { union reg ps; /* The processor status register. */ uint64_t a, b, y, x; /* Registers A, B, X, and Y. */ uint64_t e; /* Effective address register. */ + uint64_t c, d, s, f; /* Registers C, D, S, and F. */; uint64_t pc; /* Program counter. */ uint64_t sp; /* Stack pointer. */ + uint64_t bp; /* Base pointer. */ + uint64_t r11, r12, r13, r14, r15; /* Registers R11-R15. */; uint64_t clk; /* Number of clock cycles. */ }; +typedef struct op operand; + +struct op { + uint8_t type; /* Operand Type. 0 = register, 1 = memory. */ + uint8_t id; /* Operand Type ID 1. 4 bits. */ + uint8_t rind[2]; /* Register(s) used for register indirect. */ + uint8_t scale; /* Scale used for SIB. */ + int is_ind : 1; /* Flag used to determine if this operand is an indirect mode. */ + uint64_t value; /* Value of operand (used only by memory operands). */ +}; + extern int asmmon(); enum sw_type {RS, AM, BYTE}; diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s index 5828fdb..550228d 100644 --- a/programs/sub-suite/declare.s +++ b/programs/sub-suite/declare.s @@ -769,7 +769,7 @@ inst: .byte $81 ; Mnemonic Table. -mne: +mnem: .byte "ADC" .byte "AND" .byte "ASR" @@ -852,9 +852,9 @@ cmd_srt: .word list .word asm .word help - .word ins + .word inst .word run - .word set + .word set_val ; Return table used by get_ctrlidx. ct_rtb: diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s index 9c3cb87..b2850aa 100644 --- a/programs/sub-suite/lexer.s +++ b/programs/sub-suite/lexer.s @@ -434,7 +434,7 @@ ptok_alph: ldb idx1 ; Get the instruction ID. cpb #OPNUM ; Have we reached the end of the mnemonic table? beq @end ; Yes, so we're done. - lda.w #mne ; No, so get the start of the mnemonic table. + lda.w #mnem ; No, so get the start of the mnemonic table. clc ; Prepare for a non carrying add. adc.w idx2 ; Offset the pointer, by the length of the previous string. pha.q ; Preserve the mnemonic string pointer. diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s index 74ad654..ae35146 100644 --- a/programs/sub-suite/libc.s +++ b/programs/sub-suite/libc.s @@ -126,53 +126,49 @@ isdigit: sbc #'0' ; Subtract $30 from the passed character. and #$FF ; Make sure that we have only one byte. cmp #10 ; Is the subtracted value, less than 10? - bcs @false ; No, so return false. -@true: - lda #1 ; Yes, so return true. - bra @end ; We are done. -@false: - lda #0 ; Return false. -@end: + lcc #1 ; Yes, so return true. + lcs #0 ; No, so return false. +; bcs @false ; No, so return false. +;@true: +; lda #1 ; Yes, so return true. +; bra @end ; We are done. +;@false: +; lda #0 ; Return false. +;@end: rts ; End of isdigit. isxdigit: pha ; Preserve the character. jsr isdigit ; Is this character, a decimal digit? pla ; Get the character back. - bne @true ; Yes, so return true. + bne @end ; Yes, so return true. @alpha: - sec ; No, so prepare for a non carrying subtract. - ora #$20 ; Convert it to lowercase. - sbc #'a' ; Subtract $61 from the character. + ora #$20 ; No, so convert it to lowercase. + sub #'a' ; Subtract $61 from the character. and #$FF ; Make sure that we have only one byte. cmp #6 ; Is the subtracted value, less than 6? - bcs @false ; No, so return false. -@true: - lda #1 ; Yes, so return true. - bra @end ; We are done. -@false: - lda #0 ; Return false. + lcc #1 ; Yes, so return true. + lcs #0 ; No, so return false. +; bcs @false ; No, so return false. +;@true: +; lda #1 ; Yes, so return true. +; bra @end ; We are done. +;@false: +; lda #0 ; Return false. @end: rts ; End of isxdigit. isupper: - sec ; Prepare for a non carrying subtraction. - sbc #'A' ; Subtract $41 from the passed character. + sub #'A' ; Subtract $41 from the passed character. bra isletter ; Check if it's less than 26. islower: - sec ; Prepare for a non carrying subtraction. - sbc #'a' ; Subtract $61 from the passed character. + sub #'a' ; Subtract $61 from the passed character. isletter: and #$FF ; Make sure that we have only one byte. cmp #26 ; Is the subtracted value, less than 26? - bcs @false ; No, so return false. -@true: - lda #1 ; Yes, so return true. - bra @end ; We are done. -@false: - lda #0 ; Return false. -@end: + lcc #1 ; Yes, so return true. + lcs #0 ; No, so return false rts ; End of isletter. @@ -209,8 +205,7 @@ malloc: pha.q ; Preserve the size. and #0 ; Reset A. tay ; Reset Y. - pha.q ; Create two more local variables. - pha.q ; + sbs #$10 ; Allocate 2 local variables onto the stack. lda.q sp+17 ; Get the size. ora.d sp+21 ; Is the size zero? beq @end ; Yes, so we're done. @@ -282,7 +277,7 @@ malloc: bra @retptr ; Return the pointer. @sliceblk: ldy #fblk.size ; Get the size of the current block. - lda.q (sp+9). y ; + lda.q (sp+9), y ; sec ; Prepare for a non borrowing subtract. sbc.q sp+17 ; Subtract the current block's size from the passed size. sta.q (sp+9), y ; Set the current block's size to the subtracted size. @@ -300,9 +295,7 @@ malloc: clc ; Prepare for a non carrying add. adc #ublk ; Return the pointer to the real memory block. @end: - ply.q ; Clean up the stack frame. - ply.q ; - ply.q ; + ads #$18 ; Clean up the stack frame. ply.q ; Restore Y. rts ; End of malloc. @@ -320,9 +313,7 @@ free: pha.q ; Push the pointer argument to the stack. and #0 ; Reset A. tay ; Reset Y. - pha.q ; Add 3 more local variables. - pha.q ; - pha.q ; + sbs #$18 ; Allocate 3 local variables onto the stack. lda.q sp+25 ; Get the passed pointer. ora.d sp+29 ; Is the passed pointer NULL? bne @getrealblk ; No, so get the real block. @@ -373,10 +364,7 @@ free: ldy #fblk.next ; Delete the next block. sta.q (sp+25), y; @end: - pla.q ; Clean up the stack frame. - pla.q ; - pla.q ; - pla.q ; + ads #$20 ; Clean up the stack frame. ply.q ; Restore Y. plb.q ; Restore B. pla.q ; Restore A. @@ -424,7 +412,7 @@ free: cmp.q sp+9 ; Is the right pointer NULL? bne @normerge ; No, so don't merge the right block. @rmerge: - ldy #fblk.size : Get the size of the right pointer. + ldy #fblk.size ; Get the size of the right pointer. lda.q sp+17 ; Get the size of the current block. clc ; Prepare for a non carrying add. adc.q (sp+9), y ; Add the size of the current block, with the size of the right pointer. @@ -500,10 +488,7 @@ free: ldy #fblk.prev ; Set the previous block, to the left pointer. sta.q (sp+25), y; @end2: - pla.q ; Clean up the stack frame. - pla.q ; - pla.q ; - pla.q ; + ads #$20 ; Clean up the stack frame. ply.q ; Restore Y. plb.q ; Restore B. pla.q ; Restore A. @@ -534,8 +519,6 @@ memcpy: beq @end ; The size is zero, so we're done. bra @loop ; Keep looping. @end: - pla.q ; Clean up the stack frame. - pla.q ; - pla.q ; + ads #$18 ; Clean up the stack frame. pla.q ; Restore the return value. rts ; End of memcpy. diff --git a/programs/sub-suite/shift_line.c b/programs/sub-suite/shift_line.c new file mode 100644 index 0000000..255d21b --- /dev/null +++ b/programs/sub-suite/shift_line.c @@ -0,0 +1,79 @@ +#include + +const uint8_t bits[8] = { + 0x80, + 0x40, + 0x20, + 0x10, + 0x08, + 0x04, + 0x02, + 0x01 +}; + +int maxcol = 80; +int scr_str = 0; +int scr_row = 0; +int scr_col = 0; +uint8_t bitabl[16]; + +uint8_t bitpos(unsigned int row, uint8_t *mask) { + uint8_t bit = row & 7; + *mask = bits[bit]; + return row >> 3; + +} + +void setbit(unsigned int row) { + uint8_t mask; + uint8_t byte = bitpos(row, &mask); + bitabl[byte] |= mask; +} + +void clrbit(unsigned int row) { + uint8_t mask; + uint8_t byte = bitpos(row, &mask); + bitabl[byte] &= ~mask; +} + +int find_end(char *str, int start) { + int i; + for (i = start; str[i]; i++); + return i; +} + +void shift_line(char *str, int cursor, int left) { + /*int cursor = ((scr_row+scr_str)*maxcol)+scr_col;*/ + int end = find_end(str, cursor); + if (left) { + int i = end-1; + int j = end; + for (; i > cursor; i--, j--) { + if (i < 0) { + i = 0; + str[i] = 0; + break; + } + str[j] = str[i]; + str[i] = 0; + + } + /*str[i+1] = (!str[i+1]) ? ' ' : str[i+1];*/ + end = find_end(str, i+2); + /*str[i+1] = (str[i+1] == ' ') ? 0 : str[i+1];*/ + if ((end/maxcol) > scr_row) { + setbit(end/maxcol); + } + } else { + int i = cursor; + int j = cursor-1; + for (; str[i]; i++, j++) { + str[j] = str[i]; + str[i] = 0; + } + end = find_end(str, i); + if ((end % maxcol) == 0 && (end/maxcol) > scr_row) { + clrbit(end/maxcol); + } + } +} diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s index 0a3ee80..80aaa47 100644 --- a/programs/sub-suite/subasm.s +++ b/programs/sub-suite/subasm.s @@ -16,21 +16,17 @@ subasm: jsr lex ; No, so start lexing this line. bra @end ; We are done. @cmd: - ldb #1 ; Set the second pointer - lda.d #cmd_srt ; to the command subroutine table. - jsr set_ptr ; - deb ; Reset B. - tba ; Reset A. lda regf ; Get the command ID. cmp #8 ; Is the command ID greater than the command count? bcs @end ; Yes, so we're done. lsl #1 ; No, so multiply the command ID by two. - tay ; Set the index to the offset that we just calculated. - lda.w (ptr2), y ; Get the command subroutine, from the command subroutine table. - ldb #2 ; Save it in the third pointer. - jsr set_ptr ; - ldb #0 ; Reset B. - jsr (ptr3) ; Run the command's subroutine. + phx.q ; Preserve X. + tax ; Set the index to the offset that we just calculated. + lea.w (cmd_srt, x); Get the pointer, from the command subroutine table. + plx.q ; Restore X. + and #0 ; Reset A. + tab ; Reset B. + jsr (e) ; Run the command's subroutine. @end: and #0 ; Reset A. jsr update_ptr ; Get the screen buffer index. @@ -39,12 +35,14 @@ subasm: rts ; End of subasm. chk_shcmd: - tba ; Reset A. - inb ; Set the second pointer - lda.w #sh_cmds ; to the shortend command table. - jsr set_ptr ; - deb ; Reset B. - tba ; Reset A. + and #0 ; Reset A. + tab ; Reset B. +; inb ; Set the second pointer +; lda.w #sh_cmds ; to the shortend command table. +; jsr set_ptr ; +; deb ; Reset B. +; tba ; Reset A. + lea sh_cmds ; Get the address of the short command table. phy.w ; Preserve the screen buffer position. txy ; Set our index to zero. lda (ptr), y ; Is there nothing in the command buffer? @@ -53,27 +51,31 @@ chk_shcmd: beq @false ; Yes, so return that we failed. jsr tolower ; No, so convert it to lowercase. @loop: - ldb (ptr2), y ; Are we at the end of the table? +; ldb (ptr2), y ; Are we at the end of the table? + ldb (e) ; Are we at the end of the table? beq @false ; Yes, so return that we failed. cmp b ; No, so did the character match? beq @found ; Yes, so check if there are any arguments. - iny ; No, so check the next command. + ine ; No, so check the next command. + iny ; bra @loop ; Keep looping. @found: sty regf ; Save the command ID. - ldy #1 ; Check the next character in the command buffer. - lda (ptr), y ; Is this the end of the buffer? - beq @true ; Yes, so return that we succeded. + lea (ptr) ; Get the address of the next character. + ine ; +; ldy #1 ; Check the next character in the command buffer. +; lda (ptr), y ; Is this the end of the buffer? + lda (e) ; Is this the end of the buffer? + beq @true ; Yes, so return true. cmp #' ' ; No, but is this a space? - beq @true ; Yes, so return that we succeded. - bra @false ; No, so return that we failed. -@true: - lda #1 ; Return true. - bra @end ; We are done. + beq @true ; Yes, so return true. @false: ldb #0 ; Reset B. tba ; Return false. tax ; Reset X. + bra @end ; We are done. +@true: + lda #1 ; Return true. @end: ply.w ; Get back the screen buffer position. rts ; End of chk_shcmd. @@ -130,8 +132,9 @@ viewmem: jsr print_char ; jsr print_hi ; Place the address in the string buffer. jsr print_chunk ; Place the next 16 bytes in the string buffer. - lda.d #strbuf ; Print the string buffer. - jsr print_str ; + lea strbuf ; Print the string buffer. +; jsr print_str ; + jsr print_sfast ; inc idx1 ; Increment the chunk count. ldb idx1 ; Get the chunk count. cpb #$10 ; Did we print 16 chunks? @@ -161,15 +164,15 @@ help: nop ; @end: rts ; End of help. -ins: +inst: nop ; @end: - rts ; End of ins. + rts ; End of inst. run: nop ; @end: rts ; End of run. -set: +set_val: nop ; @end: - rts ; End of set. + rts ; End of set_val. diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s index bec3f41..387b5db 100644 --- a/programs/sub-suite/subeditor.s +++ b/programs/sub-suite/subeditor.s @@ -6,18 +6,18 @@ .org $8000 reset: cps ; Reset the processor status register. - ldx.d #$2FFFF ; Reset the stack pointer. - txs ; + lds.d #$2FFFF ; Reset the stack pointer. + lea 0 ; Reset E. ldy #0 ; Reset Y. tyx ; Reset X. jsr init_heap ; Initialize the heap. tax ; Set the stack pointer to the end of RAM. txs ; - sec ; Prepare for a non borrowing subtract. - sbc.d #STKSIZE ; Subtract the stack size, from the end of RAM. + sub.d #STKSIZE ; Subtract the stack size, from the end of RAM. sta.q heapend ; Save the end of the heap. and #0 ; Reset A. tax ; Reset X. + clc ; Reset the carry flag, just in case. jsr init_tables ; Initialize the main tables. ; jsr test_free ; jsr clr_scr ; Clear the screen. @@ -26,14 +26,9 @@ reset: init_heap: - and #0 ; Reset A. - lda.d #HEAPORG ; Get the heap's starting point. - sta.q heapptr ; - phb.q ; Preserve the value in B. - phx.q ; Preserve the value in X. + lea HEAPORG ; Get the heap's starting point. + ste.q heapptr ; jsr findramend ; Find the end of the heap. - plb.q ; Restore the value in B. - plx.q ; Restore the value in X. rts ; End of init_heap. @@ -79,50 +74,32 @@ init_tables: clr_arr: - phb ; Preserve whatever was in B. - ldb #0 ; Clear B. - jsr set_ptr ; Set the first pointer to the parameter. - adc #8 ; Set the second pointer to the parameter, plus eight. - inb ; Tell set_ptr to set the second pointer. - jsr set_ptr ; - deb ; Set B back to zero. - tba ; -@loop: - cpy.w scr_ptr ; Did we clear all of the array? - bcs @end ; Yes, so we're done. - sta.q (ptr), y ; No, so clear eight bytes. - sta.q (ptr2), y ; Clear eight more bytes. - tya ; Copy the array index. - adc #$10 ; Increment the index by 16. - tay ; Update the index. - tba ; Reset the Accumulator. - sta.q (ptr), y ; Do this one more time, to clear 32 bytes. - sta.q (ptr2), y ; - tya ; - adc #$10 ; - tay ; - tba ; - bra @loop ; Keep looping. + stz.q (e) ; Clear eight bytes. + ade #8 ; Increment the pointer by 8. + stz.q (e) ; Clear eight bytes. + ade #8 ; Increment the pointer by 8. + sub #$10 ; Subtract 16 from the size. + bcc @end ; We've reached the end of the array, so we're done. + beq @end ; + bra clr_arr ; Keep looping. @end: - ldy.w zero ; Set the index back to zero. - plb ; Get whatever was in the B register, back. rts ; End of clr_arr. pnt_strt: - lda.w #ed_name ; Print the name of the editor. + lea ed_name ; Print the name of the editor. jsr print_str ; - lda.w #ver_str ; Print the version text. + lea ver_str ; Print the version text. jsr print_str ; - lda.w #ed_ver ; Print the version number. + lea ed_ver ; Print the version number. jsr print_str ; - lda.w #ed_sver ; Print the sub version number. + lea ed_sver ; Print the sub version number. jsr print_str ; lda #'\n' ; Print a newline. jsr print_char ; - lda.w #made ; Print the "Created by" text. + lea made ; Print the "Created by" text. jsr print_str ; - lda.w #author ; Print the name of the author. + lea author ; Print the name of the author. jsr print_str ; lda #'\n' ; Print a newline. jsr print_char ; @@ -133,8 +110,7 @@ clr_cmd: and #0 ; Reset A. tay ; Reset Y. lda.w #CMDSIZE ; Set the clear count to CMDSIZE. - sta.w scr_ptr ; - lda.q cmd_buf ; Set the array to be cleared to the command buffer. + lea (cmd_buf) ; Set the array to be cleared to the command buffer. jsr clr_arr ; Clear the command buffer. rts ; End of clr_cmd. @@ -173,37 +149,59 @@ getchar: print_str: - ldx #0 ; Reset X. - sta.q end ; Save the parameter. -@reset: - lda.q end ; Get the parameter. - ldb #0 ; Clear the B register. - jsr set_ptr ; Set the first pointer to the parameter. - tba ; Clear the Accumulator. + and #0 ; Reset A. + tba ; Reset B. @loop: ldb #1 ; Enable replace mode. stb regb ; - lda.q ptr ; Get the first pointer. - cmp.q end ; Did the pointer change? - bne @reset ; Yes, so set it back. and #0 ; No, reset the accumulator. - txy ; Copy the string index into Y. - ldb (ptr), y ; Are we at the end of the string? + ldb (e) ; Are we at the end of the string? beq @end ; Yes, so we're done. jsr update_ptr ; No, so get the screen buffer index. tay ; Save it in Y. tba ; Get the character back. - inx ; Increment the string index. - phx ; Preserve the string index. + ine ; Increment the string pointer. jsr print_char ; Print the character. - plx ; Get the string index back. bra @loop ; Keep looping. @end: - ldb #0 ; Enable insert mode. - stb regb ; - tba ; Reset A. + stz regb ; Enable insert mode. + and #0 ; Reset A. + tab ; Reset B. rts ; End of print_str. + +;print_str: +; ldx #0 ; Reset X. +; sta.q end ; Save the parameter. +;@reset: +; lda.q end ; Get the parameter. +; ldb #0 ; Clear the B register. +; jsr set_ptr ; Set the first pointer to the parameter. +; tba ; Clear the Accumulator. +;@loop: +; ldb #1 ; Enable replace mode. +; stb regb ; +; lda.q ptr ; Get the first pointer. +; cmp.q end ; Did the pointer change? +; bne @reset ; Yes, so set it back. +; and #0 ; No, reset the accumulator. +; txy ; Copy the string index into Y. +; ldb (ptr), y ; Are we at the end of the string? +; beq @end ; Yes, so we're done. +; jsr update_ptr ; No, so get the screen buffer index. +; tay ; Save it in Y. +; tba ; Get the character back. +; inx ; Increment the string index. +; phx ; Preserve the string index. +; jsr print_char ; Print the character. +; plx ; Get the string index back. +; bra @loop ; Keep looping. +;@end: +; stz regb ; Enable insert mode. +; and #0 ; Reset A. +; tab ; Reset B. +; rts ; End of print_str. + getbit: clc ; Clear the carry flag. lda scr_str ; Has the screen been scrolled? @@ -432,21 +430,27 @@ findend: print_char: + phe.q ; Preserve E. sta rega ; Preserve the character. ldb #2 ; Make sure that set_ptr sets the third pointer. lda.q buffer ; Set the third pointer to the start of the screen buffer. jsr set_ptr ; deb ; Set B to one. tba ; Reset A. +; inc step ; lda rega ; Get the character back. jsr get_ctrlidx ; Get the control code jump table index. lsl #1 ; Multiply the return value by two, to get the index. tax ; - lda.w ct_jtb, x ; Get the address of the control code handler. - jsr set_ptr ; Set the second pointer to the control code handler. + lea.w (ct_jtb, x); Get the address of the control code handler. +; pha.q ; +; ple.q ; +; jsr set_ptr ; Set the second pointer to the control code handler. deb ; Reset B. tba ; Reset A. - jmp (ptr2) ; Jump to the handler for that control code. + jsr (e) ; Jump to the handler for that control code. + ple.q ; Restore E. + rts printc: lda #0 ; start trying to print a character. sta regd ; @@ -567,24 +571,19 @@ nl: clr_scr: lda #maxrow ; sta scr_end ; - lda #0 ; - sta scr_str ; + stz scr_str ; tay ; lda.w #LWSIZE ; Set the clear count to LWSIZE. - sta.w scr_ptr ; - lda.q bitabl ; Set the array to be cleared to the linewrap table. + lea (bitabl) ; Set the array to be cleared to the linewrap table. jsr clr_arr ; Clear the linewrap table. lda.w #SCRSIZE ; Set the clear count to SCRSIZE. - sta.w scr_ptr ; - lda.q buffer ; Set the array to be cleared to the screen buffer. + lea (buffer) ; Set the array to be cleared to the screen buffer. jsr clr_arr ; Clear the screen buffer. -; tay ; ; lda.w #CMDSIZE ; Set the clear count to CMDSIZE. -; sta.w scr_ptr ; -; lda.d #cmd_buf ; Set the array to be cleared to the command buffer. +; lea (cmd_buf) ; Set the array to be cleared to the command buffer. ; jsr clr_arr ; Clear the screen buffer. - sta scr_col ; - sta scr_row ; + stz scr_col ; + stz scr_row ; jsr update_pos ; lda #$C ; sta scr ; @@ -694,7 +693,7 @@ shftln: beq @dec_loop ; Yes, so shift, and decrement. ldb #0 ; Clear the B register. bra @inc_loop ; No, so shift, and increment. -@neg: +@minus: ldy.w zero ; Set the source poition to 0. stb (ptr3), y ; Clear the character that is in the source. bra @end ; We are done. @@ -712,7 +711,7 @@ shftln: sta (ptr3), y ; Place the character from the source position, to the destination position. ply.w ; Set our position back to the source. stb (ptr3), y ; Clear the character that is in the source. - bng @neg ; The source underflowed, so set it back to zero, + bng @minus ; The source underflowed, so set it back to zero, dey ; Decrement the source position. dex ; Decrement the destination position. bra @inc_loop ; Keep looping. @@ -767,6 +766,7 @@ shftln: @end5: rts ; End of shftln. + esc: lda status ; Get the next character. lda kbd ; diff --git a/programs/sub-suite/subsuite.s b/programs/sub-suite/subsuite.s index d28b4f2..7b31c31 100644 --- a/programs/sub-suite/subsuite.s +++ b/programs/sub-suite/subsuite.s @@ -19,5 +19,6 @@ a ;l a ;.org reset ;v +;f "subsuite.bin" $8000 ;q d diff --git a/programs/sub-suite/utils.s b/programs/sub-suite/utils.s index 21539eb..3813a05 100644 --- a/programs/sub-suite/utils.s +++ b/programs/sub-suite/utils.s @@ -48,12 +48,20 @@ print_lo: pla ; Get the nibble offset back. bra @loop ; Keep looping. @end: - lda #0 ; Null terminate the string buffer. - sta strbuf, x ; + and #0 ; Reset A. + sta strbuf, x ; Null terminate the string buffer. tax ; Reset X. - lda.d #strbuf ; Print the string buffer. - jsr print_str ; + lea strbuf ; Print the string buffer. +; jsr print_str ; + jsr print_sfast ; Use the faster, but less robust print string routine. rts ; End of print_lo. +;@end: +; lda #0 ; Null terminate the string buffer. +; sta strbuf, x ; +; tax ; Reset X. +; lea strbuf ; Print the string buffer. +; jsr print_str ; +; rts ; End of print_lo. print_chunk: @@ -302,49 +310,76 @@ get_ptok: get_ctrlidx: - cmp #$7F ; Is this a delete character? - beq @del ; Yes, so return the same value as backspace. - sec ; Do a non borrowing subtract. - sbc #8 ; Subtract 8 from the character, to get the index. +; phe.q ; Preserve E. +; cmp #$7F ; Is this a delete character? +; beq @del ; Yes, so return the same value as backspace. +; sec ; Do a non borrowing subtract. +; sbc #8 ; Subtract 8 from the character, to get the index. + sub #8 ; Subtract 8 from the character, to get the index. tax ; Copy the index to X. and #0 ; Reset A. - cpx #19 ; Are we less than, or equal to the max size of the table? - bcc @get_rtval ; Yes, so get the return value from the table. - beq @get_rtval ; - rts ; End of get_ctrlidx. -@get_rtval: - lda ct_rtb, x ; Get the return value from the table. - rts ; End of get_ctrlidx. -@del: - lda #2 ; Return 2. + cpx #19 ; Are we within the range of the table? + lea ct_rtb, x ; Get the address of the value to return. + lcc (e) ; Read from the table if we're within the range of the table. + leq (e) ; + cmp #$7F ; Is this a delete character? + leq #2 ; Return 2 if this is the delete character. +; bcc @get_rtval ; Yes, so get the return value from the table. +; beq @get_rtval ; +; ple.q ; Restore E. rts ; End of get_ctrlidx. +;@get_rtval: +; lda ct_rtb, x ; Get the return value from the table. +; rts ; End of get_ctrlidx. +;@del: +; lda #2 ; Return 2. +; rts ; End of get_ctrlidx. findramend: - pha.q ; Set the end of RAM pointer to the argument. + phx.q ; Preserve X. and #0 ; Reset A. - tab ; Reset B. lda #MAGIC ; Set A to a magic number. @loop: - ldx (sp+1) ; Preserve the value. - sta (sp+1) ; Write the magic number to the current end of RAM. - cmp (sp+1) ; Is the value in RAM, the same as the magic number we wrote? + ldx (e) ; Preserve the value. + sta (e) ; Write the magic number to the current end of RAM. + cmp (e) ; Is the value in RAM, the same as the magic number we wrote? bne @moveback ; No, so move back until we find the last writable memory location. - stx (sp+1) ; Yes, so restore the previous value. - pha.q ; Preserve the magic number. - lda.q sp+9 ; Get the end of RAM pointer. - clc ; Prepare for a non carrying add. - adc.w #$4000 ; Increment the end of RAM pointer by 16K. - sta.q sp+9 ; Save the new end of RAM pointer. - pla.q ; Restore the magic number. + stx (e) ; Yes, so restore the previous value. + ade.w #$4000 ; Increment the end of RAM pointer by 16K. bra @loop ; Keep looping. @moveback: - dec.q sp+1 ; Decrement the end of RAM pointer. - ldx (sp+1) ; Preserve the value. - sta (sp+1) ; Write the magic number to the current end of RAM. - cmp (sp+1) ; Is the value in RAM, the same as the magic number we wrote? + dee ; Decrement the end of RAM pointer. + ldx (e) ; Preserve the value. + sta (e) ; Write the magic number to the current end of RAM. + cmp (e) ; Is the value in RAM, the same as the magic number we wrote? bne @moveback ; No, so keep looping. - stx (sp+1) ; Yes, so restore the previous value. + stx (e) ; Yes, so restore the previous value. @end: - pla.q ; Restore the argument. + phe.q ; Return the end of RAM pointer. + pla.q ; + plx.q ; Restore X. rts ; End of findramend. + + +print_sfast: +; inc step ; + pea (buffer), y ; Push the address of the cursor's postion in the screen buffer to the stack. +@loop: + lda (e) ; Get the character. + beq @end ; We've hit the end of the string, so we're done. + cmp #'\n' ; Did we get a newline? + beq @nl ; Yes, so move the cursor to the next line. + sta (sp+1) ; Print the character to the screen buffer. + sta scr ; Print the character to the screen. + inc scr_col ; Move the cursor left by one character. + ine ; Increment the string pointer. + inc.q sp+1 ; Increment the screen buffer pointer. + bra @loop ; Keep looping. +@nl: + stz scr_col ; Move the cursor to the start of the line. + inc scr_row ; Move the cursor down by one line. + bra @loop ; Keep looping. +@end: + ads #8 ; Cleanup the stack frame. + rts ; End of print_sfast. diff --git a/sux.c b/sux.c index 4ccd2d5..25bd8c5 100644 --- a/sux.c +++ b/sux.c @@ -97,7 +97,9 @@ uint8_t is_extop(uint8_t opcode, uint8_t dbg) { case STY_E: case STA_E: case STB_E: - case STX_E: return 0; + case STX_E: + case JMP_E: + case JSR_E: return 0; } return 1; } @@ -109,6 +111,7 @@ void *run(void *args) { uint8_t prefix = 0; uint8_t ext_prefix = 0; uint8_t prefix2 = 0; + uint8_t op_id = 0; uint8_t opcode = 0; union reg address; union reg value; @@ -175,19 +178,25 @@ void *run(void *args) { pthread_mutex_unlock(&mutex); #endif #endif - uint32_t instr = read_value(cpu, 0, cpu->pc, 3, 1, 0); + uint32_t instr = read_value(cpu, 0, cpu->pc, 4, 1, 0); uint8_t *tmp_inst = (uint8_t *)&instr; - prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0; - ext_prefix = ((*tmp_inst & 0xD) == 0xD) ? *tmp_inst++ : 0; - opcode = *tmp_inst; - cpu->pc += ((instr & 3) == 3)+((ext_prefix & 0xD) == 0xD)+1; + uint8_t inst_len = 0; + prefix = ((instr & 3) == 3) ? tmp_inst[inst_len++] : 0; + ext_prefix = ((tmp_inst[inst_len] & 0xF) == 0xD) ? tmp_inst[inst_len++] : 0; + opcode = tmp_inst[inst_len++]; + op_id = (ext_prefix == 0x1D) ? tmp_inst[inst_len++] : 0; + + cpu->pc += inst_len; address.u64 = cpu->pc; + uint8_t operand_type[2]; uint8_t am; + uint8_t ortho_id[2]; uint8_t ext_id = 0; uint8_t tmp_opcode = opcode; uint8_t tmp_ext_prefix = ext_prefix; + int is_ortho = 0; if (ext_prefix) { - ext_id = ((ext_prefix >> 4) & 0xF); + ext_id = (ext_prefix >> 4); switch (ext_id) { case 0x0: am = ext_optype[opcode]; @@ -220,9 +229,19 @@ void *run(void *args) { case STA_E: tmp_opcode = STA_Z; break; case STB_E: tmp_opcode = STB_Z; break; case STX_E: tmp_opcode = STX_Z; break; + case JMP_E: tmp_opcode = JMP_Z; break; + case JSR_E: tmp_opcode = JSR_Z; break; } } break; + case 0x1: + operand_type[0] = ((opcode & 0x10) >> 4); + operand_type[1] = ((opcode & 0x08) >> 3); + ortho_id[0] = op_id >> 4; + ortho_id[1] = op_id & 0x0F; + am = IMPL; + is_ortho = 1; + break; } } else { am = optype[opcode]; @@ -234,7 +253,7 @@ void *run(void *args) { #if keypoll pthread_mutex_lock(&mutex); #endif - disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, thread); + disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, operand_type, ortho_id, thread); lines+=1; #if keypoll pthread_mutex_unlock(&mutex); @@ -246,7 +265,7 @@ void *run(void *args) { addr[STEP_ADDR] = 1; step = 1; }*/ - if (isrw(opcode) && am != REL && isread(opcode)) { + if (isrw(opcode, ext_prefix) && am != REL && isread(opcode, ext_prefix)) { value.u64 = read_value(cpu, 0, address.u64, size, 1, check_io); } } @@ -254,12 +273,15 @@ void *run(void *args) { ext_prefix = tmp_ext_prefix; opcode = tmp_opcode; if (ext_prefix) { + uint8_t tmp = 0; switch (ext_id) { - case 0x0: exec_ext_inst(cpu, opcode, prefix, value, address, size, thread); break; + case 0x0: exec_ext_inst(cpu, opcode, prefix, value.u64, address.u64, size, thread); break; + case 0x1: exec_ortho_inst(cpu, opcode, prefix, size, operand_type, ortho_id, thread); break; } } else { - exec_base_inst(cpu, opcode, prefix, value, address, size, thread); + exec_base_inst(cpu, opcode, prefix, value.u64, address.u64, size, thread); } + //usleep(1); #if !IO ins++; #endif diff --git a/sux.h b/sux.h index 9d7bcb3..6b8a7f6 100644 --- a/sux.h +++ b/sux.h @@ -37,6 +37,15 @@ extern uint8_t end; #define setflag(flag, bit) ((flag)) ? (cpu->ps.u8[thread] |= bit) : (cpu->ps.u8[thread] &= ~bit) #define getflag(bit) (cpu->ps.u8[thread] & bit) +#define ORTHO_1CC(mne, cc) \ + mne##_R##cc: case mne##_M##cc + +#define ORTHO_1OP(mne) \ + mne##_R: case mne##_M + +#define ORTHO_2OP(mne) \ + mne##_RR: case mne##_RM: case mne##_MR: case mne##_MM + extern pthread_mutex_t mutex; extern pthread_mutex_t main_mutex; extern pthread_cond_t cond; @@ -44,7 +53,7 @@ extern pthread_cond_t main_cond; #if debug extern void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread); -extern void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t thread); +extern void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t *op_type, uint8_t *op_id, uint8_t thread); #endif /*#define KEYBUF_SIZE 0x40 @@ -55,7 +64,7 @@ extern void io(uint64_t address, uint8_t rw); extern void init_scr(); -static inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) { +static /*inline*/ uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) { uint8_t id = (prefix & 0x0C) >> 2; switch (addrmode) { case ZM: @@ -88,72 +97,194 @@ static inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) { return 0xFF; } -static inline uint8_t isrw(uint8_t opcode) { - switch (opcode) { - case STA_AB: /* STA Absolute. */ - case STA_Z: /* STA Zero Matrix. */ - case STA_ZX: /* STA Zero Matrix, Indexed with X. */ - case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ - case STA_IN: /* STA Indirect. */ - case STA_IX: /* STA Indexed Indirect. */ - case STA_IY: /* STA Indirect Indexed. */ - case STY_AB: /* STY Absolute. */ - case STY_Z: /* STY Zero Matrix. */ - case STY_IN: /* STY Indirect. */ - case STX_AB: /* STX Absolute. */ - case STX_Z: /* STX Zero Matrix. */ - case STX_IN: /* STX Indirect. */ - case STB_AB: /* STB Absolute. */ - case STB_Z: /* STB Zero Matrix. */ - case STB_ZX: /* STB Zero Matrix, Indexed with X. */ - case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ - case STB_IN: /* STB Indirect. */ - case STB_IX: /* STB Indexed Indirect. */ - case STB_IY: /* STB Indirect Indexed. */ - case INC_AB: /* INC Absolute. */ - case INC_Z: /* INC Zero Matrix. */ - case DEC_AB: /* DEC Absolute. */ - case DEC_Z: /* DEC Zero Matrix. */ - return 0; /* Writing. */ - default: - return 1; /* Reading. */ +static /*inline*/ uint8_t get_ortho_addrsize(uint8_t prefix, uint8_t addrmode) { + uint8_t type = IMM; + switch (addrmode) { + case MEM_ABS : + case MEM_ABSR : + case MEM_AIND : + case MEM_AINDR: + case MEM_ARIND: type = ABS; break; + case MEM_ZM : + case MEM_ZMR : + case MEM_IND : + case MEM_ZINDR: + case MEM_ZRIND: type = ZM; break; } + return get_addrsize(prefix, type); } -static inline uint8_t isread(uint8_t opcode) { - switch (opcode) { - case LDA_IMM: /* LDA Immediate. */ - case LDA_AB: /* LDA Absolute. */ - case LDA_Z: /* LDA Zero Matrix. */ - case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ - case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ - case LDA_IN: /* LDA Indirect. */ - case LDA_IX: /* LDA Indexed Indirect. */ - case LDA_IY: /* LDA Indirect Indexed. */ - case LDB_IMM: /* LDB Immediate. */ - case LDB_AB: /* LDB Absolute. */ - case LDB_Z: /* LDB Zero Matrix. */ - case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ - case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ - case LDB_IN: /* LDB Indirect. */ - case LDB_IX: /* LDB Indexed Indirect. */ - case LDB_IY: /* LDB Indirect Indexed. */ - case LDY_IMM: /* LDY Immediate. */ - case LDY_AB: /* LDY Absolute. */ - case LDY_Z: /* LDY Zero Matrix. */ - case LDY_IN: /* LDY Indirect. */ - case LDX_IMM: /* LDX Immediate. */ - case LDX_AB: /* LDX Absolute. */ - case LDX_Z: /* LDX Zero Matrix. */ - case LDX_IN: /* LDX Indirect. */ - case JMP_AB: /* JMP Absolute. */ - case JMP_Z: /* JMP Zero Matrix. */ - case JMP_IN: /* JMP Indirect. */ - case JSR_IN: /* JSR Indirect. */ - case JSR_AB: /* Jump to SubRoutine. */ - case JSR_Z: /* JSR Zero Matrix. */ - return 0; - default: - return 1; + +static /*inline*/ uint8_t isrw(uint8_t opcode, uint8_t ext_prefix) { + if ((ext_prefix & 0xD) == 0xD) { + switch (ext_prefix >> 4) { + case 0x0: + switch (opcode) { + case STA_E : + case STB_E : + case STX_E : + case STY_E : + case STE_AB: + case STE_Z : + case STS_AB: + case STS_Z : + case STS_E : + case STZ_AB: + case STZ_Z : + case STZ_E : + case SNG_E : + case SPO_E : + case SCC_E : + case SCS_E : + case SEQ_E : + case SNE_E : + case INC_E : + case DEC_E : + case NOT_AB: + case NOT_Z : + case NOT_E : + case SWP_AB: + case SWP_Z : + case SWP_E : + case LLM_AB: + case LLM_Z : + case LLM_E : + case LRM_AB: + case LRM_Z : + case LRM_E : + case RLM_AB: + case RLM_Z : + case RLM_E : + case RRM_AB: + case RRM_Z : + case RRM_E : + case ARM_AB: + case ARM_Z : + case ARM_E : return 0; + default : return 1; + } + } + } else { + switch (opcode) { + case STA_AB: /* STA Absolute. */ + case STA_Z: /* STA Zero Matrix. */ + case STA_ZX: /* STA Zero Matrix, Indexed with X. */ + case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ + case STA_IN: /* STA Indirect. */ + case STA_IX: /* STA Indexed Indirect. */ + case STA_IY: /* STA Indirect Indexed. */ + case STY_AB: /* STY Absolute. */ + case STY_Z: /* STY Zero Matrix. */ + case STY_IN: /* STY Indirect. */ + case STX_AB: /* STX Absolute. */ + case STX_Z: /* STX Zero Matrix. */ + case STX_IN: /* STX Indirect. */ + case STB_AB: /* STB Absolute. */ + case STB_Z: /* STB Zero Matrix. */ + case STB_ZX: /* STB Zero Matrix, Indexed with X. */ + case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ + case STB_IN: /* STB Indirect. */ + case STB_IX: /* STB Indexed Indirect. */ + case STB_IY: /* STB Indirect Indexed. */ + case INC_AB: /* INC Absolute. */ + case INC_Z: /* INC Zero Matrix. */ + case DEC_AB: /* DEC Absolute. */ + case DEC_Z: /* DEC Zero Matrix. */ + return 0; /* Writing. */ + default: + return 1; /* Reading. */ + } + } +} +static /*inline*/ uint8_t isread(uint8_t opcode, uint8_t ext_prefix) { + if ((ext_prefix & 0xD) == 0xD) { + switch (ext_prefix >> 4) { + case 0x0: + switch (opcode) { + case LEA_AB : + case LEA_AX : + case LEA_AY : + case LEA_AI : + case LEA_AIX: + case LEA_AIY: + case LEA_Z : + case LEA_ZX : + case LEA_ZY : + case LEA_IN : + case LEA_IX : + case LEA_IY : + case PEA_AB : + case PEA_AX : + case PEA_AY : + case PEA_AI : + case PEA_AIX: + case PEA_AIY: + case PEA_Z : + case PEA_ZX : + case PEA_ZY : + case PEA_IN : + case PEA_IX : + case PEA_IY : + case LDS_IMM: + case LDS_AB : + case LDS_Z : + case LDS_E : + case LNG_IMM: + case LNG_E : + case LPO_IMM: + case LPO_E : + case LCC_IMM: + case LCC_E : + case LCS_IMM: + case LCS_E : + case LEQ_IMM: + case LEQ_E : + case LNE_IMM: + case LNE_E : + case LDA_E : + case LDB_E : + case LDX_E : + case LDY_E : + case JMP_E : + case JSR_E : return 0; + default : return 1; + } + } + } else { + switch (opcode) { + case LDA_IMM: /* LDA Immediate. */ + case LDA_AB: /* LDA Absolute. */ + case LDA_Z: /* LDA Zero Matrix. */ + case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ + case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ + case LDA_IN: /* LDA Indirect. */ + case LDA_IX: /* LDA Indexed Indirect. */ + case LDA_IY: /* LDA Indirect Indexed. */ + case LDB_IMM: /* LDB Immediate. */ + case LDB_AB: /* LDB Absolute. */ + case LDB_Z: /* LDB Zero Matrix. */ + case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ + case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ + case LDB_IN: /* LDB Indirect. */ + case LDB_IX: /* LDB Indexed Indirect. */ + case LDB_IY: /* LDB Indirect Indexed. */ + case LDY_IMM: /* LDY Immediate. */ + case LDY_AB: /* LDY Absolute. */ + case LDY_Z: /* LDY Zero Matrix. */ + case LDY_IN: /* LDY Indirect. */ + case LDX_IMM: /* LDX Immediate. */ + case LDX_AB: /* LDX Absolute. */ + case LDX_Z: /* LDX Zero Matrix. */ + case LDX_IN: /* LDX Indirect. */ + case JMP_AB: /* JMP Absolute. */ + case JMP_Z: /* JMP Zero Matrix. */ + case JMP_IN: /* JMP Indirect. */ + case JSR_IN: /* JSR Indirect. */ + case JSR_AB: /* Jump to SubRoutine. */ + case JSR_Z: /* JSR Zero Matrix. */ + return 0; + default: + return 1; + } } } @@ -178,7 +309,7 @@ static void *memcopy(void *restrict dst, const void *restrict src, unsigned int } -static inline uint64_t read_value(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { +static /*inline*/ uint64_t read_value(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { #if getclk cpu->clk += inc_clk; #endif @@ -210,7 +341,7 @@ static inline uint64_t read_value(struct sux *cpu, uint64_t reg, uint64_t addres } } -static inline void write_value(struct sux *cpu, uint64_t value, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { +static /*inline*/ void write_value(struct sux *cpu, uint64_t value, uint64_t address, uint8_t size, uint8_t inc_clk, uint8_t check_io) { if (address < mem_size) { size = (size > 7) ? 7 : size; #if 1 @@ -240,7 +371,7 @@ static inline void write_value(struct sux *cpu, uint64_t value, uint64_t address #endif } -static inline uint64_t offset_addr(struct sux *cpu, uint64_t offset, uint8_t size, uint8_t inc_clk, uint8_t prefix) { +static /*inline*/ uint64_t offset_addr(struct sux *cpu, uint64_t offset, uint8_t size, uint8_t inc_clk, uint8_t prefix) { uint64_t of; switch (prefix >> 6) { case 1: of = cpu->sp; break; @@ -261,11 +392,11 @@ static inline uint64_t offset_addr(struct sux *cpu, uint64_t offset, uint8_t siz } } -static inline uint64_t imm_addr(struct sux *cpu) { +static /*inline*/ uint64_t imm_addr(struct sux *cpu) { return cpu->pc; } -static inline uint64_t read_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) { +static /*inline*/ uint64_t read_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) { uint64_t address; uint8_t size = get_addrsize(prefix, type); if (prefix >> 6) { @@ -279,18 +410,18 @@ static inline uint64_t read_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_cl return address; } -static inline uint64_t idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg) { +static /*inline*/ uint64_t idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg) { #if getclk cpu->clk += inc_clk; #endif return read_addr(cpu, prefix, inc_clk, type, inc_pc) + idx_reg; } -static inline uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) { +static /*inline*/ uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) { return read_value(cpu, 0, read_addr(cpu, prefix, inc_clk, type, inc_pc), 7, inc_clk, 0); } -static inline uint64_t ind_idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg, uint8_t pre_idx) { +static /*inline*/ uint64_t ind_idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg, uint8_t pre_idx) { #if getclk cpu->clk += inc_clk; #endif @@ -301,7 +432,7 @@ static inline uint64_t ind_idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc } } -static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { +static /*inline*/ uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) { uint8_t rs = (prefix >> 4) & 3; uint8_t size = (1 << rs) - 1; uint64_t offset = read_value(cpu, 0, cpu->pc, size, inc_clk, 0); @@ -320,10 +451,10 @@ static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk } } -static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) { +static /*inline*/ uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) { uint64_t address = 0; uint8_t type; - if ((ext_prefix & 0xD) == 0xD) { + if ((ext_prefix & 0xF) == 0xD) { switch (ext_prefix >> 4) { case 0x0: type = ext_optype[opcode]; break; } @@ -375,53 +506,131 @@ static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, return address; } +static /*inline*/ uint64_t get_ortho_addr(struct sux *cpu, uint8_t prefix, uint64_t address, operand *op, uint64_t *value, uint8_t *op_type, uint8_t *op_id, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) { + for (int i = 0; i < 2; i++) { + union reg tmp; + tmp.u64 = 0; + op[i].type = op_type[i]; + op[i].id = op_id[i]; + op[i].value = 0; + op[i].rind[0] = 0xFF; + op[i].rind[1] = 0xFF; + if (op[i].type) { + int inst_size = 0; + int addr_size = get_ortho_addrsize(prefix, op[i].id); + int rs = (1 << (prefix >> 4)); + int is_rind = (op[i].id != MEM_ABS && op[i].id != MEM_ZM && op[i].id != MEM_AIND && op[i].id != MEM_IND && op[i].id != MEM_IMM); + if (is_rind) { + inst_size = (op[i].id == MEM_SIB)+1; + tmp.u64 = read_value(cpu, 0, address, inst_size-1, 0, 0); + if (inc_pc) { + address += inst_size; + } + op[i].rind[0] = (tmp.u8[inst_size-1] & 0x0F); + op[i].rind[1] = (tmp.u8[inst_size-1] >> 4); + if (op[i].rind[1] == op[i].rind[0]) { + op[i].rind[1] = 0xFF; + } + op[i].scale = (inst_size == 2) ? tmp.u8[0] : 0; + } + if (addr_size != 0xFF || (rs && op[i].id == MEM_IMM)) { + inst_size = (addr_size != 0xFF) ? addr_size+1 : rs; + op[i].value = read_value(cpu, 0, address, inst_size-1, inc_clk, 0); + value[i] = op[i].value; + if (inc_pc) { + address += inst_size; + } + } + if (is_rind) { + for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) { + uint64_t reg; + switch (op[i].rind[j]) { + case REG_A : reg = cpu->a; break; + case REG_B : reg = cpu->b; break; + case REG_X : reg = cpu->x; break; + case REG_Y : reg = cpu->y; break; + case REG_E : reg = cpu->e; break; + case REG_C : reg = cpu->c; break; + case REG_D : reg = cpu->d; break; + case REG_S : reg = cpu->s; break; + case REG_F : reg = cpu->f; break; + case REG_SP : reg = cpu->sp; break; + case REG_BP : reg = cpu->bp; break; + case REG_R11: reg = cpu->r11; break; + case REG_R12: reg = cpu->r12; break; + case REG_R13: reg = cpu->r13; break; + case REG_R14: reg = cpu->r14; break; + case REG_R15: reg = cpu->r15; break; + } + value[i] += reg; + } + if (op[i].id == MEM_SIB) { + value[i] *= op[i].scale+1; + } + #if getclk + cpu->clk += inc_clk; + #endif + } + } + } + return address; +} + -static inline uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t carry, uint8_t thread) { +static /*inline*/ uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t carry, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; uint64_t sum = reg+value+carry; setflag(sum == 0, Z); - setflag((sum >> 63), N); - setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V); + setflag(sum >> (msb-1), N); + setflag(((reg^value) >> (msb-1)) && ((reg^sum) >> (msb-1)), V); setflag((sum < value), C); return sum; } -static inline uint64_t transfer(struct sux *cpu, uint64_t src, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t transfer(struct sux *cpu, uint64_t src, uint64_t value, uint8_t thread) { setflag(src == 0, Z); setflag(src >> 63, N); return src; } -static inline void push(struct sux *cpu, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ void push(struct sux *cpu, uint64_t value, uint8_t size, uint8_t thread) { write_value(cpu, value, cpu->sp-size, size, 1, 0); cpu->sp -= size+1; } -static inline uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) { uint64_t value = read_value(cpu, 0, cpu->sp+1, size, 1, 0); cpu->sp += size+1; return value; } -static inline uint64_t and(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t and(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; reg &= value; setflag(reg == 0, Z); - setflag(reg >> 63, N); + setflag(reg >> (msb-1), N); return reg; } -static inline uint64_t or(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t or(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; reg |= value; setflag(reg == 0, Z); - setflag(reg >> 63, N); + setflag(reg >> (msb-1), N); return reg; } -static inline uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; reg ^= value; setflag(reg == 0, Z); - setflag(reg >> 63, N); + setflag(reg >> (msb-1), N); return reg; } -static inline uint64_t lsl(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t lsl(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint64_t sum = (value < msb) ? reg << value : 0; @@ -431,7 +640,7 @@ static inline uint64_t lsl(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ return sum; } -static inline uint64_t lsr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t lsr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint64_t sum = (value < msb) ? reg >> value : 0; @@ -441,7 +650,7 @@ static inline uint64_t lsr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ return sum; } -static inline uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint8_t sign = reg >> (msb-1); @@ -452,7 +661,7 @@ static inline uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ return sum; } -static inline uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint64_t sum; @@ -468,7 +677,7 @@ static inline uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ return sum; } -static inline uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint64_t sum; @@ -484,23 +693,27 @@ static inline uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ return sum; } -static inline uint64_t mul(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t mul(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; uint64_t sum = reg*value; setflag(sum == 0, Z); - setflag(sum >> 63, N); - setflag(!((reg^value) >> 63) && ((reg^sum) >> 63), V); + setflag(sum >> (msb-1), N); + setflag(!((reg^value) >> (msb-1)) && ((reg^sum) >> (msb-1)), V); return sum; } -static inline uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint64_t *rem, uint8_t thread) { +static /*inline*/ uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint64_t *rem, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; uint64_t sum = reg/value; *rem = reg % value; setflag(sum == 0, Z); - setflag((sum >> 63), N); + setflag(sum >> (msb-1), N); return sum; } -static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) { +static /*inline*/ void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) { uint64_t sum = reg-value; setflag(sum >> 63, N); setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V); @@ -509,14 +722,14 @@ static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t th } /* Increment, or Decrement register. */ -static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t thread) { +static /*inline*/ uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t thread) { reg += (inc) ? 1 : -1; setflag(reg == 0, Z); setflag(reg >> 63, N); return reg; } -static inline uint64_t lbcnt(struct sux *cpu, uint64_t value, uint8_t bit, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t lbcnt(struct sux *cpu, uint64_t value, uint8_t bit, uint8_t size, uint8_t thread) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; if ((!bit && !value) || (bit && value == -1)) { @@ -528,13 +741,13 @@ static inline uint64_t lbcnt(struct sux *cpu, uint64_t value, uint8_t bit, uint8 return j; } -static inline void bit_test(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { +static /*inline*/ void bit_test(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { setflag((value >> 7) & 1, N); setflag((value >> 6) & 1, V); setflag((value & reg) == 0, Z); } -static inline uint64_t swap(struct sux *cpu, uint64_t reg, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t swap(struct sux *cpu, uint64_t reg, uint8_t size, uint8_t thread) { size = (size > 7) ? 7 : size; uint8_t half = ((size-1)*8) >> 1; uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8)); @@ -544,14 +757,14 @@ static inline uint64_t swap(struct sux *cpu, uint64_t reg, uint8_t size, uint8_t } -static inline uint64_t popcnt(struct sux *cpu, uint64_t value, uint8_t thread) { +static /*inline*/ uint64_t popcnt(struct sux *cpu, uint64_t value, uint8_t thread) { uint64_t count = 0; for (; value; count++, value &= value - 1); return count; } /* Increment, or Decrement memory. */ -static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) { +static /*inline*/ void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) { uint8_t size = (1 << ((prefix >> 4) & 3))-1; uint64_t value; value = read_value(cpu, 0, address, size, 1, 0); @@ -568,7 +781,7 @@ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_ write_value(cpu, value, address, size, 1, 1); } -static inline void bitshft_mem(struct sux *cpu, uint8_t shft_type, uint64_t shft_cnt, uint64_t address, uint8_t prefix, uint8_t thread) { +static /*inline*/ void bitshft_mem(struct sux *cpu, uint8_t shft_type, uint64_t shft_cnt, uint64_t address, uint8_t prefix, uint8_t thread) { uint8_t size = (1 << ((prefix >> 4) & 3))-1; uint64_t value = read_value(cpu, 0, address, size, 1, 0); switch (shft_type) { @@ -581,22 +794,22 @@ static inline void bitshft_mem(struct sux *cpu, uint8_t shft_type, uint64_t shft write_value(cpu, value, address, size, 1, 1); } -static inline void not_mem(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t thread) { +static /*inline*/ void not_mem(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t thread) { uint8_t size = (1 << ((prefix >> 4) & 3))-1; write_value(cpu, ~read_value(cpu, 0, address, size, 1, 0), address, size, 1, 1); } -static inline void lbcnt_mem(struct sux *cpu, uint64_t address, uint8_t bit, uint8_t size, uint8_t thread) { +static /*inline*/ void lbcnt_mem(struct sux *cpu, uint64_t address, uint8_t bit, uint8_t size, uint8_t thread) { uint64_t value = read_value(cpu, 0, address, size, 1, 0); write_value(cpu, lbcnt(cpu, value, bit, size, thread), address, size, 1, 1); } -static inline void swap_mem(struct sux *cpu, uint64_t address, uint8_t size, uint8_t thread) { +static /*inline*/ void swap_mem(struct sux *cpu, uint64_t address, uint8_t size, uint8_t thread) { uint64_t value = read_value(cpu, 0, address, size, 1, 0); write_value(cpu, swap(cpu, value, size, thread), address, size, 1, 1); } -static inline uint64_t mem_move(struct sux *cpu, uint64_t n, uint64_t dst, uint64_t src, uint8_t rep, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t mem_move(struct sux *cpu, uint64_t n, uint64_t dst, uint64_t src, uint8_t rep, uint8_t size, uint8_t thread) { if (!rep) { uint64_t value = read_value(cpu, 0, src, size, 1, 1); write_value(cpu, value, dst, size, 1, 1); @@ -609,20 +822,278 @@ static inline uint64_t mem_move(struct sux *cpu, uint64_t n, uint64_t dst, uint6 } } -static inline uint64_t load(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t thread) { +static /*inline*/ uint64_t load(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t thread) { uint64_t value = read_value(cpu, reg, address, size, 1, 1); setflag(value == 0, Z); setflag(value >> 63, N); return value; } -static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { +static /*inline*/ void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_t prefix, uint8_t thread) { uint8_t size = (1 << ((prefix >> 4) & 3))-1; write_value(cpu, reg, address, size, 1, 1); } -static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, union reg value, union reg address, uint8_t size, uint8_t thread) { - uint8_t addr_size = get_addrsize(ext_optype[opcode], prefix); +static /*inline*/ uint64_t mov(struct sux *cpu, uint64_t src, uint64_t size, uint8_t thread) { + size = (size > 7) ? 7 : size; + uint8_t msb = (size+1)*8; + uint64_t dst = 0; + uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8)); + if (size < 7) { + dst = (dst & ~mask) | (src & mask); + } else { + dst = src; + } + setflag(dst == 0, Z); + setflag(dst >> (msb-1), N); + return dst; +} + +static /*inline*/ uint64_t set(struct sux *cpu, uint8_t flag, uint8_t thread) { + return flag; +} + +static /*inline*/ uint64_t inc_dec(struct sux *cpu, uint64_t value, uint8_t size, uint8_t inc, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; + value += (inc) ? 1 : -1; + setflag(value == 0, Z); + setflag(value >> (msb-1), N); + return value; +} + +static /*inline*/ uint64_t imul(struct sux *cpu, uint64_t dst, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; + int64_t sum = dst*value; + setflag(sum == 0, Z); + setflag(sum >> (msb-1), N); + setflag(!((dst^value) >> (msb-1)) && ((dst^sum) >> (msb-1)), V); + return sum; +} + +static /*inline*/ uint64_t idiv(struct sux *cpu, uint64_t dst, uint64_t value, uint64_t *rem, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; + int64_t sum = dst/value; + *rem = dst % value; + setflag(sum == 0, Z); + setflag(sum >> (msb-1), N); + return sum; +} + +static /*inline*/ uint64_t neg(struct sux *cpu, uint64_t value, uint8_t size, uint8_t thread) { + size = (size > 8) ? 8 : size; + uint8_t msb = size*8; + value = -value; + setflag(value == 0, Z); + setflag(value >> (msb-1), N); + return value; +} + +static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t size, uint8_t *op_type, uint8_t *op_id, uint8_t thread) { + uint64_t dst = 0; + uint64_t src = 0; + uint64_t rem = 0; + uint64_t address[2] = {0, 0}; + int isdiv = 0; + operand op[2]; + cpu->pc = get_ortho_addr(cpu, prefix, cpu->pc, op, address, op_type, op_id, 1, 1, thread); + if (op[1].type) { + src = read_value(cpu, 0, op[1].value, size, 1, 1); + } else { + switch (op[1].id) { + case REG_A : src = cpu->a; break; + case REG_B : src = cpu->b; break; + case REG_X : src = cpu->x; break; + case REG_Y : src = cpu->y; break; + case REG_E : src = cpu->e; break; + case REG_C : src = cpu->c; break; + case REG_D : src = cpu->d; break; + case REG_S : src = cpu->s; break; + case REG_F : src = cpu->f; break; + case REG_SP : src = cpu->sp; break; + case REG_BP : src = cpu->bp; break; + case REG_R11: src = cpu->r11; break; + case REG_R12: src = cpu->r12; break; + case REG_R13: src = cpu->r13; break; + case REG_R14: src = cpu->r14; break; + case REG_R15: src = cpu->r15; break; + } + } + if (op[0].type) { + dst = read_value(cpu, 0, op[0].value, size, 1, 1); + } else { + switch (op[0].id) { + case REG_A : dst = cpu->a; break; + case REG_B : dst = cpu->b; break; + case REG_X : dst = cpu->x; break; + case REG_Y : dst = cpu->y; break; + case REG_E : dst = cpu->e; break; + case REG_C : dst = cpu->c; break; + case REG_D : dst = cpu->d; break; + case REG_S : dst = cpu->s; break; + case REG_F : dst = cpu->f; break; + case REG_SP : dst = cpu->sp; break; + case REG_BP : dst = cpu->bp; break; + case REG_R11: dst = cpu->r11; break; + case REG_R12: dst = cpu->r12; break; + case REG_R13: dst = cpu->r13; break; + case REG_R14: dst = cpu->r14; break; + case REG_R15: dst = cpu->r15; break; + } + } + switch (opcode) { + case ORTHO_2OP(MNG): + if (getflag(N)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MPO): + if (!getflag(N)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MCS): + if (getflag(C)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MCC): + if (!getflag(C)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MEQ): + if (getflag(Z)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MNE): + if (!getflag(Z)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MVS): + if (getflag(V)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MVC): + if (!getflag(V)) { + dst = mov(cpu, src, size, thread); + } + break; + case ORTHO_2OP(MOV): dst = mov(cpu, src, size, thread); break; + case ORTHO_2OP(ADC): dst = adc(cpu, dst, src, getflag(C), (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(SBC): dst = adc(cpu, dst, ~src, getflag(C), (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(ADD): dst = adc(cpu, dst, src, 0, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(SUB): dst = adc(cpu, dst, ~src, 1, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(AND): dst = and(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(OR ): dst = or(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(XOR): dst = xor(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(LSL): dst = lsl(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(LSR): dst = lsr(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(ROL): dst = rol(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(ROR): dst = ror(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(ASR): dst = asr(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(MUL): dst = mul(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(DIV): dst = divd(cpu, dst, src, &rem, (op[0].type) ? size+1 : 8, thread); isdiv = 1; break; + case ORTHO_2OP(CMP): adc(cpu, dst, ~src, 1, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(PCN): dst = popcnt(cpu, src, thread); break; + case ORTHO_2OP(IML): dst = imul(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(IDV): dst = idiv(cpu, dst, src, &rem, (op[0].type) ? size+1 : 8, thread); isdiv = 1; break; + case ORTHO_2OP(LEA): + do { + uint64_t address; + uint64_t mask; + if (op[1].type) { + uint8_t addr_size = get_ortho_addrsize(prefix, op[1].id); + size = (!size) ? addr_size : size; + address = op[1].value; + } else { + address = src; + } + mask = (-(uint64_t)1 >> ((7 - size) * 8)); + dst = (address & mask); + } while (0); + break; + case ORTHO_1OP(PEA): + do { + uint64_t address = (op[0].type) ? op[0].value : dst; + push(cpu, address, 7, thread); + } while (0); + break; + case ORTHO_1OP(INC): dst = inc_dec(cpu, dst, size, 1, thread); break; + case ORTHO_1OP(DEC): dst = inc_dec(cpu, dst, size, 0, thread); break; + case ORTHO_1OP(PSH): push(cpu, dst, size, thread); break; + case ORTHO_1OP(PUL): dst = pull(cpu, size, thread); break; + case ORTHO_1OP(NOT): dst = ~dst; break; + case ORTHO_1OP(CLZ): dst = lbcnt(cpu, src, 0, size, thread); break; + case ORTHO_1OP(CLO): dst = lbcnt(cpu, src, 1, size, thread); break; + case ORTHO_1OP(SWP): dst = swap(cpu, dst, size, thread); break; + case ORTHO_1OP(NEG): dst = neg(cpu, dst, size, thread); break; + case ORTHO_1CC(SET, NG): dst = set(cpu, getflag(N), thread); break; + case ORTHO_1CC(SET, PO): dst = set(cpu, !getflag(N), thread); break; + case ORTHO_1CC(SET, CS): dst = set(cpu, getflag(C), thread); break; + case ORTHO_1CC(SET, CC): dst = set(cpu, !getflag(C), thread); break; + case ORTHO_1CC(SET, EQ): dst = set(cpu, getflag(Z), thread); break; + case ORTHO_1CC(SET, NE): dst = set(cpu, !getflag(Z), thread); break; + case ORTHO_1CC(SET, VS): dst = set(cpu, getflag(V), thread); break; + case ORTHO_1CC(SET, VC): dst = set(cpu, !getflag(V), thread); break; + + } + + if (op[0].type) { + write_value(cpu, dst, op[0].value, size, 1, 1); + } else { + switch (op[0].id) { + case REG_A : cpu->a = dst; break; + case REG_B : cpu->b = dst; break; + case REG_X : cpu->x = dst; break; + case REG_Y : cpu->y = dst; break; + case REG_E : cpu->e = dst; break; + case REG_C : cpu->c = dst; break; + case REG_D : cpu->d = dst; break; + case REG_S : cpu->s = dst; break; + case REG_F : cpu->f = dst; break; + case REG_SP : cpu->sp = dst; break; + case REG_BP : cpu->bp = dst; break; + case REG_R11: cpu->r11 = dst; break; + case REG_R12: cpu->r12 = dst; break; + case REG_R13: cpu->r13 = dst; break; + case REG_R14: cpu->r14 = dst; break; + case REG_R15: cpu->r15 = dst; break; + } + } + if (isdiv) { + if (op[1].type) { + write_value(cpu, rem, op[1].value, size, 1, 1); + } else { + switch (op[1].id) { + case REG_A : cpu->a = rem; break; + case REG_B : cpu->b = rem; break; + case REG_X : cpu->x = rem; break; + case REG_Y : cpu->y = rem; break; + case REG_E : cpu->e = rem; break; + case REG_C : cpu->c = rem; break; + case REG_D : cpu->d = rem; break; + case REG_S : cpu->s = rem; break; + case REG_F : cpu->f = rem; break; + case REG_SP : cpu->sp = rem; break; + case REG_BP : cpu->bp = rem; break; + case REG_R11: cpu->r11 = rem; break; + case REG_R12: cpu->r12 = rem; break; + case REG_R13: cpu->r13 = rem; break; + case REG_R14: cpu->r14 = rem; break; + case REG_R15: cpu->r15 = rem; break; + } + } + } +} + +static /*inline*/ void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint64_t value, uint64_t address, uint8_t size, uint8_t thread) { + uint8_t addr_size = get_addrsize(prefix, ext_optype[opcode]); uint8_t tmp = 0; switch (opcode) { case LEA_AB : /* LEA Absolute. */ @@ -637,7 +1108,12 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case LEA_IN : /* LEA Indirect. */ case LEA_IX : /* LEA Indexed Idirect. */ case LEA_IY : /* LEA Indirect Indexed. */ - cpu->e = address.u64; + do { + size = (!size) ? addr_size : size; + uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8)); + cpu->e = (address & mask); + //cpu->e = load(cpu, address, 0, size, thread); + } while (0); break; case PEA_AB : /* PEA Absolute. */ case PEA_AX : /* PEA Absolute, Indexed with X. */ @@ -651,41 +1127,41 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case PEA_IN : /* PEA Indirect. */ case PEA_IX : /* PEA Indexed Idirect. */ case PEA_IY : /* PEA Indirect Indexed. */ - push(cpu, address.u64, 7, thread); + push(cpu, address, 7, thread); break; case ADD_IMM: /* ADD Immediate. */ case ADD_AB : /* ADD Absolute. */ case ADD_Z : /* ADD Zero Matrix. */ case ADD_E : /* ADD E Indirect. */ - cpu->a = adc(cpu, cpu->a, value.u64, 0, thread); + cpu->a = adc(cpu, cpu->a, value, 0, 8, thread); break; case SUB_IMM: /* SUB Immediate. */ case SUB_AB : /* SUB Absolute. */ case SUB_Z : /* SUB Zero Matrix. */ case SUB_E : /* SUB E Indirect. */ - cpu->a = adc(cpu, cpu->a, ~value.u64, 1, thread); + cpu->a = adc(cpu, cpu->a, ~value, 1, 8, thread); break; case ADE_IMM: /* ADE Immediate. */ case ADE_AB : /* ADE Absolute. */ case ADE_Z : /* ADE Zero Matrix. */ - cpu->e = adc(cpu, cpu->e, value.u64, 0, thread); + cpu->e = adc(cpu, cpu->e, value, 0, 8, thread); break; case SBE_IMM: /* SBE Immediate. */ case SBE_AB : /* SBE Absolute. */ case SBE_Z : /* SBE Zero Matrix. */ - cpu->e = adc(cpu, cpu->e, ~value.u64, 1, thread); + cpu->e = adc(cpu, cpu->e, ~value, 1, 8, thread); break; case ADS_IMM: /* ADS Immediate. */ case ADS_AB : /* ADS Absolute. */ case ADS_Z : /* ADS Zero Matrix. */ case ADS_E : /* ADS E Indirect. */ - cpu->sp = adc(cpu, cpu->sp, value.u64, 0, thread); + cpu->sp = adc(cpu, cpu->sp, value, 0, 8, thread); break; case SBS_IMM: /* SBS Immediate. */ case SBS_AB : /* SBS Absolute. */ case SBS_Z : /* SBS Zero Matrix. */ case SBS_E : /* SBS E Indirect. */ - cpu->sp = adc(cpu, cpu->sp, ~value.u64, 1, thread); + cpu->sp = adc(cpu, cpu->sp, ~value, 1, 8, thread); break; case NOT_A : /* NOT Accumulator. */ cpu->a = ~cpu->a; @@ -693,7 +1169,7 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case NOT_AB: /* NOT Absolute. */ case NOT_Z : /* NOT Zero Matrix. */ case NOT_E : /* NOT E Indirect. */ - not_mem(cpu, address.u64, prefix, thread); + not_mem(cpu, address, prefix, thread); break; case LLM_AB: /* LLM Absolute. */ case LLM_Z : /* LLM Zero Matrix. */ @@ -727,14 +1203,14 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case ARM_Z : case ARM_E : tmp = 4; break; } - bitshft_mem(cpu, tmp, cpu->b, address.u64, prefix, thread); + bitshft_mem(cpu, tmp, cpu->b, address, prefix, thread); break; case PHE_IMP: push(cpu, cpu->e, size, thread); break; /* PusH E register. */ - case PLE_IMP: pull(cpu, size, thread); break; /* PuLl E register. */ + case PLE_IMP: cpu->e = pull(cpu, size, thread); break; /* PuLl E register. */ case CPE_IMM: /* CPE Immediate. */ case CPE_AB : /* CPE Absolute. */ case CPE_Z : /* CPE Zero Matrix. */ - adc(cpu, cpu->e, ~value.u64, 1, thread); + adc(cpu, cpu->e, ~value, 1, 8, thread); break; case ICE_AB : /* ICE Absolute. */ case ICE_Z : /* ICE Zero Matrix. */ @@ -744,7 +1220,7 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case LDS_AB : /* LDS Absolute. */ case LDS_Z : /* LDS Zero Matrix. */ case LDS_E : /* LDS E Indirect. */ - cpu->sp = load(cpu, cpu->sp, address.u64, size, thread); + cpu->sp = load(cpu, cpu->sp, address, size, thread); break; case DEE_IMP: cpu->e = idr(cpu, cpu->e, 0, thread); break; /* DEcrement E register. */ case INE_IMP: cpu->e = idr(cpu, cpu->e, 1, thread); break; /* INcrement E register. */ @@ -753,16 +1229,16 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case STS_AB: /* STS Absolute. */ case STS_Z : /* STS Zero Matrix. */ case STS_E : /* STS E Indirect. */ - store(cpu, address.u64, cpu->sp, prefix, thread); + store(cpu, address, cpu->sp, prefix, thread); break; case STE_AB: /* STE Absolute. */ case STE_Z : /* STE Zero Matrix. */ - store(cpu, address.u64, cpu->sp, prefix, thread); + store(cpu, address, cpu->sp, prefix, thread); break; case STZ_AB: /* STZ Absolute. */ case STZ_Z : /* STZ Zero Matrix. */ case STZ_E : /* STZ E Indirect. */ - store(cpu, address.u64, 0, prefix, thread); + store(cpu, address, 0, prefix, thread); break; case SCO_IMM: /* SCO Immediate. */ case SCO_AB : /* SCO Absolute. */ @@ -777,17 +1253,17 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case CLZ_AB: /* CLZ Absolute. */ case CLZ_Z : /* CLZ Zero Matrix. */ case CLZ_E : /* CLZ E Indirect. */ - cpu->a = lbcnt(cpu, value.u64, 0, size, thread); + cpu->a = lbcnt(cpu, value, 0, size, thread); break; case CLO_AB: /* CLO Absolute. */ case CLO_Z : /* CLO Zero Matrix. */ case CLO_E : /* CLO E Indirect. */ - cpu->a = lbcnt(cpu, value.u64, 1, size, thread); + cpu->a = lbcnt(cpu, value, 1, size, thread); break; case BIT_AB: /* BIT Absolute. */ case BIT_Z : /* BIT Zero Matrix. */ case BIT_E : /* BIT E Indirect. */ - bit_test(cpu, cpu->a, value.u64, thread); + bit_test(cpu, cpu->a, value, thread); break; case MMV_IMP: /* Memory MoVe. */ cpu->b = mem_move(cpu, cpu->b, cpu->x, cpu->y, 0, size, thread); @@ -798,141 +1274,141 @@ static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix case SWP_AB: /* SWP Absolute. */ case SWP_Z : /* SWP Zero Matrix. */ case SWP_E : /* SWP E Indirect. */ - swap_mem(cpu, address.u64, size, thread); + swap_mem(cpu, address, size, thread); break; case PCN_AB: /* PCN Absolute. */ case PCN_Z : /* PCN Zero Matrix. */ case PCN_E : /* PCN E Indirect. */ - cpu->a = popcnt(cpu, value.u64, thread); + cpu->a = popcnt(cpu, value, thread); break; case REP_REL: /* REP Relative. */ if (cpu->b != 0) { cpu->b--; - cpu->pc = address.u64; + cpu->pc = address; } break; case REQ_REL: /* REQ Relative. */ if (cpu->b != 0 && getflag(Z)) { cpu->b--; - cpu->pc = address.u64; + cpu->pc = address; } break; case RNE_REL: /* RNE Relative. */ if (cpu->b != 0 && !getflag(Z)) { cpu->b--; - cpu->pc = address.u64; + cpu->pc = address; } break; case LNG_IMM: /* LNG Immediate. */ case LNG_E : /* LNG E Indirect. */ if (getflag(N)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case LPO_IMM: /* LPO Immediate. */ case LPO_E : /* LPO E Indirect. */ if (!getflag(N)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case LCS_IMM: /* LCS Immediate. */ case LCS_E : /* LCS E Indirect. */ if (getflag(C)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case LCC_IMM: /* LCC Immediate. */ case LCC_E : /* LCC E Indirect. */ if (!getflag(C)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case LEQ_IMM: /* LEQ Immediate. */ case LEQ_E : /* LEQ E Indirect. */ if (getflag(Z)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case LNE_IMM: /* LNE Immediate. */ case LNE_E : /* LNE E Indirect. */ if (!getflag(Z)) { - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); } break; case SNG_E : /* SNG E Indirect. */ if (getflag(N)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; case SPO_E : /* SPO E Indirect. */ if (!getflag(N)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; case SCS_E : /* SCS E Indirect. */ if (getflag(C)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; case SCC_E : /* SCC E Indirect. */ if (!getflag(C)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; case SEQ_E : /* SEQ E Indirect. */ if (getflag(Z)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; case SNE_E : /* SNE E Indirect. */ if (!getflag(Z)) { - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); } break; } } -static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, union reg value, union reg address, uint8_t size, uint8_t thread) { +static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint64_t value, uint64_t address, uint8_t size, uint8_t thread) { uint64_t *rem = 0; switch (opcode) { case CPS_IMP: /* Clear Processor Status. */ cpu->ps.u8[thread] = 0; break; case ADC_B: /* ADC B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case ADC_IMM: /* ADC Immediate. */ case ADC_AB: /* ADC Absolute. */ case ADC_Z: /* ADC Zero Matrix. */ - cpu->a = adc(cpu, cpu->a, value.u64, getflag(C), thread); + cpu->a = adc(cpu, cpu->a, value, 8, getflag(C), thread); break; case PHP_IMP: push(cpu, cpu->ps.u8[thread], 0, thread); break; /* PusH Processor status to stack. */ case PHA_IMP: push(cpu, cpu->a , size, thread); break; /* PusH Accumulator to stack. */ case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */ case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */ case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */ - case TAY_IMP: cpu->y = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */ - case TAX_IMP: cpu->x = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */ - case TYX_IMP: cpu->x = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to X. */ - case TYA_IMP: cpu->a = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to Accumulator. */ - case TXA_IMP: cpu->a = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Accumulator. */ - case TXY_IMP: cpu->y = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Y. */ - case TAB_IMP: cpu->b = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to B. */ - case TSX_IMP: cpu->x = transfer(cpu, cpu->sp, value.u64, thread); break; /* Transfer Stack pointer to X. */ - case TBA_IMP: cpu->a = transfer(cpu, cpu->b , value.u64, thread); break; /* Transfer B to Accumulator. */ - case TXS_IMP: cpu->sp = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Stack pointer. */ + case TAY_IMP: cpu->y = transfer(cpu, cpu->a , value, thread); break; /* Transfer Accumulator to Y. */ + case TAX_IMP: cpu->x = transfer(cpu, cpu->a , value, thread); break; /* Transfer Accumulator to Y. */ + case TYX_IMP: cpu->x = transfer(cpu, cpu->y , value, thread); break; /* Transfer Y to X. */ + case TYA_IMP: cpu->a = transfer(cpu, cpu->y , value, thread); break; /* Transfer Y to Accumulator. */ + case TXA_IMP: cpu->a = transfer(cpu, cpu->x , value, thread); break; /* Transfer X to Accumulator. */ + case TXY_IMP: cpu->y = transfer(cpu, cpu->x , value, thread); break; /* Transfer X to Y. */ + case TAB_IMP: cpu->b = transfer(cpu, cpu->a , value, thread); break; /* Transfer Accumulator to B. */ + case TSX_IMP: cpu->x = transfer(cpu, cpu->sp, value, thread); break; /* Transfer Stack pointer to X. */ + case TBA_IMP: cpu->a = transfer(cpu, cpu->b , value, thread); break; /* Transfer B to Accumulator. */ + case TXS_IMP: cpu->sp = transfer(cpu, cpu->x , value, thread); break; /* Transfer X to Stack pointer. */ case BRA_REL: /* BRA Relative. */ case JMP_AB: /* JMP Absolute. */ case JMP_Z: /* JMP Zero Matrix. */ case JMP_IN: /* JMP Indirect. */ - cpu->pc = address.u64; + cpu->pc = address; break; case SBC_B: /* SBC B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case SBC_IMM: /* SBC Immediate. */ case SBC_AB: /* SBC Absolute. */ case SBC_Z: /* SBC Zero Matrix. */ - cpu->a = adc(cpu, cpu->a, ~value.u64, getflag(C), thread); + cpu->a = adc(cpu, cpu->a, ~value, 8, getflag(C), thread); break; case PLP_IMP: cpu->ps.u8[thread] = pull(cpu, 0, thread); break; /* PuLl Processor status from stack. */ case PLA_IMP: cpu->a = pull(cpu, size, thread); break; /* PuLl Accumulator from stack. */ @@ -941,53 +1417,53 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case PLX_IMP: cpu->x = pull(cpu, size, thread); break; /* PuLl X register from stack. */ break; case AND_B: /* AND B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case AND_IMM: /* AND Immediate. */ case AND_AB: /* AND Absolute. */ case AND_Z: /* AND Zero Matrix. */ - cpu->a = and(cpu, cpu->a, value.u64, thread); + cpu->a = and(cpu, cpu->a, value, 8, thread); break; case BPO_REL: /* BPO Relative. */ if (!getflag(N)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case ORA_B: /* ORA B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case ORA_IMM: /* ORA Immediate. */ case ORA_AB: /* ORA Absolute. */ case ORA_Z: /* ORA Zero Matrix. */ - cpu->a = or(cpu, cpu->a, value.u64, thread); + cpu->a = or(cpu, cpu->a, value, 8, thread); break; case SEI_IMP: /* SEt Interrupt. */ setflag(1, I); break; case BNG_REL: /* BNG Relative. */ if (getflag(N)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case XOR_B: /* XOR B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case XOR_IMM: /* XOR Immediate. */ case XOR_AB: /* XOR Absolute. */ case XOR_Z: /* XOR Zero Matrix. */ - cpu->a = xor(cpu, cpu->a, value.u64, thread); + cpu->a = xor(cpu, cpu->a, value, 8, thread); break; case CLI_IMP: /* CLear Interrupt. */ setflag(0, I); break; case BCS_REL: /* BCS Relative. */ if (getflag(C)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case LSL_B: /* LSL B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case LSL_IMM: /* LSL Immediate. */ case LSL_AB: /* LSL Absolute. */ case LSL_Z: /* LSL Zero Matrix. */ - cpu->a = lsl(cpu, cpu->a, value.u64, 8, thread); + cpu->a = lsl(cpu, cpu->a, value, 8, thread); break; case SEC_IMP: /* SEt Carry flag.*/ setflag(1, C); @@ -999,17 +1475,17 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case STA_IN: /* STA Indirect. */ case STA_IX: /* STA Indexed Indirect. */ case STA_IY: /* STA Indirect Indexed. */ - store(cpu, address.u64, cpu->a, prefix, thread); + store(cpu, address, cpu->a, prefix, thread); break; case STY_AB: /* STY Absolute. */ case STY_Z: /* STY Zero Matrix. */ case STY_IN: /* STY Indirect. */ - store(cpu, address.u64, cpu->y, prefix, thread); + store(cpu, address, cpu->y, prefix, thread); break; case STX_AB: /* STX Absolute. */ case STX_Z: /* STX Zero Matrix. */ case STX_IN: /* STX Indirect. */ - store(cpu, address.u64, cpu->x, prefix, thread); + store(cpu, address, cpu->x, prefix, thread); break; case STB_AB: /* STB Absolute. */ case STB_Z: /* STB Zero Matrix. */ @@ -1018,26 +1494,26 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case STB_IN: /* STB Indirect. */ case STB_IX: /* STB Indexed Indirect. */ case STB_IY: /* STB Indirect Indexed. */ - store(cpu, address.u64, cpu->b, prefix, thread); + store(cpu, address, cpu->b, prefix, thread); break; case BCC_REL: /* BCC Relative. */ if (!getflag(C)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case LSR_B: /* LSR B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case LSR_IMM: /* LSR Immediate. */ case LSR_AB: /* LSR Absolute. */ case LSR_Z: /* LSR Zero Matrix. */ - cpu->a = lsr(cpu, cpu->a, value.u64, 8, thread); + cpu->a = lsr(cpu, cpu->a, value, 8, thread); break; case ASR_B: /* ASR B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case ASR_IMM: /* ASR Immediate. */ case ASR_AB: /* ASR Absolute. */ case ASR_Z: /* ASR Zero Matrix. */ - cpu->a = asr(cpu, cpu->a, value.u64, 8, thread); + cpu->a = asr(cpu, cpu->a, value, 8, thread); break; case CLC_IMP: /* CLear Carry flag. */ setflag(0, C); @@ -1050,7 +1526,7 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case LDB_IN: /* LDB Indirect. */ case LDB_IX: /* LDB Indexed Indirect. */ case LDB_IY: /* LDB Indirect Indexed. */ - cpu->b = load(cpu, cpu->b, address.u64, size, thread); + cpu->b = load(cpu, cpu->b, address, size, thread); break; case LDA_IMM: /* LDA Immediate. */ case LDA_AB: /* LDA Absolute. */ @@ -1060,59 +1536,59 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case LDA_IN: /* LDA Indirect. */ case LDA_IX: /* LDA Indexed Indirect. */ case LDA_IY: /* LDA Indirect Indexed. */ - cpu->a = load(cpu, cpu->a, address.u64, size, thread); + cpu->a = load(cpu, cpu->a, address, size, thread); break; case LDY_IMM: /* LDY Immediate. */ case LDY_AB: /* LDY Absolute. */ case LDY_Z: /* LDY Zero Matrix. */ case LDY_IN: /* LDY Indirect. */ - cpu->y = load(cpu, cpu->y, address.u64, size, thread); + cpu->y = load(cpu, cpu->y, address, size, thread); break; case LDX_IMM: /* LDX Immediate. */ case LDX_AB: /* LDX Absolute. */ case LDX_Z: /* LDX Zero Matrix. */ case LDX_IN: /* LDX Indirect. */ - cpu->x = load(cpu, cpu->x, address.u64, size, thread); + cpu->x = load(cpu, cpu->x, address, size, thread); break; case BEQ_REL: /* BEQ Relative. */ if (getflag(Z)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case ROL_B: /* ROL B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case ROL_IMM: /* ROL Immediate. */ case ROL_AB: /* ROL Absolute. */ case ROL_Z: /* ROL Zero Matrix. */ - cpu->a = rol(cpu, cpu->a, value.u64, 8, thread); + cpu->a = rol(cpu, cpu->a, value, 8, thread); break; case BNE_REL: /* BNE Relative. */ if (!getflag(Z)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case ROR_B: /* ROR B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case ROR_IMM: /* ROR Immediate. */ case ROR_AB: /* ROR Absolute. */ case ROR_Z: /* ROR Zero Matrix. */ - cpu->a = ror(cpu, cpu->a, value.u64, 8, thread); + cpu->a = ror(cpu, cpu->a, value, 8, thread); break; case BVS_REL: /* BVS Relative. */ if (getflag(V)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case MUL_B: /* MUL B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case MUL_IMM: /* MUL Immediate. */ case MUL_AB: /* MUL Absolute. */ case MUL_Z: /* MUL Zero Matrix. */ - cpu->a = mul(cpu, cpu->a, value.u64, thread); + cpu->a = mul(cpu, cpu->a, value, 8, thread); break; case BVC_REL: /* BVC Relative. */ if (!getflag(V)) { - cpu->pc = address.u64; + cpu->pc = address; } break; case DIV_B: /* DIV B register. */ @@ -1120,7 +1596,7 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case DIV_AB: /* DIV Absolute. */ case DIV_Z: /* DIV Zero Matrix. */ rem = (opcode != DIV_B) ? &cpu->b : &cpu->x; - cpu->a = divd(cpu, cpu->a, value.u64, rem, thread); + cpu->a = divd(cpu, cpu->a, value, rem, 8, thread); break; case CLV_IMP: /* CLear oVerflow flag. */ setflag(0, V); @@ -1131,27 +1607,27 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case CPB_IN: /* CPB Indirect. */ case CPB_IX: /* CPB Indexed Indirect. */ case CPB_IY: /* CPB Indirect Indexed. */ - adc(cpu, cpu->b, ~value.u64, 1, thread); + adc(cpu, cpu->b, ~value, 1, 8, thread); break; case CMP_B: /* CMP B register. */ - value.u64 = cpu->b; /* Falls Through. */ + value = cpu->b; /* Falls Through. */ case CMP_IMM: /* CMP Immediate. */ case CMP_AB: /* CMP Absolute. */ case CMP_Z: /* CMP Zero Matrix. */ case CMP_IN: /* CMP Indirect. */ case CMP_IX: /* CMP Indexed Indirect. */ case CMP_IY: /* CMP Indirect Indexed. */ - adc(cpu, cpu->a, ~value.u64, 1, thread); + adc(cpu, cpu->a, ~value, 1, 8, thread); break; case CPY_IMM: /* CPY Immediate. */ case CPY_AB: /* CPY Absolute. */ case CPY_Z: /* CPY Zero Matrix. */ - adc(cpu, cpu->y, ~value.u64, 1, thread); + adc(cpu, cpu->y, ~value, 1, 8, thread); break; case CPX_IMM: /* CPX Immediate. */ case CPX_AB: /* CPX Absolute. */ case CPX_Z: /* CPX Zero Matrix. */ - adc(cpu, cpu->x, ~value.u64, 1, thread); + adc(cpu, cpu->x, ~value, 1, 8, thread); break; case INC_IMP: cpu->a = idr(cpu, cpu->a, 1, thread); break; case INB_IMP: cpu->b = idr(cpu, cpu->b, 1, thread); break; @@ -1165,11 +1641,11 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi case JSR_AB: /* Jump to SubRoutine. */ case JSR_Z: /* JSR Zero Matrix. */ push(cpu, cpu->pc, (size) ? size : 7, thread); - cpu->pc = address.u64; + cpu->pc = address; break; case INC_AB: /* INC Absolute. */ case INC_Z: /* INC Zero Matrix. */ - idm(cpu, address.u64, prefix, 1, thread); + idm(cpu, address, prefix, 1, thread); break; case NOP_IMP: /* No OPeration. */ break; @@ -1181,7 +1657,7 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi break; case DEC_AB: /* DEC Absolute. */ case DEC_Z: /* DEC Zero Matrix. */ - idm(cpu, address.u64, prefix, 0, thread); + idm(cpu, address, prefix, 0, thread); break; case BRK_IMP: /* BReaK. */ case WAI_IMP: /* WAit for Interrupt. */ @@ -1196,12 +1672,16 @@ static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefi push(cpu, cpu->pc, 7, thread); push(cpu, cpu->ps.u8[thread], 0, thread); setflag(1, I); - value.u64 = read_value(cpu, 0, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7, 1, 0); + value = read_value(cpu, 0, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7, 1, 0); if (opcode == WAI_IMP) { kbd_rdy &= (uint8_t)~(1 << thread); } - cpu->pc = value.u64; + cpu->pc = value; default: break; } } + +#undef ORTHO_1CC +#undef ORTHO_1OP +#undef ORTHO_2OP diff --git a/test/ortho.s b/test/ortho.s new file mode 100644 index 0000000..bc70d3d --- /dev/null +++ b/test/ortho.s @@ -0,0 +1,35 @@ +.org 0 +count: + .res 8 +.org $40000 +mem: + .res 256 + +.org $8000 +reset: + cps + lds.d #$3FFFF + and #0 + tay + xor b, b + xor.q count, count +; cmp.q (count), y + cmp.qo (count), y + lea.o (count), y + lea mem +loop: + inc b + inc.q count +; mov.q e, count + mov (b+e), b + mov a, (b+e) + bra loop + +.org $FFC0 +.qword reset + +a +;.org reset +;v +;q +d diff --git a/test/struct.s b/test/struct.s index 33de1f1..f8dd71c 100644 --- a/test/struct.s +++ b/test/struct.s @@ -57,6 +57,12 @@ ass .word .endstruct +.struct token + next .byte + val .byte + id .byte + +.endstruct .org 0 @@ -68,6 +74,7 @@ lda #lol.oof ldb #lol.asd.aa.lol ldx #lol.asd.aa.why ldy #lol.why + a ;l a ;v -- cgit v1.2.3-13-gbd6f