← index
PSP.Homebrew/apps/atariVM/icode.c
Source: PSP.Homebrew/apps/atariVM/icode.c
#include "icode.h"

#include "stack.h"


const char *op_array[] = { 0, "adc", "and", "asl", "bcc", "bcs", "beq", "bit", "bmi", "bne", "bpl", "brk", "bvc",
"bvs", "clc", "cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", "eor", "inc", "int", "inx", "iny", "jmp", "jsr",
"lda", "ldm", "ldx", "ldy","lsr", "nop", "ora", "pha", "php", "pla", "plp", "rol", "ror", "rti", "rts", "sbc", "sec",
"sed", "sei", "sta", "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya", 0 };

// machine code op-codes                

struct machine_code code[] = {
// ADC

{ 0x69, IMMEDIATE, TOK_ADC }, { 0x65, ZEROPAGE, TOK_ADC },
{ 0x75, ZEROPAGE_X, TOK_ADC }, { 0x6D, ABSOULTE, TOK_ADC }, {0x7D, ABSOULTE_X, TOK_ADC }, { 0x79, ABSOULTE_Y, TOK_ADC},
{ 0x61, INDEXED_I, TOK_ADC }, { 0x71, INDIRECT_I, TOK_ADC }, 
// AND

{ 0x29, IMMEDIATE, TOK_AND }, {0x25, ZEROPAGE, TOK_AND}, {0x35, ZEROPAGE_X, TOK_AND}, {0x2D, ABSOULTE, TOK_AND},
{ 0x3D, ABSOULTE_X, TOK_AND }, {0x39, ABSOULTE_Y, TOK_AND }, {0x21, INDEXED_I, TOK_AND}, {0x31, INDIRECT_I, TOK_AND},
// ASL

{ 0x0A, ACCUMULATOR, TOK_ASL }, {0x06, ZEROPAGE, TOK_ASL}, {0x16, ZEROPAGE_X, TOK_ASL}, {0x0E, ABSOULTE, TOK_ASL},
{ 0x1E, ABSOULTE_X, TOK_ASL },
// BCC

{ 0x90, RELATIVE, TOK_BCC},
// BCS

{ 0xB0, RELATIVE, TOK_BCS},
// BEQ

{ 0xF0, RELATIVE, TOK_BEQ},
// BIT

{ 0x24, ZEROPAGE, TOK_BIT}, {0x2C, ABSOULTE, TOK_BIT},
// BMI

{ 0x30, RELATIVE, TOK_BMI},
// BNE

{ 0xD0, RELATIVE, TOK_BNE},
// BPL

{ 0x10, RELATIVE, TOK_BPL},
// BRK

{ 0x00, IMPLIED, TOK_BRK},
// BVC

{ 0x50, RELATIVE, TOK_BVC},
// BVS

{ 0x70, RELATIVE, TOK_BVC},
// CLC

{ 0x18, IMPLIED, TOK_CLC},
// CLD

{ 0xD8, IMPLIED, TOK_CLD},
// CLI

{ 0x58, IMPLIED, TOK_CLI},
// CLV

{ 0xB8, IMPLIED, TOK_CLV},
// CMP

{ 0xC9, IMMEDIATE, TOK_CMP}, {0xC5, ZEROPAGE, TOK_CMP}, { 0xD5, ZEROPAGE_X, TOK_CMP }, { 0xCD, ABSOULTE, TOK_CMP},
{ 0xDD, ABSOULTE_X, TOK_CMP}, {0xD9, ABSOULTE_Y, TOK_CMP}, {0xD9, ABSOULTE_Y, TOK_CMP}, { 0xC1, INDEXED_I, TOK_CMP},
{ 0xD1, INDIRECT_I, TOK_CMP},
// CPX

{ 0xE0, IMMEDIATE, TOK_CPX}, {0xE4, ZEROPAGE, TOK_CPX}, {0xEC, ABSOULTE, TOK_CPX},
// CPY

{ 0xC0, IMMEDIATE, TOK_CPY}, {0xC4, ZEROPAGE, TOK_CPY}, {0xCC, ABSOULTE, TOK_CPY},
// DEC

{ 0xC6, ZEROPAGE, TOK_DEC}, {0xD6, ZEROPAGE_X, TOK_DEC}, {0xCE, ABSOULTE, TOK_DEC}, {0xDE, ABSOULTE_X, TOK_DEC},
// DEX

{ 0xCA, IMPLIED, TOK_DEX},
// DEY

{ 0x88, IMPLIED, TOK_DEY},
// EOR

{ 0x49, IMMEDIATE, TOK_EOR}, {0x45, ZEROPAGE, TOK_EOR}, {0x55, ZEROPAGE_X, TOK_EOR}, {0x4D, ABSOULTE, TOK_EOR},
{ 0x5D, ABSOULTE_X, TOK_EOR}, {0x59, ABSOULTE_Y, TOK_EOR}, {0x41, INDEXED_I, TOK_EOR}, {0x51, INDIRECT_I, TOK_EOR},
// INC

{0xE6, ZEROPAGE, TOK_INC}, {0xF6, ZEROPAGE_X, TOK_INC}, {0xEE, ABSOULTE, TOK_INC}, {0xFE, ABSOULTE_X, TOK_INC},
// INX

{0xE8, IMPLIED, TOK_INX},
// INY

{0xC8, IMPLIED, TOK_INY},
// JMP

{0x4C, ABSOULTE, TOK_JMP}, {0x6C, INDIRECT, TOK_JMP},
// JSR

{0x20, ABSOULTE, TOK_JSR},
// LDA 

{ 0xA9, IMMEDIATE, TOK_LDA}, {0xA5, ZEROPAGE, TOK_LDA}, {0xB5, ZEROPAGE_X, TOK_LDA}, {0xAD, ABSOULTE, TOK_LDA},
{ 0xBD, ABSOULTE_X, TOK_LDA}, {0xB9, ABSOULTE_Y, TOK_LDA}, {0xA1, INDEXED_I, TOK_LDA}, {0xB1, INDIRECT_I, TOK_LDA},
// LDX

{0xA2, IMMEDIATE, TOK_LDX}, {0xA6, ZEROPAGE, TOK_LDX}, {0xB6, ZEROPAGE_Y, TOK_LDX}, {0xAE, ABSOULTE, TOK_LDX},
{0xA1, INDEXED_I, TOK_LDX},{0xB1, INDIRECT_I, TOK_LDX},
// LDY

{0xA0, IMMEDIATE, TOK_LDY}, {0xA4, ZEROPAGE, TOK_LDY}, {0xB4, ZEROPAGE_X, TOK_LDY}, {0xAC, ABSOULTE, TOK_LDY},
{0xBC, ABSOULTE_X, TOK_LDY}, 
// LSR

{0x4A, ACCUMULATOR, TOK_LSR}, {0x46, ZEROPAGE, TOK_LSR}, {0x56, ZEROPAGE_X, TOK_LSR}, {0x4E, ABSOULTE, TOK_LSR},
{0x5E, ABSOULTE_X, TOK_LSR},
// NOP

{0xEA, IMPLIED, TOK_NOP},
// ORA

{0x09, IMMEDIATE, TOK_ORA}, {0x05, ZEROPAGE, TOK_ORA}, {0x15, ZEROPAGE_X, TOK_ORA}, {0x0D, ABSOULTE, TOK_ORA},
{0x1D, ABSOULTE_X, TOK_ORA}, {0x19, ABSOULTE_Y, TOK_ORA}, {0x01, INDEXED_I, TOK_ORA}, {0x11, INDIRECT_I, TOK_ORA},
// PHA

{0x48, IMPLIED, TOK_PHA},
// PHP

{0x08, IMPLIED, TOK_PHP},
// PLA

{0x68, IMPLIED, TOK_PLA},
// PLP

{0x28, IMPLIED, TOK_PLP},
// ROL

{0x21, ACCUMULATOR, TOK_ROL},{0x26, ZEROPAGE, TOK_ROL}, {0x36, ZEROPAGE_X, TOK_ROL}, {0x2E, ABSOULTE, TOK_ROL},
{0x3E, ABSOULTE_X, TOK_ROL},
// ROR 

{0x6A, ACCUMULATOR, TOK_ROR}, {0x66, ZEROPAGE, TOK_ROR}, {0x76, ZEROPAGE_X, TOK_ROR}, {0x6E, ABSOULTE, TOK_ROR},
{0x7E, ABSOULTE_X, TOK_ROR},
// RTI

{0x40, IMPLIED, TOK_RTI},
// RTS

{0x60, IMPLIED, TOK_RTS},
// SBC

{ 0xE9, IMMEDIATE, TOK_SBC}, {0xE5, ZEROPAGE, TOK_SBC}, {0xF5, ZEROPAGE_X, TOK_SBC}, {0xED, ABSOULTE, TOK_SBC},
{ 0xFD, ABSOULTE_X, TOK_SBC}, {0xF9, ABSOULTE_Y, TOK_SBC}, {0xE1, INDEXED_I, TOK_SBC}, {0xF1, INDIRECT_I, TOK_SBC},
// SEC

{0x38, IMPLIED, TOK_SEC},
// SED

{0xF8, IMPLIED, TOK_SED},
// SEI

{0x78, IMPLIED, TOK_SEI},
// STA

{ 0x85, ZEROPAGE, TOK_STA}, {0x95, ZEROPAGE_X, TOK_STA}, {0x8D, ABSOULTE, TOK_STA}, {0x9D, ABSOULTE_X, TOK_STA},
{ 0x99, ABSOULTE_Y, TOK_STA}, {0x81, INDEXED_I, TOK_STA}, {0x91, INDIRECT_I, TOK_STA},
// STX

{ 0x86, ZEROPAGE, TOK_STX}, {0x96,  ZEROPAGE_Y, TOK_STX}, {0x8E, ABSOULTE, TOK_STX},
// STY

{ 0x84, ZEROPAGE, TOK_STY}, {0x94, ZEROPAGE_X, TOK_STY}, {0x8C, ABSOULTE, TOK_STY},
// TAX

{ 0xAA, IMPLIED, TOK_TAX},
// TAY

{ 0xA8, IMPLIED, TOK_TAY},
// TSX

{ 0xBA, IMPLIED, TOK_TSX},
// TXA

{ 0x8A, IMPLIED, TOK_TXA},
// TXS

{ 0x9A, IMPLIED, TOK_TXS},
// TYA

{ 0x98, IMPLIED, TOK_TYA},

0

};



