From: Hugo Villeneuve Date: Sat, 15 Feb 2014 06:43:32 +0000 (-0500) Subject: Replace disam.h with opcodes{h,c} X-Git-Tag: v2.0.1~6 X-Git-Url: http://gitweb.hugovil.com/?p=emu8051.git;a=commitdiff_plain;h=fbbb71d6d8aa93bccc87b17408a89432e4b8161c Replace disam.h with opcodes{h,c} Also rename opcode2c.pl -> opcodes2c.pl --- diff --git a/src/common/Makefile.am b/src/common/Makefile.am index aa19efe..267c498 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -7,7 +7,8 @@ AM_CPPFLAGS = \ noinst_LIBRARIES = libemu8051.a libemu8051_a_SOURCES = \ - instructions_8051.c \ + instructions_8051.c instructions_8051.h \ + opcodes.c opcodes.h \ options.c options.h \ log.c log.h \ hexfile.c hexfile.h \ @@ -21,8 +22,9 @@ libemu8051_a_SOURCES = \ reg8051.h # These files are generated automatically by a perl script. -instructions_8051.c instructions_8051.h disasm.h : opcode2c.pl opcodes.lst - ./opcode2c.pl +instructions_8051.c instructions_8051.h opcodes.h opcodes.c : opcodes2c.pl opcodes.lst + @echo " PERL opcodes2c.pl" + @./opcodes2c.pl CLEANFILES = *~ @@ -30,10 +32,9 @@ MAINTAINERCLEANFILES = \ Makefile.in \ instructions_8051.c \ instructions_8051.h \ - disasm.h + opcodes.h \ + opcodes.c EXTRA_DIST = \ - opcode2c.pl \ - opcodes.lst \ - instructions_8051.h \ - disasm.h + opcodes2c.pl \ + opcodes.lst diff --git a/src/common/cpu8051.c b/src/common/cpu8051.c index fb387ee..288c11e 100644 --- a/src/common/cpu8051.c +++ b/src/common/cpu8051.c @@ -20,7 +20,7 @@ #include "memory.h" #include "psw.h" #include "timers.h" -#include "disasm.h" +#include "opcodes.h" #include "options.h" #include "instructions_8051.h" @@ -407,18 +407,11 @@ cpu8051_int_mem_bit_info(uint8_t bit_address, char *text) sprintf(&text[len], ".%X", bit_address); } -/* Get instruction size from opcode */ -int -cpu8051_get_instruction_size(unsigned char opcode) -{ - return instr_size[opcode]; -} - /* Display instruction mnemonic. */ int cpu8051_disasm_mnemonic(unsigned char opcode, char *buf) { - return sprintf(buf, "%s", instr_type_str[instr_type_id[opcode]]); + return sprintf(buf, "%s", opcodes_get_instr_type_str(opcode)); } /* Disasm instruction arguments starting at address into a text string */ @@ -452,8 +445,9 @@ cpu8051_disasm_args(unsigned int address, char *buf) return; } - for (i = 1; i <= instr_arg_type_id[args_table_offset]; i++) { - switch (instr_arg_type_id[args_table_offset + i]) { + for (i = 1; i <= opcodes_get_instr_arg_type_id(args_table_offset); + i++) { + switch (opcodes_get_instr_arg_type_id(args_table_offset + i)) { case ADDR11: { len += sprintf(&buf[len], "%.4XH", ((opcode << 3) & 0xF00) + @@ -517,13 +511,12 @@ cpu8051_disasm_args(unsigned int address, char *buf) break; } default: { - len += sprintf( - &buf[len], "%s", - instr_arg_type_str[instr_arg_type_id[ - args_table_offset + i]]); + len += sprintf(&buf[len], "%s", + opcodes_get_instr_arg_type_str( + args_table_offset + i)); } } - if (i < instr_arg_type_id[args_table_offset]) + if (i < opcodes_get_instr_arg_type_id(args_table_offset)) len += sprintf(&buf[len], ","); } } @@ -541,7 +534,7 @@ cpu8051_disasm(unsigned int address, char *text) len += sprintf(text, " %.4X ", address); opcode = mem_read8(PGM_MEM_ID, address); - inst_size = instr_size[opcode]; + inst_size = opcodes_get_instr_size(opcode); /* Display hex bytes. */ for (i = 0; i < inst_size; i++) diff --git a/src/common/cpu8051.h b/src/common/cpu8051.h index 3348aee..ae17ead 100644 --- a/src/common/cpu8051.h +++ b/src/common/cpu8051.h @@ -74,9 +74,6 @@ cpu8051_run(int instr_count, int (*interface_stop)(void)); void cpu8051_reset(void); -int -cpu8051_get_instruction_size(unsigned char opcode); - int cpu8051_disasm_mnemonic(unsigned char opcode, char *buf); diff --git a/src/common/opcode2c.pl b/src/common/opcode2c.pl deleted file mode 100755 index 23800cc..0000000 --- a/src/common/opcode2c.pl +++ /dev/null @@ -1,855 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (C) 1999 Jonathan St-André -# Copyright (C) 1999 Hugo Villeneuve -# -# This file is released under the GPLv2 - -open INST_DEF, ">instructions_8051.h" or die "Error creating : $!\n"; -open INST_IMP, ">instructions_8051.c" or die "Error creating : $!\n"; -open OPCODELST, "opcodes.lst" or die "Error opening : $!\n"; -open DISASM_H, ">disasm.h" or die "Error creating : $!\n"; - -# Write GPL license -# Argument 0 is file descriptor -sub write_header -{ - my $fd = $_[0]; - - print $fd " *\n"; - print $fd " * Do not modify this file directly, as it was created by opcode2c.pl\n"; - print $fd " * Any modifications made directly to this file will be lost.\n"; - print $fd " *\n"; - print $fd " * Copyright (C) 1999 Jonathan St-André\n"; - print $fd " * Copyright (C) 1999 Hugo Villeneuve \n"; - print $fd " *\n"; - print $fd " * This file is released under the GPLv2\n"; - print $fd " */\n\n"; -} - -# Write C function source code line to INST_IMP file. -# Prefix each line with a tab (indentation) and add newline character at the end. -sub cfw -{ - print INST_IMP "\t",$_[0],"\n"; -} - -# Header for instructions_8051.c -print INST_IMP "/*\n"; -print INST_IMP " * instructions_8051.c\n"; -write_header(INST_IMP); -print INST_IMP "/* Define only here, for not having extern scope on local variables. */\n"; -print INST_IMP "#define INSTRUCTIONS_8051_M 1\n\n\n"; -print INST_IMP "#include \"reg8051.h\"\n"; -print INST_IMP "#include \"cpu8051.h\"\n"; -print INST_IMP "#include \"memory.h\"\n"; -print INST_IMP "#include \"psw.h\"\n"; -print INST_IMP "#include \"operations.h\"\n"; -print INST_IMP "#include \"instructions_8051.h\"\n\n\n"; - -# Header for disasm.h -print DISASM_H "/*\n"; -print DISASM_H " * disasm.h\n"; -write_header(DISASM_H); -print DISASM_H "#ifndef DISASM_H\n"; -print DISASM_H "#define DISASM_H 1\n\n"; - -# Column indexes in opcodes.lst table -use constant COL_OPCODE => 0; -use constant COL_INSTR => 1; -use constant COL_ARGS => 2; - -use constant COL_COUNT_NO_ARGS => 4; - -$nbinst=0; -$nbaddr=0; -$nbargs=0; -$instnumb=0; - -# Read file describing each instruction/opcode - -# Discard first two lines, which are comments -$ligne = ; -$ligne = ; - -while($ligne=) { - chop $ligne; - - if (length $ligne < 2) { - next; - } - - @wordlist = split ' ',$ligne; - $nbword = @wordlist; - $instruction = $wordlist[COL_INSTR]; - - for ($i = (COL_INSTR + 1); $i < ($nbword - 2); $i++) { - $instruction = "$instruction $wordlist[$i]"; - } - - $a_instruction[$instnumb] = $instruction; - $a_bytes[$instnumb] = $wordlist[$nbword - 2]; - $a_cycles[$instnumb] = $wordlist[$nbword - 1]; - $a_opcodehex[$instnumb] = $wordlist[COL_OPCODE]; - - $instfunction[$instnumb] = "CPU8051::OP_$wordlist[COL_OPCODE]"; - - $instargs[$instnumb << 2] = $instargs[($instnumb << 2) + 1] = - $instargs[($instnumb << 2) + 2] = $instargs[($instnumb << 2) + 3] = 0; - - if ($nbword > COL_COUNT_NO_ARGS) { - @argslist = split /\,/,$wordlist[COL_ARGS]; - $argslistsize = @argslist; - $instargs[$instnumb << 2] = $argslistsize; - for ($i = 0; $i < $argslistsize; $i++) { - if (not exists $argstypes{$argslist[$i]}) { - $argstypes[$nbargs] = $argslist[$i]; - $argstypes{$argslist[$i]} = $nbargs++; - } - $instargs[($instnumb << 2) + $i + 1] = $argstypes{$argslist[$i]}; - } - } - - if (not exists $insttext{$wordlist[COL_INSTR]}) { - $insttext[$nbinst] = $wordlist[COL_INSTR]; - $insttext{$wordlist[COL_INSTR]} = $nbinst++; - } - - $insttype[$instnumb] = $insttext{$wordlist[COL_INSTR]}; - - if (not exists $addrmode{$wordlist[COL_ARGS]}) { - $addrmode[$nbaddr] = $wordlist[COL_ARGS]; - $addrmode{$wordlist[COL_ARGS]} = $nbaddr++; - } - - $nbbytes[$instnumb] = $wordlist[$nbword - 2]; - - $instaddr[$instnumb] = $addrmode{$wordlist[COL_ARGS]}; - - $instnumb++; -} - -# ------------------------------------------------------------------------------ -print DISASM_H "/* Size(in bytes) of each instruction (offset in table is instruction opcode) */\n"; - -$nbelement = @nbbytes; - -print DISASM_H "static int instr_size[$nbelement] = {"; - -for ($i = 0; $i < $nbelement; $i++) { - if ($i % 16 == 0) { - print DISASM_H "\n\t"; - } else { - print DISASM_H " "; - } - print DISASM_H "$nbbytes[$i],"; -} -print DISASM_H "\n"; -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * For all 256 opcodes, the value in this table gives the instruction type\n"; -print DISASM_H " * ex.: MOV, INC, CLR, CPL,...\n"; -print DISASM_H " * To know what is the instruction type, use\n"; -print DISASM_H " * the number as an offset in instr_type_str[]\n"; -print DISASM_H " */\n"; - -$nbelement = @insttype; - -print DISASM_H "static int instr_type_id[$nbelement] = {"; - -for ($i = 0; $i < $nbelement; $i++) { - if ($i % 16 == 0) { - print DISASM_H "\n\t"; - } else { - print DISASM_H " "; - } - print DISASM_H "$insttype[$i],"; -} -print DISASM_H "\n"; -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -print DISASM_H "/* List of instructions types referenced by instr_type_id[] */\n"; -$nbelement = @insttext; -$elementnb = 0; -print DISASM_H "static char *instr_type_str[$nbelement] = {\n"; - -foreach $instruc (@insttext) { - print DISASM_H "\t\"$instruc\""; - if ($elementnb++ < ($nbelement - 1)) { - print DISASM_H ","; - } - print DISASM_H "\n"; -} - -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * Table describing all arguments types of an instruction\n"; -print DISASM_H " * The table is indexed instr_arg_type_id[ opcode * 4]\n"; -print DISASM_H " * instr_arg_type_id[opcode*4 + 1] gives number of instruction arguments\n"; -print DISASM_H " * instr_arg_type_id[opcode*4 + i] for i=1,2 and 3 gives type of each argument\n"; -print DISASM_H " * for most instructions, the 3rd argument isn't used\n"; -print DISASM_H " * the argument type is referecing to instr_arg_type_str[]\n"; -print DISASM_H " */\n"; - -$nbelement = @instargs; - -print DISASM_H "static int instr_arg_type_id[$nbelement] = {"; - -for ($i = 0; $i < $nbelement; $i++) { - if ($i % 16 == 0) { - print DISASM_H "\n\t"; - } else { - print DISASM_H " "; - } - - print DISASM_H "$instargs[$i],"; -} -print DISASM_H "\n"; -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * List all types of arguments available to instructions\n"; -print DISASM_H " * Referenced by instr_arg_type_id[]\n"; -print DISASM_H " */\n"; - -$nbelement = @argstypes; -$elementnb = 0; - -print DISASM_H "static char *instr_arg_type_str[$nbelement] = {\n"; - -foreach $args (@argstypes) { - print DISASM_H "\t\"$args\""; - if ($elementnb++ < $nbelement-1) { - print DISASM_H ","; - } - print DISASM_H "\n"; -} -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -for ($i = 0 ; $i < 256; $i++) { - print INST_IMP "/*","*"x76,"\n"; - print INST_IMP " * Instruction \"$a_instruction[$i]\" takes $a_cycles[$i] cycle(s) and $a_bytes[$i] byte(s).\n"; - print INST_IMP " ","*"x76,"/\n"; - print INST_IMP "int\n"; - print INST_IMP "cpu8051_OP_$a_opcodehex[$i](void)\n"; - print INST_IMP "{\n"; - - if( $i == 0x85 ) { - # Cas particulier pour MOV direct,direct -> src et dest sont inverses dans la memoire - print INST_IMP " unsigned char srcaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; - print INST_IMP " unsigned char source = mem_read_direct( srcaddr );\n"; - print INST_IMP " unsigned char destaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; - print INST_IMP " unsigned char destination = mem_read_direct( destaddr );\n"; - print INST_IMP " destination = source;\n"; - print INST_IMP " mem_write_direct( destaddr, destination );\n"; - } - else { - if ($instargs[$i*4] > 0) { - $op_destination=$instargs[$i*4+1]; - if ($op_destination == 0) { # addr11 - cfw("unsigned int addr11 = ( ( mem_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + mem_read8( PGM_MEM_ID, cpu8051.pc );"); - cfw("cpu8051.pc++;"); - } - if ($op_destination == 1) { # addr16 - cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_destination == 2) { # A - cfw("unsigned char destination = mem_read_direct( _ACC_ );"); - } - if ($op_destination == 3) { # direct - cfw("unsigned char destaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); - cfw("unsigned char destination = mem_read_direct( destaddr );"); - } - if ($op_destination == 4) { # @R0 - cfw("unsigned char destination = mem_read_indirect ( mem_read_direct( BANKPSW + _R0_ ) );"); - } - if ($op_destination == 5) { # @R1 - cfw("unsigned char destination = mem_read_indirect ( mem_read_direct( BANKPSW + _R1_ ) );"); - } - if ($op_destination == 6) { # R0 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R0_ );"); - } - if ($op_destination == 7) { # R1 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R1_ );"); - } - if ($op_destination == 8) { # R2 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R2_ );"); - } - if ($op_destination == 9) { # R3 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R3_ );"); - } - if ($op_destination == 10) { # R4 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R4_ );"); - } - if ($op_destination == 11) { # R5 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R5_ );"); - } - if ($op_destination == 12) { # R6 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R6_ );"); - } - if ($op_destination == 13) { # R7 - cfw("unsigned char destination = mem_read_direct( BANKPSW + _R7_ );"); - } - if ($op_destination == 14) { # bitaddr - cfw("unsigned char destination, dstbitaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); - cfw("destination = mem_read_bit( dstbitaddr );"); - } - if ($op_destination == 15) { # reladdr - cfw("cpu8051.pc++;"); - cfw("unsigned int destination = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); - } - if ($op_destination == 16) { # #data - cfw("unsigned char destination = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); - } - if ($op_destination == 17) { # C - cfw("unsigned char destination = psw_read_cy();"); - } - if ($op_destination == 18) { # @A+DPTR - cfw("unsigned int destination = mem_read_direct( _ACC_ ) + mem_sfr_read_dptr();"); - } - if ($op_destination == 20) { # AB - cfw("unsigned char destination = mem_read_direct( _ACC_ );"); - cfw("unsigned char source = mem_read_direct( _B_ );"); - } - if ($op_destination == 21) { # DPTR - cfw("unsigned int destination = mem_sfr_read_dptr();"); - } - if ($op_destination == 23) { # /bitaddr - cfw("unsigned char destination, dstbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("destination = ( mem_read_bit( dstbitaddr ) ^ 1 );"); - } - if ($op_destination == 24) { # @DPTR - cfw("unsigned char destination = mem_read_indirect(mem_sfr_read_dptr());"); - } - } - - if ($instargs[$i*4] > 1) { - $op_source=$instargs[$i*4+2]; - if ($op_source == 0) { # addr11 - cfw("unsigned int addr11 = ( ( mem_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - } - if ($op_source == 1) { # addr16 - cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_source == 2) { # A - cfw("unsigned char source = mem_read_direct( _ACC_ );"); - } - if ($op_source == 3) { # direct - cfw("unsigned char srcaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("unsigned char source = mem_read_direct( srcaddr );"); - } - if ($op_source == 4) { # @R0 - cfw("unsigned char source = mem_read_indirect ( mem_read_direct( BANKPSW + _R0_ ) );"); - } - if ($op_source == 5) { # @R1 - cfw("unsigned char source = mem_read_indirect ( mem_read_direct( BANKPSW + _R1_ ) );"); - } - if ($op_source == 6) { # R0 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R0_ );"); - } - if ($op_source == 7) { # R1 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R1_ );"); - } - if ($op_source == 8) { # R2 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R2_ );"); - } - if ($op_source == 9) { # R3 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R3_ );"); - } - if ($op_source == 10) { # R4 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R4_ );"); - } - if ($op_source == 11) { # R5 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R5_ );"); - } - if ($op_source == 12) { # R6 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R6_ );"); - } - if ($op_source == 13) { # R7 - cfw("unsigned char source = mem_read_direct( BANKPSW + _R7_ );"); - } - - if ($op_source == 14) { # bitaddr - cfw("unsigned char source, srcbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("source = mem_read_bit( srcbitaddr );"); - } - if ($op_source == 15) { # reladdr - cfw("(cpu8051.pc)++;"); - cfw("unsigned int source = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); - } - if ($op_source == 16) { # #data - cfw("unsigned char source = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - } - if ($op_source == 17) { # C - cfw("unsigned char source = psw_read_cy();"); - } - if ($op_source == 18) { # @A+DPTR - cfw("unsigned char source = mem_read8( PGM_MEM_ID, mem_read_direct( _ACC_ ) + mem_sfr_read_dptr());"); - } - if ($op_source == 19) { # @A+PC - cfw("unsigned char source = mem_read8( PGM_MEM_ID, mem_read_direct( _ACC_ ) + ( ++cpu8051.pc ) );"); - } - if ($op_source == 21) { # DPTR - cfw("unsigned int source = mem_sfr_read_dptr();"); - } - if ($op_source == 22) { # #data16 - cfw("uint16_t source = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_source == 23) { # /bitaddr - cfw("unsigned char source, srcbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("source = ( mem_read_bit( srcbitaddr ) ^ 1 );"); - } - if ($op_source == 24) { # @DPTR - cfw("unsigned char source = mem_read_indirect(mem_sfr_read_dptr());"); - } - } - -############################################################################## - $modifysrc=0; - - # RR - if ($insttype[$i] == 3) { - cfw("destination = ( destination >> 1 ) | ( destination << 7 );"); - } - - # INC - if ($insttype[$i] == 4) { - cfw("destination++;"); - } - - # JBC - if ($insttype[$i] == 5) { - cfw("if ( destination == 1 ) { cpu8051.pc = source; destination = 0; }"); - } - - # ACALL - if ($insttype[$i] == 6) { - cfw("stack_push16(cpu8051.pc);"); - } - - # LCALL - if ($insttype[$i] == 7) { - cfw("stack_push16(cpu8051.pc);"); - } - - # RRC - if ($insttype[$i] == 8) { - cfw("unsigned char new_cy = destination & 0x01;"); - cfw("destination = ( destination >> 1 ) | (psw_read_cy() << 7);"); - cfw("psw_write_cy(new_cy);"); - } - - # DEC - if ($insttype[$i] == 9) { - cfw("destination--;"); - } - - # JB - if ($insttype[$i] == 10) { - cfw("if ( destination == 1 ) { cpu8051.pc = source; }"); - } - - # RET - if ($insttype[$i] == 11) { - cfw("cpu8051.pc = stack_pop16();"); - } - - # RL - if ($insttype[$i] == 12) { - cfw("destination = ( destination << 1 ) | ( destination >> 7 );"); - } - - # ADD - if ($insttype[$i] == 13) { - cfw("destination = addition(destination, source, 0);"); - } - - # JNB - if ($insttype[$i] == 14) { - cfw("if ( destination == 0 ) { cpu8051.pc = source; }"); - } - - # RETI - if ($insttype[$i] == 15) { - cfw("cpu8051.active_priority = -1;"); - cfw("cpu8051.pc = stack_pop16();"); - } - - # RLC - if ($insttype[$i] == 16) { - cfw("unsigned char new_cy = destination & 0x80;"); - cfw("destination = ( destination << 1 ) | psw_read_cy();"); - cfw("psw_write_cy(new_cy);"); - } - - # ADDC - # ADD and ADDC function identically except that ADDC adds the value of - # operand as well as the value of the Carry flag whereas ADD does not - # add the Carry flag to the result. - if ($insttype[$i] == 17) { - cfw("unsigned char carryflag = psw_read_cy();"); - cfw("destination = addition(destination, source, carryflag);"); - } - - # JC - if ($insttype[$i] == 18) { - cfw("if (psw_read_cy()) { cpu8051.pc = destination; }"); - } - - # ORL - if ($insttype[$i] == 19) { - cfw("destination |= source;"); - } - - # JNC - if ($insttype[$i] == 20) { - cfw("if (psw_read_cy() == 0) { cpu8051.pc = destination; }"); - } - - # ANL - if ($insttype[$i] == 21) { - cfw("destination &= source;"); - } - - # JZ - if ($insttype[$i] == 22) { - cfw("if ( mem_read_direct( _ACC_ ) == 0 ) { cpu8051.pc = destination; }"); - } - - # XRL - if ($insttype[$i] == 23) { - cfw("destination ^= source;"); - } - - # JNZ - if ($insttype[$i] == 24) { - cfw("if ( mem_read_direct( _ACC_ ) != 0 ) { cpu8051.pc = destination; }"); - } - - # JMP - if ($insttype[$i] == 25) { - cfw("cpu8051.pc = destination;"); - } - - # MOV - if ($insttype[$i] == 26) { - cfw("destination = source;"); - } - - # SJMP - if ($insttype[$i] == 27) { - cfw("cpu8051.pc = destination;"); - } - - # MOVC - if ($insttype[$i] == 28) { - cfw("destination = source;"); - } - - # DIV - if ($insttype[$i] == 29) { - # A = destination - # B = source - cfw("psw_clr_cy();"); - # If B is zero, the OV flag will be set indicating a - # division-by-zero error - cfw("if (source != 0) {"); - cfw(" mem_write_direct(_ACC_, destination/source);"); - cfw(" mem_write_direct( _B_, destination%source);"); - cfw(" psw_clr_ov();"); - cfw("} else {"); - cfw(" psw_set_ov();"); - cfw("}"); - } - - # SUBB - if ($insttype[$i] == 30) { - cfw("unsigned char carryflag = psw_read_cy();"); - cfw("psw_clr_cy();"); - cfw("psw_clr_ac();"); - cfw("psw_clr_ov();"); - cfw("if ( destination < ( source + carryflag ) ) {"); - cfw(" psw_set_cy();"); - cfw(" if ((destination & 0x7F) > ((source + carryflag) & 0x7F)) psw_set_ov();"); - cfw("} else if ((destination & 0x7F) < ((source + carryflag) & 0x7F)) psw_set_ov();"); - cfw("if ((destination & 0x0F) < ((source + carryflag) & 0x0F)) psw_set_ac();"); - cfw("destination -= source + carryflag;"); - } - - # MUL - if ($insttype[$i] == 31) { - # A = destination - # B = source - cfw("psw_clr_cy();"); - cfw("mem_write_direct(_ACC_, destination * source);"); - cfw("mem_write_direct(_B_, (destination * source) / 0x100);"); - cfw("if (mem_read_direct(_B_) > 0)"); - cfw(" psw_set_ov();"); - cfw("else"); - cfw(" psw_clr_ov();"); - } - - # CPL - if ($insttype[$i] == 33) { - if ($instargs[$i*4+1] == 2) { cfw("destination ^= 0xFF;"); } - else { cfw("destination ^= 0x01;"); } - } - - # CJNE - if ($insttype[$i] == 34) { - cfw("unsigned int reladdr = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc)) + (cpu8051.pc + 1);"); - cfw("psw_clr_cy();"); - cfw("if ( destination < source ) psw_set_cy();"); - cfw("if ( destination != source ) cpu8051.pc = reladdr; else cpu8051.pc++;"); - } - - # PUSH - if ($insttype[$i] == 35) { - cfw("stack_push8(destination);"); - } - - # CLR - if ($insttype[$i] == 36) { - cfw("destination = 0;"); - } - - # SWAP - if ($insttype[$i] == 37) { - cfw("destination = ( destination << 4 ) + ( destination >> 4 );"); - } - - # XCH - if ($insttype[$i] == 38) { - cfw("unsigned char tmpval = destination;"); - cfw("destination = source; source = tmpval;"); - $modifysrc=1; - } - - # POP - if ($insttype[$i] == 39) { - cfw("destination = stack_pop8();"); - } - - # SETB - if ($insttype[$i] == 40) { - cfw("destination = 1;"); - } - - # DA - if ($insttype[$i] == 41) { - cfw("if (((destination & 0x0F) > 9) || psw_read_ac()) {"); - cfw(" if ( ( destination + 6 ) > 0xFF) psw_set_cy();"); - cfw(" destination += 6;"); - cfw("}"); - cfw("if ( psw_read_cy() || ( ( destination & 0xF0 ) > 0x90 ) ) {"); - cfw(" if ( ( destination + 0x60 ) > 0xFF ) psw_set_cy();"); - cfw(" destination += 0x60;"); - cfw("}"); - } - - # DJNZ - if ($insttype[$i] == 42) { - cfw("destination--;"); - cfw("if ( destination != 0 ) cpu8051.pc = source;"); - } - - # XCHD - if ($insttype[$i] == 43) { - cfw("unsigned char tmpval = ( destination & 0x0F );"); - cfw("destination = ( destination & 0xF0 ) + ( source & 0x0F );"); - cfw("source = ( source & 0xF0 ) + tmpval;"); - $modifysrc=1; - } - - # MOVX - if ($insttype[$i] == 44) { - cfw("destination = source;"); - } - - - -############################################################################## - - - if ($instargs[$i*4] > 0) { - $op_destination=$instargs[$i*4+1]; - if ($op_destination == 0) { # addr11 - cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); - } - if ($op_destination == 1) { # addr16 - cfw("cpu8051.pc = addr16;"); - } - if ($op_destination == 2) { # A - cfw("mem_write_direct( _ACC_, destination );"); - } - if ($op_destination == 3) { # direct - cfw("mem_write_direct( destaddr, destination );"); - } - if ($op_destination == 4) { # @R0 - cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R0_ ), destination );"); - } - if ($op_destination == 5) { # @R1 - cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R1_ ), destination );"); - } - if ($op_destination == 6) { # R0 - cfw("mem_write_direct( BANKPSW + _R0_, destination );"); - } - if ($op_destination == 7) { # R1 - cfw("mem_write_direct( BANKPSW + _R1_, destination );"); - } - if ($op_destination == 8) { # R2 - cfw("mem_write_direct( BANKPSW + _R2_, destination );"); - } - if ($op_destination == 9) { # R3 - cfw("mem_write_direct( BANKPSW + _R3_, destination );"); - } - if ($op_destination == 10) { # R4 - cfw("mem_write_direct( BANKPSW + _R4_, destination );"); - } - if ($op_destination == 11) { # R5 - cfw("mem_write_direct( BANKPSW + _R5_, destination );"); - } - if ($op_destination == 12) { # R6 - cfw("mem_write_direct( BANKPSW + _R6_, destination );"); - } - if ($op_destination == 13) { # R7 - cfw("mem_write_direct( BANKPSW + _R7_, destination );"); - } - - if ($op_destination == 14) { # bitaddr - cfw("mem_write_bit( dstbitaddr, destination );"); - } - if ($op_destination == 17) { # C - cfw("psw_write_cy(destination);"); - } - if ($op_destination == 21) { # DPTR - cfw("mem_sfr_write_dptr(destination);"); - } - if ($op_destination == 23) { # /bitaddr - cfw("mem_write_bit( dstbitaddr, destination );"); - } - if ($op_destination == 24) { # @DPTR - cfw("mem_write_indirect(mem_sfr_read_dptr(), destination);"); - } - } - - if ($modifysrc == 1) { - if ($instargs[$i*4] > 1) { - $op_source=$instargs[$i*4+2]; - if ($op_source == 0) { # addr11 - cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); - } - if ($op_source == 1) { # addr16 - cfw("cpu8051.pc = addr16;"); - } - if ($op_source == 2) { # A - cfw("mem_write_direct( _ACC_, source );"); - } - if ($op_source == 3) { # direct - cfw("mem_write_direct( srcaddr, source );"); - } - if ($op_source == 4) { # @R0 - cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R0_ ), source );"); - } - if ($op_source == 5) { # @R1 - cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R1_ ), source );"); - } - if ($op_source == 6) { # R0 - cfw("mem_write_direct( BANKPSW + _R0_, source );"); - } - if ($op_source == 7) { # R1 - cfw("mem_write_direct( BANKPSW + _R1_, source );"); - } - if ($op_source == 8) { # R2 - cfw("mem_write_direct( BANKPSW + _R2_, source );"); - } - if ($op_source == 9) { # R3 - cfw("mem_write_direct( BANKPSW + _R3_, source );"); - } - if ($op_source == 10) { # R4 - cfw("mem_write_direct( BANKPSW + _R4_, source );"); - } - if ($op_source == 11) { # R5 - cfw("mem_write_direct( BANKPSW + _R5_, source );"); - } - if ($op_source == 12) { # R6 - cfw("mem_write_direct( BANKPSW + _R6_, source );"); - } - if ($op_source == 13) { # R7 - cfw("mem_write_direct( BANKPSW + _R7_, source );"); - } - if ($op_source == 14) { # bitaddr - cfw("mem_write_bit( srcbitaddr, source );"); - } - if ($op_source == 17) { # C - cfw("psw_write_cy(source);"); - } - if ($op_source == 21) { # DPTR - cfw("mem_sfr_write_dptr(source);"); - } - if ($op_source == 23) { # /bitaddr - cfw("mem_write_bit( srcbitaddr, source );"); - } - if ($op_source == 24) { # @DPTR - cfw("mem_write_indirect(mem_sfr_read_dptr(), source);"); - } - } - } - } - cfw("return $a_cycles[$i];"); - print INST_IMP "}\n"; - print INST_IMP "\n"; -} -# ------------------------------------------------------------------------------ - - -# Header for instructions_8051.h -print INST_DEF "/*\n"; -print INST_DEF " * instructions_8051.h\n"; -write_header(INST_DEF); -print INST_DEF "#ifndef INSTRUCTIONS_8051_H\n"; -print INST_DEF "#define INSTRUCTIONS_8051_H 1\n\n\n"; -print INST_DEF "#define BANKPSW (mem_read_direct(_PSW_) & 0x18)\n\n"; -print INST_DEF "typedef int (*OPCODE_FP)(void);\n\n\n"; -for( $i=0; $i<256; $i++ ) { - print INST_DEF "int\n"; - print INST_DEF "cpu8051_OP_$a_opcodehex[$i](void);\n\n"; -} -print INST_DEF "\n"; -print INST_DEF "/* Exported variables. */\n"; -print INST_DEF "#ifdef INSTRUCTIONS_8051_M\n"; -print INST_DEF "OPCODE_FP opcode_table[256] = {\n"; - -for ($i = 0; $i < 256; $i++) { - $ifunc = substr($instfunction[$i], 9); - - print INST_DEF "\tcpu8051_$ifunc,\n"; -} -print INST_DEF "};\n"; -print INST_DEF "#else\n"; -print INST_DEF "OPCODE_FP opcode_table[256];\n"; -print INST_DEF "#endif\n\n\n"; - -print INST_DEF "#endif /* INSTRUCTIONS_8051_H */\n"; - -print DISASM_H "#endif /* DISASM_H */\n"; - -close DISASM_H; -close OPCODELST; -close INST_DEF; -close INST_IMP; diff --git a/src/common/opcodes2c.pl b/src/common/opcodes2c.pl new file mode 100755 index 0000000..2bc822a --- /dev/null +++ b/src/common/opcodes2c.pl @@ -0,0 +1,901 @@ +#!/usr/bin/perl +# +# Copyright (C) 1999 Jonathan St-André +# Copyright (C) 1999 Hugo Villeneuve +# +# This file is released under the GPLv2 + +open INST_DEF, ">instructions_8051.h" or die "Error creating : $!\n"; +open INST_IMP, ">instructions_8051.c" or die "Error creating : $!\n"; +open OPCODELST, "opcodes.lst" or die "Error opening : $!\n"; +open OPCODES_DEF, ">opcodes.h" or die "Error creating : $!\n"; +open OPCODES_IMP, ">opcodes.c" or die "Error creating : $!\n"; + +# Write GPL license +# Argument 0 is file descriptor +sub write_header +{ + my $fd = $_[0]; + + print $fd " *\n"; + print $fd " * Do not modify this file directly, as it was created by opcodes2c.pl\n"; + print $fd " * Any modifications made directly to this file will be lost.\n"; + print $fd " *\n"; + print $fd " * Copyright (C) 1999 Jonathan St-André\n"; + print $fd " * Copyright (C) 1999 Hugo Villeneuve \n"; + print $fd " *\n"; + print $fd " * This file is released under the GPLv2\n"; + print $fd " */\n\n"; +} + +# Write C function source code line to INST_IMP file. +# Prefix each line with a tab (indentation) and add newline character at the end. +sub cfw +{ + print INST_IMP "\t",$_[0],"\n"; +} + +# Header for instructions_8051.c +print INST_IMP "/*\n"; +print INST_IMP " * instructions_8051.c\n"; +write_header(INST_IMP); +print INST_IMP "/* Define only here, for not having extern scope on local variables. */\n"; +print INST_IMP "#define INSTRUCTIONS_8051_M 1\n\n\n"; +print INST_IMP "#include \"reg8051.h\"\n"; +print INST_IMP "#include \"cpu8051.h\"\n"; +print INST_IMP "#include \"memory.h\"\n"; +print INST_IMP "#include \"psw.h\"\n"; +print INST_IMP "#include \"operations.h\"\n"; +print INST_IMP "#include \"instructions_8051.h\"\n\n\n"; + +# Header for opcodes.h +print OPCODES_DEF "/*\n"; +print OPCODES_DEF " * opcodes.h\n"; +write_header(OPCODES_DEF); +print OPCODES_DEF "#ifndef OPCODES_H\n"; +print OPCODES_DEF "#define OPCODES_H 1\n\n"; + +print OPCODES_DEF "int\n"; +print OPCODES_DEF "opcodes_get_instr_size(uint8_t opcode);\n"; +print OPCODES_DEF "char *\n"; +print OPCODES_DEF "opcodes_get_instr_type_str(uint8_t opcode);\n"; +print OPCODES_DEF "int\n"; +print OPCODES_DEF "opcodes_get_instr_arg_type_id(unsigned int offset);\n"; +print OPCODES_DEF "char *\n"; +print OPCODES_DEF "opcodes_get_instr_arg_type_str(unsigned int offset);\n"; + +# opcodes.c +print OPCODES_IMP "/*\n"; +print OPCODES_IMP " * opcodes.c\n"; +write_header(OPCODES_IMP); +print OPCODES_IMP "#include \n\n"; + +# Column indexes in opcodes.lst table +use constant COL_OPCODE => 0; +use constant COL_INSTR => 1; +use constant COL_ARGS => 2; + +use constant COL_COUNT_NO_ARGS => 4; + +$nbinst=0; +$nbaddr=0; +$nbargs=0; +$instnumb=0; + +# Read file describing each instruction/opcode + +# Discard first two lines, which are comments +$ligne = ; +$ligne = ; + +while($ligne=) { + chop $ligne; + + if (length $ligne < 2) { + next; + } + + @wordlist = split ' ',$ligne; + $nbword = @wordlist; + $instruction = $wordlist[COL_INSTR]; + + for ($i = (COL_INSTR + 1); $i < ($nbword - 2); $i++) { + $instruction = "$instruction $wordlist[$i]"; + } + + $a_instruction[$instnumb] = $instruction; + $a_bytes[$instnumb] = $wordlist[$nbword - 2]; + $a_cycles[$instnumb] = $wordlist[$nbword - 1]; + $a_opcodehex[$instnumb] = $wordlist[COL_OPCODE]; + + $instfunction[$instnumb] = "CPU8051::OP_$wordlist[COL_OPCODE]"; + + $instargs[$instnumb << 2] = $instargs[($instnumb << 2) + 1] = + $instargs[($instnumb << 2) + 2] = $instargs[($instnumb << 2) + 3] = 0; + + if ($nbword > COL_COUNT_NO_ARGS) { + @argslist = split /\,/,$wordlist[COL_ARGS]; + $argslistsize = @argslist; + $instargs[$instnumb << 2] = $argslistsize; + for ($i = 0; $i < $argslistsize; $i++) { + if (not exists $argstypes{$argslist[$i]}) { + $argstypes[$nbargs] = $argslist[$i]; + $argstypes{$argslist[$i]} = $nbargs++; + } + $instargs[($instnumb << 2) + $i + 1] = $argstypes{$argslist[$i]}; + } + } + + if (not exists $insttext{$wordlist[COL_INSTR]}) { + $insttext[$nbinst] = $wordlist[COL_INSTR]; + $insttext{$wordlist[COL_INSTR]} = $nbinst++; + } + + $insttype[$instnumb] = $insttext{$wordlist[COL_INSTR]}; + + if (not exists $addrmode{$wordlist[COL_ARGS]}) { + $addrmode[$nbaddr] = $wordlist[COL_ARGS]; + $addrmode{$wordlist[COL_ARGS]} = $nbaddr++; + } + + $nbbytes[$instnumb] = $wordlist[$nbword - 2]; + + $instaddr[$instnumb] = $addrmode{$wordlist[COL_ARGS]}; + + $instnumb++; +} + +# ------------------------------------------------------------------------------ +print OPCODES_IMP "/* Size(in bytes) of each instruction (offset in table is instruction opcode) */\n"; + +$nbelement = @nbbytes; + +print OPCODES_IMP "static int instr_size[$nbelement] = {"; + +for ($i = 0; $i < $nbelement; $i++) { + if ($i % 16 == 0) { + print OPCODES_IMP "\n\t"; + } else { + print OPCODES_IMP " "; + } + print OPCODES_IMP "$nbbytes[$i],"; +} +print OPCODES_IMP "\n"; +print OPCODES_IMP "};\n"; +print OPCODES_IMP "\n"; + +# ------------------------------------------------------------------------------ +print OPCODES_IMP "/*\n"; +print OPCODES_IMP " * For all 256 opcodes, the value in this table gives the instruction type\n"; +print OPCODES_IMP " * ex.: MOV, INC, CLR, CPL,...\n"; +print OPCODES_IMP " * To know what is the instruction type, use\n"; +print OPCODES_IMP " * the number as an offset in instr_type_str[]\n"; +print OPCODES_IMP " */\n"; + +$nbelement = @insttype; + +print OPCODES_IMP "static int instr_type_id[$nbelement] = {"; + +for ($i = 0; $i < $nbelement; $i++) { + if ($i % 16 == 0) { + print OPCODES_IMP "\n\t"; + } else { + print OPCODES_IMP " "; + } + print OPCODES_IMP "$insttype[$i],"; +} +print OPCODES_IMP "\n"; +print OPCODES_IMP "};\n"; +print OPCODES_IMP "\n"; + +# ------------------------------------------------------------------------------ +print OPCODES_IMP "/* List of instructions types referenced by instr_type_id[] */\n"; +$nbelement = @insttext; +$elementnb = 0; +print OPCODES_IMP "static char *instr_type_str[$nbelement] = {\n"; + +foreach $instruc (@insttext) { + print OPCODES_IMP "\t\"$instruc\""; + if ($elementnb++ < ($nbelement - 1)) { + print OPCODES_IMP ","; + } + print OPCODES_IMP "\n"; +} + +print OPCODES_IMP "};\n"; +print OPCODES_IMP "\n"; + +# ------------------------------------------------------------------------------ +print OPCODES_IMP "/*\n"; +print OPCODES_IMP " * Table describing all arguments types of an instruction\n"; +print OPCODES_IMP " * The table is indexed instr_arg_type_id[ opcode * 4]\n"; +print OPCODES_IMP " * instr_arg_type_id[opcode*4 + 1] gives number of instruction arguments\n"; +print OPCODES_IMP " * instr_arg_type_id[opcode*4 + i] for i=1,2 and 3 gives type of each argument\n"; +print OPCODES_IMP " * for most instructions, the 3rd argument isn't used\n"; +print OPCODES_IMP " * the argument type is referenced to instr_arg_type_str[]\n"; +print OPCODES_IMP " */\n"; + +$nbelement = @instargs; + +print OPCODES_IMP "static int instr_arg_type_id[$nbelement] = {"; + +for ($i = 0; $i < $nbelement; $i++) { + if ($i % 16 == 0) { + print OPCODES_IMP "\n\t"; + } else { + print OPCODES_IMP " "; + } + + print OPCODES_IMP "$instargs[$i],"; +} +print OPCODES_IMP "\n"; +print OPCODES_IMP "};\n"; +print OPCODES_IMP "\n"; + +# ------------------------------------------------------------------------------ +print OPCODES_IMP "/*\n"; +print OPCODES_IMP " * List all types of arguments available to instructions\n"; +print OPCODES_IMP " * Referenced by instr_arg_type_id[]\n"; +print OPCODES_IMP " */\n"; + +$nbelement = @argstypes; +$elementnb = 0; + +print OPCODES_IMP "static char *instr_arg_type_str[$nbelement] = {\n"; + +foreach $args (@argstypes) { + print OPCODES_IMP "\t\"$args\""; + if ($elementnb++ < $nbelement-1) { + print OPCODES_IMP ","; + } + print OPCODES_IMP "\n"; +} +print OPCODES_IMP "};\n"; +print OPCODES_IMP "\n"; + +print OPCODES_IMP "int\n"; +print OPCODES_IMP "opcodes_get_instr_size(uint8_t opcode)\n"; +print OPCODES_IMP "{\n"; +print OPCODES_IMP "\treturn instr_size[opcode];\n"; +print OPCODES_IMP "}\n"; +print OPCODES_IMP "\n"; + +print OPCODES_IMP "char *\n"; +print OPCODES_IMP "opcodes_get_instr_type_str(uint8_t opcode)\n"; +print OPCODES_IMP "{\n"; +print OPCODES_IMP "\treturn instr_type_str[instr_type_id[opcode]];\n"; +print OPCODES_IMP "}\n"; +print OPCODES_IMP "\n"; + +print OPCODES_IMP "int\n"; +print OPCODES_IMP "opcodes_get_instr_arg_type_id(unsigned int offset)\n"; +print OPCODES_IMP "{\n"; +print OPCODES_IMP "\treturn instr_arg_type_id[offset];\n"; +print OPCODES_IMP "}\n"; +print OPCODES_IMP "\n"; + +print OPCODES_IMP "char *\n"; +print OPCODES_IMP "opcodes_get_instr_arg_type_str(unsigned int offset)\n"; +print OPCODES_IMP "{\n"; +print OPCODES_IMP "\treturn instr_arg_type_str[instr_arg_type_id[offset]];\n"; +print OPCODES_IMP "}\n"; +print OPCODES_IMP "\n"; + + +# ------------------------------------------------------------------------------ +for ($i = 0 ; $i < 256; $i++) { + print INST_IMP "/*","*"x76,"\n"; + print INST_IMP " * Instruction \"$a_instruction[$i]\" takes $a_cycles[$i] cycle(s) and $a_bytes[$i] byte(s).\n"; + print INST_IMP " ","*"x76,"/\n"; + print INST_IMP "int\n"; + print INST_IMP "cpu8051_OP_$a_opcodehex[$i](void)\n"; + print INST_IMP "{\n"; + + if( $i == 0x85 ) { + # Cas particulier pour MOV direct,direct -> src et dest sont inverses dans la memoire + print INST_IMP " unsigned char srcaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; + print INST_IMP " unsigned char source = mem_read_direct( srcaddr );\n"; + print INST_IMP " unsigned char destaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; + print INST_IMP " unsigned char destination = mem_read_direct( destaddr );\n"; + print INST_IMP " destination = source;\n"; + print INST_IMP " mem_write_direct( destaddr, destination );\n"; + } + else { + if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + cfw("unsigned int addr11 = ( ( mem_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + mem_read8( PGM_MEM_ID, cpu8051.pc );"); + cfw("cpu8051.pc++;"); + } + if ($op_destination == 1) { # addr16 + cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_destination == 2) { # A + cfw("unsigned char destination = mem_read_direct( _ACC_ );"); + } + if ($op_destination == 3) { # direct + cfw("unsigned char destaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); + cfw("unsigned char destination = mem_read_direct( destaddr );"); + } + if ($op_destination == 4) { # @R0 + cfw("unsigned char destination = mem_read_indirect ( mem_read_direct( BANKPSW + _R0_ ) );"); + } + if ($op_destination == 5) { # @R1 + cfw("unsigned char destination = mem_read_indirect ( mem_read_direct( BANKPSW + _R1_ ) );"); + } + if ($op_destination == 6) { # R0 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R0_ );"); + } + if ($op_destination == 7) { # R1 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R1_ );"); + } + if ($op_destination == 8) { # R2 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R2_ );"); + } + if ($op_destination == 9) { # R3 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R3_ );"); + } + if ($op_destination == 10) { # R4 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R4_ );"); + } + if ($op_destination == 11) { # R5 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R5_ );"); + } + if ($op_destination == 12) { # R6 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R6_ );"); + } + if ($op_destination == 13) { # R7 + cfw("unsigned char destination = mem_read_direct( BANKPSW + _R7_ );"); + } + if ($op_destination == 14) { # bitaddr + cfw("unsigned char destination, dstbitaddr = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); + cfw("destination = mem_read_bit( dstbitaddr );"); + } + if ($op_destination == 15) { # reladdr + cfw("cpu8051.pc++;"); + cfw("unsigned int destination = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); + } + if ($op_destination == 16) { # #data + cfw("unsigned char destination = mem_read8( PGM_MEM_ID, cpu8051.pc++ );"); + } + if ($op_destination == 17) { # C + cfw("unsigned char destination = psw_read_cy();"); + } + if ($op_destination == 18) { # @A+DPTR + cfw("unsigned int destination = mem_read_direct( _ACC_ ) + mem_sfr_read_dptr();"); + } + if ($op_destination == 20) { # AB + cfw("unsigned char destination = mem_read_direct( _ACC_ );"); + cfw("unsigned char source = mem_read_direct( _B_ );"); + } + if ($op_destination == 21) { # DPTR + cfw("unsigned int destination = mem_sfr_read_dptr();"); + } + if ($op_destination == 23) { # /bitaddr + cfw("unsigned char destination, dstbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("destination = ( mem_read_bit( dstbitaddr ) ^ 1 );"); + } + if ($op_destination == 24) { # @DPTR + cfw("unsigned char destination = mem_read_indirect(mem_sfr_read_dptr());"); + } + } + + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + cfw("unsigned int addr11 = ( ( mem_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + } + if ($op_source == 1) { # addr16 + cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_source == 2) { # A + cfw("unsigned char source = mem_read_direct( _ACC_ );"); + } + if ($op_source == 3) { # direct + cfw("unsigned char srcaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("unsigned char source = mem_read_direct( srcaddr );"); + } + if ($op_source == 4) { # @R0 + cfw("unsigned char source = mem_read_indirect ( mem_read_direct( BANKPSW + _R0_ ) );"); + } + if ($op_source == 5) { # @R1 + cfw("unsigned char source = mem_read_indirect ( mem_read_direct( BANKPSW + _R1_ ) );"); + } + if ($op_source == 6) { # R0 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R0_ );"); + } + if ($op_source == 7) { # R1 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R1_ );"); + } + if ($op_source == 8) { # R2 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R2_ );"); + } + if ($op_source == 9) { # R3 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R3_ );"); + } + if ($op_source == 10) { # R4 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R4_ );"); + } + if ($op_source == 11) { # R5 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R5_ );"); + } + if ($op_source == 12) { # R6 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R6_ );"); + } + if ($op_source == 13) { # R7 + cfw("unsigned char source = mem_read_direct( BANKPSW + _R7_ );"); + } + + if ($op_source == 14) { # bitaddr + cfw("unsigned char source, srcbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("source = mem_read_bit( srcbitaddr );"); + } + if ($op_source == 15) { # reladdr + cfw("(cpu8051.pc)++;"); + cfw("unsigned int source = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); + } + if ($op_source == 16) { # #data + cfw("unsigned char source = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + } + if ($op_source == 17) { # C + cfw("unsigned char source = psw_read_cy();"); + } + if ($op_source == 18) { # @A+DPTR + cfw("unsigned char source = mem_read8( PGM_MEM_ID, mem_read_direct( _ACC_ ) + mem_sfr_read_dptr());"); + } + if ($op_source == 19) { # @A+PC + cfw("unsigned char source = mem_read8( PGM_MEM_ID, mem_read_direct( _ACC_ ) + ( ++cpu8051.pc ) );"); + } + if ($op_source == 21) { # DPTR + cfw("unsigned int source = mem_sfr_read_dptr();"); + } + if ($op_source == 22) { # #data16 + cfw("uint16_t source = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_source == 23) { # /bitaddr + cfw("unsigned char source, srcbitaddr = mem_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("source = ( mem_read_bit( srcbitaddr ) ^ 1 );"); + } + if ($op_source == 24) { # @DPTR + cfw("unsigned char source = mem_read_indirect(mem_sfr_read_dptr());"); + } + } + +############################################################################## + $modifysrc=0; + + # RR + if ($insttype[$i] == 3) { + cfw("destination = ( destination >> 1 ) | ( destination << 7 );"); + } + + # INC + if ($insttype[$i] == 4) { + cfw("destination++;"); + } + + # JBC + if ($insttype[$i] == 5) { + cfw("if ( destination == 1 ) { cpu8051.pc = source; destination = 0; }"); + } + + # ACALL + if ($insttype[$i] == 6) { + cfw("stack_push16(cpu8051.pc);"); + } + + # LCALL + if ($insttype[$i] == 7) { + cfw("stack_push16(cpu8051.pc);"); + } + + # RRC + if ($insttype[$i] == 8) { + cfw("unsigned char new_cy = destination & 0x01;"); + cfw("destination = ( destination >> 1 ) | (psw_read_cy() << 7);"); + cfw("psw_write_cy(new_cy);"); + } + + # DEC + if ($insttype[$i] == 9) { + cfw("destination--;"); + } + + # JB + if ($insttype[$i] == 10) { + cfw("if ( destination == 1 ) { cpu8051.pc = source; }"); + } + + # RET + if ($insttype[$i] == 11) { + cfw("cpu8051.pc = stack_pop16();"); + } + + # RL + if ($insttype[$i] == 12) { + cfw("destination = ( destination << 1 ) | ( destination >> 7 );"); + } + + # ADD + if ($insttype[$i] == 13) { + cfw("destination = addition(destination, source, 0);"); + } + + # JNB + if ($insttype[$i] == 14) { + cfw("if ( destination == 0 ) { cpu8051.pc = source; }"); + } + + # RETI + if ($insttype[$i] == 15) { + cfw("cpu8051.active_priority = -1;"); + cfw("cpu8051.pc = stack_pop16();"); + } + + # RLC + if ($insttype[$i] == 16) { + cfw("unsigned char new_cy = destination & 0x80;"); + cfw("destination = ( destination << 1 ) | psw_read_cy();"); + cfw("psw_write_cy(new_cy);"); + } + + # ADDC + # ADD and ADDC function identically except that ADDC adds the value of + # operand as well as the value of the Carry flag whereas ADD does not + # add the Carry flag to the result. + if ($insttype[$i] == 17) { + cfw("unsigned char carryflag = psw_read_cy();"); + cfw("destination = addition(destination, source, carryflag);"); + } + + # JC + if ($insttype[$i] == 18) { + cfw("if (psw_read_cy()) { cpu8051.pc = destination; }"); + } + + # ORL + if ($insttype[$i] == 19) { + cfw("destination |= source;"); + } + + # JNC + if ($insttype[$i] == 20) { + cfw("if (psw_read_cy() == 0) { cpu8051.pc = destination; }"); + } + + # ANL + if ($insttype[$i] == 21) { + cfw("destination &= source;"); + } + + # JZ + if ($insttype[$i] == 22) { + cfw("if ( mem_read_direct( _ACC_ ) == 0 ) { cpu8051.pc = destination; }"); + } + + # XRL + if ($insttype[$i] == 23) { + cfw("destination ^= source;"); + } + + # JNZ + if ($insttype[$i] == 24) { + cfw("if ( mem_read_direct( _ACC_ ) != 0 ) { cpu8051.pc = destination; }"); + } + + # JMP + if ($insttype[$i] == 25) { + cfw("cpu8051.pc = destination;"); + } + + # MOV + if ($insttype[$i] == 26) { + cfw("destination = source;"); + } + + # SJMP + if ($insttype[$i] == 27) { + cfw("cpu8051.pc = destination;"); + } + + # MOVC + if ($insttype[$i] == 28) { + cfw("destination = source;"); + } + + # DIV + if ($insttype[$i] == 29) { + # A = destination + # B = source + cfw("psw_clr_cy();"); + # If B is zero, the OV flag will be set indicating a + # division-by-zero error + cfw("if (source != 0) {"); + cfw(" mem_write_direct(_ACC_, destination/source);"); + cfw(" mem_write_direct( _B_, destination%source);"); + cfw(" psw_clr_ov();"); + cfw("} else {"); + cfw(" psw_set_ov();"); + cfw("}"); + } + + # SUBB + if ($insttype[$i] == 30) { + cfw("unsigned char carryflag = psw_read_cy();"); + cfw("psw_clr_cy();"); + cfw("psw_clr_ac();"); + cfw("psw_clr_ov();"); + cfw("if ( destination < ( source + carryflag ) ) {"); + cfw(" psw_set_cy();"); + cfw(" if ((destination & 0x7F) > ((source + carryflag) & 0x7F)) psw_set_ov();"); + cfw("} else if ((destination & 0x7F) < ((source + carryflag) & 0x7F)) psw_set_ov();"); + cfw("if ((destination & 0x0F) < ((source + carryflag) & 0x0F)) psw_set_ac();"); + cfw("destination -= source + carryflag;"); + } + + # MUL + if ($insttype[$i] == 31) { + # A = destination + # B = source + cfw("psw_clr_cy();"); + cfw("mem_write_direct(_ACC_, destination * source);"); + cfw("mem_write_direct(_B_, (destination * source) / 0x100);"); + cfw("if (mem_read_direct(_B_) > 0)"); + cfw(" psw_set_ov();"); + cfw("else"); + cfw(" psw_clr_ov();"); + } + + # CPL + if ($insttype[$i] == 33) { + if ($instargs[$i*4+1] == 2) { cfw("destination ^= 0xFF;"); } + else { cfw("destination ^= 0x01;"); } + } + + # CJNE + if ($insttype[$i] == 34) { + cfw("unsigned int reladdr = ((char) mem_read8(PGM_MEM_ID, cpu8051.pc)) + (cpu8051.pc + 1);"); + cfw("psw_clr_cy();"); + cfw("if ( destination < source ) psw_set_cy();"); + cfw("if ( destination != source ) cpu8051.pc = reladdr; else cpu8051.pc++;"); + } + + # PUSH + if ($insttype[$i] == 35) { + cfw("stack_push8(destination);"); + } + + # CLR + if ($insttype[$i] == 36) { + cfw("destination = 0;"); + } + + # SWAP + if ($insttype[$i] == 37) { + cfw("destination = ( destination << 4 ) + ( destination >> 4 );"); + } + + # XCH + if ($insttype[$i] == 38) { + cfw("unsigned char tmpval = destination;"); + cfw("destination = source; source = tmpval;"); + $modifysrc=1; + } + + # POP + if ($insttype[$i] == 39) { + cfw("destination = stack_pop8();"); + } + + # SETB + if ($insttype[$i] == 40) { + cfw("destination = 1;"); + } + + # DA + if ($insttype[$i] == 41) { + cfw("if (((destination & 0x0F) > 9) || psw_read_ac()) {"); + cfw(" if ( ( destination + 6 ) > 0xFF) psw_set_cy();"); + cfw(" destination += 6;"); + cfw("}"); + cfw("if ( psw_read_cy() || ( ( destination & 0xF0 ) > 0x90 ) ) {"); + cfw(" if ( ( destination + 0x60 ) > 0xFF ) psw_set_cy();"); + cfw(" destination += 0x60;"); + cfw("}"); + } + + # DJNZ + if ($insttype[$i] == 42) { + cfw("destination--;"); + cfw("if ( destination != 0 ) cpu8051.pc = source;"); + } + + # XCHD + if ($insttype[$i] == 43) { + cfw("unsigned char tmpval = ( destination & 0x0F );"); + cfw("destination = ( destination & 0xF0 ) + ( source & 0x0F );"); + cfw("source = ( source & 0xF0 ) + tmpval;"); + $modifysrc=1; + } + + # MOVX + if ($insttype[$i] == 44) { + cfw("destination = source;"); + } + + + +############################################################################## + + + if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); + } + if ($op_destination == 1) { # addr16 + cfw("cpu8051.pc = addr16;"); + } + if ($op_destination == 2) { # A + cfw("mem_write_direct( _ACC_, destination );"); + } + if ($op_destination == 3) { # direct + cfw("mem_write_direct( destaddr, destination );"); + } + if ($op_destination == 4) { # @R0 + cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R0_ ), destination );"); + } + if ($op_destination == 5) { # @R1 + cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R1_ ), destination );"); + } + if ($op_destination == 6) { # R0 + cfw("mem_write_direct( BANKPSW + _R0_, destination );"); + } + if ($op_destination == 7) { # R1 + cfw("mem_write_direct( BANKPSW + _R1_, destination );"); + } + if ($op_destination == 8) { # R2 + cfw("mem_write_direct( BANKPSW + _R2_, destination );"); + } + if ($op_destination == 9) { # R3 + cfw("mem_write_direct( BANKPSW + _R3_, destination );"); + } + if ($op_destination == 10) { # R4 + cfw("mem_write_direct( BANKPSW + _R4_, destination );"); + } + if ($op_destination == 11) { # R5 + cfw("mem_write_direct( BANKPSW + _R5_, destination );"); + } + if ($op_destination == 12) { # R6 + cfw("mem_write_direct( BANKPSW + _R6_, destination );"); + } + if ($op_destination == 13) { # R7 + cfw("mem_write_direct( BANKPSW + _R7_, destination );"); + } + + if ($op_destination == 14) { # bitaddr + cfw("mem_write_bit( dstbitaddr, destination );"); + } + if ($op_destination == 17) { # C + cfw("psw_write_cy(destination);"); + } + if ($op_destination == 21) { # DPTR + cfw("mem_sfr_write_dptr(destination);"); + } + if ($op_destination == 23) { # /bitaddr + cfw("mem_write_bit( dstbitaddr, destination );"); + } + if ($op_destination == 24) { # @DPTR + cfw("mem_write_indirect(mem_sfr_read_dptr(), destination);"); + } + } + + if ($modifysrc == 1) { + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); + } + if ($op_source == 1) { # addr16 + cfw("cpu8051.pc = addr16;"); + } + if ($op_source == 2) { # A + cfw("mem_write_direct( _ACC_, source );"); + } + if ($op_source == 3) { # direct + cfw("mem_write_direct( srcaddr, source );"); + } + if ($op_source == 4) { # @R0 + cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R0_ ), source );"); + } + if ($op_source == 5) { # @R1 + cfw("mem_write_indirect( mem_read_direct( BANKPSW + _R1_ ), source );"); + } + if ($op_source == 6) { # R0 + cfw("mem_write_direct( BANKPSW + _R0_, source );"); + } + if ($op_source == 7) { # R1 + cfw("mem_write_direct( BANKPSW + _R1_, source );"); + } + if ($op_source == 8) { # R2 + cfw("mem_write_direct( BANKPSW + _R2_, source );"); + } + if ($op_source == 9) { # R3 + cfw("mem_write_direct( BANKPSW + _R3_, source );"); + } + if ($op_source == 10) { # R4 + cfw("mem_write_direct( BANKPSW + _R4_, source );"); + } + if ($op_source == 11) { # R5 + cfw("mem_write_direct( BANKPSW + _R5_, source );"); + } + if ($op_source == 12) { # R6 + cfw("mem_write_direct( BANKPSW + _R6_, source );"); + } + if ($op_source == 13) { # R7 + cfw("mem_write_direct( BANKPSW + _R7_, source );"); + } + if ($op_source == 14) { # bitaddr + cfw("mem_write_bit( srcbitaddr, source );"); + } + if ($op_source == 17) { # C + cfw("psw_write_cy(source);"); + } + if ($op_source == 21) { # DPTR + cfw("mem_sfr_write_dptr(source);"); + } + if ($op_source == 23) { # /bitaddr + cfw("mem_write_bit( srcbitaddr, source );"); + } + if ($op_source == 24) { # @DPTR + cfw("mem_write_indirect(mem_sfr_read_dptr(), source);"); + } + } + } + } + cfw("return $a_cycles[$i];"); + print INST_IMP "}\n"; + print INST_IMP "\n"; +} +# ------------------------------------------------------------------------------ + + +# Header for instructions_8051.h +print INST_DEF "/*\n"; +print INST_DEF " * instructions_8051.h\n"; +write_header(INST_DEF); +print INST_DEF "#ifndef INSTRUCTIONS_8051_H\n"; +print INST_DEF "#define INSTRUCTIONS_8051_H 1\n\n\n"; +print INST_DEF "#define BANKPSW (mem_read_direct(_PSW_) & 0x18)\n\n"; +print INST_DEF "typedef int (*OPCODE_FP)(void);\n\n\n"; +for( $i=0; $i<256; $i++ ) { + print INST_DEF "int\n"; + print INST_DEF "cpu8051_OP_$a_opcodehex[$i](void);\n\n"; +} +print INST_DEF "\n"; +print INST_DEF "/* Exported variables. */\n"; +print INST_DEF "#ifdef INSTRUCTIONS_8051_M\n"; +print INST_DEF "OPCODE_FP opcode_table[256] = {\n"; + +for ($i = 0; $i < 256; $i++) { + $ifunc = substr($instfunction[$i], 9); + + print INST_DEF "\tcpu8051_$ifunc,\n"; +} +print INST_DEF "};\n"; +print INST_DEF "#else\n"; +print INST_DEF "OPCODE_FP opcode_table[256];\n"; +print INST_DEF "#endif\n\n\n"; + +print INST_DEF "#endif /* INSTRUCTIONS_8051_H */\n"; + +print OPCODES_DEF "#endif /* OPCODES_IMP */\n"; + +close OPCODES_DEF; +close OPCODES_IMP; +close OPCODELST; +close INST_DEF; +close INST_IMP; diff --git a/src/gtk/pgmwin.c b/src/gtk/pgmwin.c index 6cec8fb..4c35d7f 100644 --- a/src/gtk/pgmwin.c +++ b/src/gtk/pgmwin.c @@ -16,6 +16,7 @@ #include "common.h" #include "memory.h" #include "cpu8051.h" +#include "opcodes.h" #include "pgmwin.h" #include "hexfile.h" @@ -262,7 +263,7 @@ pgmwin_refresh(void) gtk_list_store_set(store, &iter, COL_ADDR, str, -1); opcode = mem_read8(PGM_MEM_ID, address); - inst_size = cpu8051_get_instruction_size(opcode); + inst_size = opcodes_get_instr_size(opcode); /* Display instruction hex bytes. */ for (k = 0, col_id = COL_B0; k < 3; k++, col_id++) {