void strlower(char *buf) {
	int i;
	for( i = 0; buf[i] != 0; i++)
		buf[i] = (char)tolower(buf[i]);
}

int trans_opcode(const char *op_code) {
	int i;
	strlower((char*)op_code);
	for(i = 1; op_array[i] != 0; i++)
		if(strcmp(op_array[i], op_code) == 0) {
			return i;
		}
	return TOK_NULL;
}

void build_icode(const char *icode) {

	struct sym_list *lst;
	FILE *fptr = fopen(icode,"w");
	if(!fptr)
		return;

	fwrite(&symbols.count, 1, sizeof(symbols.count), fptr);

	for(lst = symbols.node_list; lst != 0; lst = lst->next) {
		
		if(lst->node->op_code == 0) {
			unsigned int ival = atoi(lst->node->text);
			fwrite(&ival, 1, sizeof(ival), fptr);
		}
		else {
			fwrite(&lst->node->op_code, 1, sizeof(lst->node->op_code), fptr);
		}
	}

	fclose(fptr);
}
unsigned char get_machine_opcode(struct sym_list *l, int *address_mode) {

	int i;
	for(i = 0; code[i].p_code != 0; i++) {


		if(code[i].p_code == l->node->op_code && (code[i].address_mode == *address_mode || code[i].address_mode == IMPLIED || code[i].address_mode == RELATIVE)) {

			*address_mode = code[i].address_mode;
			return code[i].op_code;
		}
	}

	return 0;
}

char *trans_admode(int *mode) {

	switch(*mode) {
		case ACCUMULATOR:
			return "Accumulator";
		case ZEROPAGE:
			return "Zero Page";
		case ZEROPAGE_X:
			return "Zero Page (X)";
		case ZEROPAGE_Y:
			return "Zero Page (Y)";
		case INDEXED_I:
			return "Indexed Indirect";
		case INDIRECT_I:
			return "Indirect Index";
		case ABSOULTE:
			return "*Absoulte*";
		case ABSOULTE_X:
			return "Absoulte X";
		case ABSOULTE_Y:
			return "Absoulte Y";
		case IMMEDIATE:
			return "Immediate";
		case RELATIVE:
			return "Realtive";
		case IMPLIED:
			return "Implied";
	}

	return "Null";
}


/*
void build_c(const char *output) {

	// proccess the symbol table and find all the string variables
	// loop through and print each token to the correct c function
	
	FILE *fptr = fopen(output, "w");
	int index = 0;
	if(!fptr) return;

	fprintf(fptr, "#include<stdio.h>\n#include<stdlib.h>\n#include<SDL.h>\n#include\"ataristd.h\"\n\n");

	for(lst = symbols.node_list; lst != 0; lst = lst->next) {
		if(lst->node->type == TOK_QUOTE) {
			lst->node->index = index;
			fprintf(fptr,"const char *strvar%d = \"%s\";\n", index++,  lst->node->text);
		}

	}
	
	stack_init(&the_stack);
	fprintf(fptr,"extern int SDL_main(int argc, char **argv) {\n\n");
	fprintf(fptr,"SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);\n\n");
		lst = symbols.node_list;
		while(lst != 0) {
			char op_code = lst->node->op_code;
		switch(lst->node->op_code) {
			case TOK_LDA:
			case TOK_LDX:
			case TOK_LDY:
			case TOK_CMP:
			case TOK_CPX:
			case TOK_CPY:
			case TOK_ADC:
			case TOK_AND:
			case TOK_ROR:
			case TOK_ROL:
			case TOK_ASL:
				{
					int op_type = 0, op1 = term(&op_type);
					if(op_type == TOK_HEX) {

						fprintf(fptr, "\n%s(_reg.memory_map[0x%x]);\n", op_array[op_code], op1);

					} else {
						fprintf(fptr, "\n%s(0x%x);\n", op_array[op_code], op1);
					}

				}
				break;
			case TOK_STA:
			case TOK_STY:
			case TOK_STX:
				{
					int op_type = 0, op1 = term(&op_type); 
					fprintf(fptr, "\n%s(0x%x);\n", op_array[op_code], op1);

				}
				break;
			case TOK_INT:
				{
					int op_type = 0, op1 = term(&op_type); 
					fprintf(fptr, "\n%sx(0x%x);\n", op_array[op_code], op1);
					break;
				}
			case TOK_BNE:
				{
					get_next();
					fprintf(fptr, "\nif(_reg.flags[6] == 1)\n");
					fprintf(fptr, "\ngoto %s;\n", lst->node->text);
				}
				break;
			case TOK_JMP:
				{
					get_next();
					fprintf(fptr,"\ngoto %s;\n", lst->node->text);
				}
				break;
			case TOK_JSR:
				{
					get_next();
					fprintf(fptr,"\ngoto %s;\n", lst->node->text);
					stack_push(&the_stack, lst);
				}
				break;
			case TOK_RTS:
				{
					struct sym_list *l = stack_pop(&the_stack);
					if(l) fprintf(fptr,"\ngoto %s\n", l->node->text);
				}
				break;
			case TOK_INX:
			case TOK_INY:
			case TOK_DEX:
			case TOK_DEY:
			case TOK_INC:
			case TOK_DEC:
				{
					fprintf(fptr,"\n%s();\n", op_array[lst->node->op_code]);
				}
				break;
			default:
				{
					if(lst && lst->node->type == TOK_CHAR) {
						fprintf(fptr, "\n%s:\n", lst->node->text);
					}
				}
				break;
				
		
		}

		get_next();

	}

	fprintf(fptr, "\nreturn 0;\n}\n");

	fclose(fptr);

}*/

void build_debug(const char *output) {

	struct sym_list *lst;
	FILE *fptr = fopen(output,"w");
	if(!fptr)
		return;

	fprintf(fptr, "<HTML> <TITLE> Atari 800 Debug Output </TITLE> <BR> ");
	fprintf(fptr, "<TABLE BORDER=2>");
	fprintf(fptr, "<TR> <TH> <b>Machine Instruction <TH> P-code <TH> Mnemoic <TH> Operand <TH> Address Mode</b></TR>");
	for(lst = symbols.node_list; lst != 0; lst = lst->next) {
		struct sym_list *prev = lst;
		if(lst->node->op_code != 0) {
			unsigned char op = 0;
			int address_mode = ABSOULTE;
			fprintf(fptr, "<TR>");
			// translate p-code to machine instruction

			op = get_machine_opcode(lst, &address_mode );
			fprintf(fptr, "<TH> 0x%x", op); // for now

			fprintf(fptr, "<TH> 0x%x ", lst->node->op_code);
			fprintf(fptr, "<TH> %s ", lst->node->text);
			lst = lst->next;
			if(lst && lst->node->op_code == 0)
			fprintf(fptr, "<TH> %s ", lst->node->text);
			else { 
				fprintf(fptr, "<TH> no operand ");
				lst = prev;
			}
			fprintf(fptr, "<TH> %s", trans_admode(&address_mode));
			fprintf(fptr, "</TR>");
		}
		
	}
	fprintf(fptr,"</TABLE>");
	fprintf(fptr, "<BR></HTML>");

	fclose(fptr);
}


unsigned char set_bit(unsigned char bits, unsigned char which) {
	bits |= (1 << which);
	return bits;
}
unsigned char clr_bit(unsigned char bits, unsigned char which) {
	bits &= (1 << which);
	return bits;
}
unsigned char get_bit(unsigned char bits, unsigned char which) {
	return (bits & (1UL << which)) == 0 ? 0 : 1;
}

struct call_back *callbacks = 0;
int cp = 0;

void set_callback(struct call_back *c) {
	callbacks = c;
}

struct call_back *get_callback(unsigned int address) {
	int i;
	struct call_back *callback = callbacks;
	for(i = 0; callback != 0; callback++)
		if(callbacks->address == address)
			return callbacks;
	return 0;
}
// it dont come easy you know it dont come easy