📄 asm.c
字号:
static char _[] = " @(#)asm.c 5.23 93/10/26 10:17:03, Srini, AMD";/****************************************************************************** * Copyright 1991 Advanced Micro Devices, Inc. * * This software is the property of Advanced Micro Devices, Inc (AMD) which * specifically grants the user the right to modify, use and distribute this * software provided this notice is not removed or altered. All other rights * are reserved by AMD. * * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS * SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR * USE OF THIS SOFTWARE. * * So that all may benefit from your experience, please report any problems * or suggestions about this software to the 29K Technical Support Center at * 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or * 0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. * * Advanced Micro Devices, Inc. * 29K Support Products * Mail Stop 573 * 5900 E. Ben White Blvd. * Austin, TX 78741 * 800-292-9263 ***************************************************************************** * Engineer: Srini Subramanian. ***************************************************************************** * This module supports the assemble command to assemble 29K instructions * in memory. ***************************************************************************** */#include <stdio.h>#include "opcodes.h"#include "memspcs.h"#include "main.h"#include "monitor.h"#include "macros.h"#include "miniint.h"#include "error.h"#ifdef MSDOS#include <string.h>#define strcasecmp stricmp#else#include <string.h>#endif/*** There are approximately 23 different instruction formats for the** Am29000. Instructions are assembled using one of these formats.**** Note: Opcodes in the "switch" statement are sorted in numerical** order.***/int get_addr_29k_m PARAMS((char *, struct addr_29k_t *, INT32));int addr_29k_ok PARAMS((struct addr_29k_t *));void convert32 PARAMS((BYTE *));int set_data PARAMS((BYTE *, BYTE *, int));int asm_instr PARAMS((struct instr_t *, char **, int));int asm_arith_logic PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_load_store PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_vector PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_no_parms PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_one_parms PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_float PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_call_jmp PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_calli_jmpi PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_class PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_clz PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_const PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_consth PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_convert PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_div0 PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_exhws PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_jmp PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_jmpi PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_mfsr PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_mtsr PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_mtsrim PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_mftlb PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_mttlb PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_sqrt PARAMS((struct instr_t *, struct addr_29k_t *, int));int asm_emulate PARAMS((struct instr_t *, struct addr_29k_t *, int));extern void Mini_poll_kbd PARAMS((char *cmd_buffer, int size, int mode));extern int Mini_cmdfile_input PARAMS((char *cmd_buffer, int size));extern int tokenize_cmd PARAMS((char *, char **));extern void lcase_tokens PARAMS((char **, int));extern INT32 do_assemble PARAMS(( struct addr_29k_t addr_29k, char *token[], int token_count));#ifndef XRAYextern char cmd_buffer[];#define MAX_ASM_TOKENS 15static char *asm_token[MAX_ASM_TOKENS];static int asm_token_count;/*** This function is used to assemble an instruction. The command** takes as parameters an array of strings (*token[]) and a** count (token_count) which gives the number of tokens in the** array. These tokens should have the following values:**** token[0] - 'a' (the assemble command)** token[1] - <address> (the address to assemble instruction at)** token[2] - <opcode> (the 29K opcode nmemonic)** token[3] to token[n] - parameters to the assembly instruction.***/INT32asm_cmd(token, token_count) char *token[]; int token_count; { INT32 result; struct addr_29k_t addr_29k; int asm_done; /* ** Parse parameters */ if ((token_count < 2) || (token_count > 9)) { return (EMSYNTAX); } else if (token_count == 2) { /* Get address of assembly */ result = get_addr_29k_m(token[1], &addr_29k, I_MEM); if (result != 0) return (result); result = addr_29k_ok(&addr_29k); if (result != 0) return (result); asm_done = 0; fprintf(stderr, "0x%08lx:\t", addr_29k.address); do { if (io_config.cmd_file_io == TRUE) { if (Mini_cmdfile_input(cmd_buffer, BUFFER_SIZE) == SUCCESS) { fprintf(stderr, "%s", cmd_buffer); } else { Mini_poll_kbd(cmd_buffer, BUFFER_SIZE, BLOCK); /* block */ } } else { Mini_poll_kbd(cmd_buffer, BUFFER_SIZE, BLOCK); /* block */ } if (io_config.log_file) /* make a log file */#ifdef MSDOS fprintf(io_config.log_file, "%s\n", cmd_buffer);#else fprintf(io_config.log_file, "%s", cmd_buffer);#endif if (io_config.echo_mode == (INT32) TRUE)#ifdef MSDOS fprintf(io_config.echo_file, "%s\n", cmd_buffer);#else fprintf(io_config.echo_file, "%s", cmd_buffer);#endif asm_token_count = tokenize_cmd(cmd_buffer, asm_token); lcase_tokens(asm_token, asm_token_count); if (strcmp(token[0], ".") == 0) asm_done = 1; else { result= do_assemble(addr_29k, &asm_token[0], asm_token_count); if (result != SUCCESS) warning (result); else addr_29k.address = addr_29k.address + 4; fprintf(stderr, "0x%08lx:\t", addr_29k.address); } } while (asm_done != 1); } else { /* Get address of assembly */ result = get_addr_29k_m(token[1], &addr_29k, I_MEM); if (result != 0) return (result); result = addr_29k_ok(&addr_29k); if (result != 0) return (result); return (do_assemble(addr_29k, &token[2], (token_count-2))); } return (SUCCESS);}INT32do_assemble(addr_29k, token, token_count)struct addr_29k_t addr_29k;char *token[];int token_count;{ INT32 result; struct instr_t instr; INT32 retval; BYTE *write_data; INT32 bytes_ret; INT32 hostendian; /* for UDI conformant */ /* Initialize instr */ instr.op = 0; instr.c = 0; instr.a = 0; instr.b = 0; /* Assemble instruction */ result = asm_instr(&instr, &(token[0]), token_count); if (result != 0) return (EMSYNTAX); /* Will the data overflow the message buffer? done in TIP */ write_data = (BYTE *) &instr; hostendian = FALSE; if ((retval = Mini_write_req (addr_29k.memory_space, addr_29k.address, 1, /* count */ (INT16) sizeof(INST32), /* size */ &bytes_ret, write_data, hostendian)) != SUCCESS) { return(FAILURE); }; return (SUCCESS);}#endif/*** This function is used to assemble a single Am29000 instruction.** The token[] array contains the lower-case tokens for a single** assembler instruction. The token_count contains the number of** tokens in the array. This number should be at least 1 (as in the** cases of instructions like IRET) and at most 5 (for instructions** like LOAD).*/#ifdef XRAY extern struct t_inst_table { char *inst_mnem; unsigned char oprn_fmt;} inst_table[];#endifintasm_instr(instr, token, token_count) struct instr_t *instr; char *token[]; int token_count; { int i; int result; struct addr_29k_t parm[10]; char temp_opcode[20]; char *temp_ptr; int opcode_found; static char *str_0x40="0x40"; static char *str_gr1="gr1"; /* Is token_count valid, and is the first token a string? */ if ((token_count < 1) || (token_count > 7) || (strcmp(token[0], "") == 0)) return (EMSYNTAX); /* Get opcode */ /* ** Note: Since the opcode_name[] string used in the disassembler ** uses padded strings, we cannot do a strcmp(). We canot do a ** strncmp() of the length of token[0] either, since "and" will ** match up (for instance) with "andn". So we copy the string, ** null terminate at the first pad character (space), and then ** compare. This is inefficient, but necessary. */ i=0; opcode_found = FALSE; while ((i<256) && (opcode_found != TRUE)) {#ifdef XRAY result = strcasecmp(token[0], inst_table[i].inst_mnem);#else temp_ptr = strcpy(temp_opcode, opcode_name[i]); if (strcmp(temp_ptr, "") != 0) temp_ptr = strtok(temp_opcode, " "); result = strcmp(token[0], temp_ptr);#endif if (result == 0) { opcode_found = TRUE; instr->op = (BYTE) i; } i = i + 1; } /* end while */ /* Check for a NOP */ if ((opcode_found == FALSE) && (strcasecmp(token[0], "nop") == 0)) { opcode_found = TRUE; instr->op = ASEQ0; /* Fake up tokens to give "aseq 0x40,gr1,gr1" */ token_count = 4; token[1] = str_0x40; token[2] = str_gr1; token[3] = str_gr1; } if (opcode_found == FALSE) return (EMSYNTAX); if ((strcasecmp(token[0], "iretinv") == 0) || (strcasecmp(token[0], "inv") == 0) ) { /* iretinv and inv instructions */ for (i=1; i<token_count; i=i+1) { result = get_addr_29k_m(token[i], &(parm[i-1]), GENERIC_SPACE); if (result != 0) return (result); } } else { /* Make the other tokens into addr_29k */ for (i=1; i<token_count; i=i+1) { result = get_addr_29k_m(token[i], &(parm[i-1]), I_MEM); if (result != 0) return (result); /* Check if register values are legal */ if (ISREG(parm[i-1].memory_space)) { result = addr_29k_ok(&(parm[i-1])); if (result != 0) return (EMBADREG); } /* Set bit 7 if a LOCAL_REG */ if (parm[i-1].memory_space == LOCAL_REG) parm[i-1].address = (parm[i-1].address | 0x80); } } switch (instr->op) { /* Opcodes 0x00 to 0x0F */ case ILLEGAL_00: result = EMSYNTAX; break; case CONSTN: result = asm_const(instr, parm, 2); break; case CONSTH: result = asm_consth(instr, parm, 2); break; case CONST: result = asm_const(instr, parm, 2); break; case MTSRIM: result = asm_mtsrim(instr, parm, 2); break; case CONSTHZ: result = asm_const(instr, parm, 2); break; case LOADL0: result = asm_load_store(instr, parm, 4); break; case LOADL1: result = asm_load_store(instr, parm, 4); break; case CLZ0: result = asm_clz(instr, parm, 2); break; case CLZ1: result = asm_clz(instr, parm, 2); break; case EXBYTE0: result = asm_arith_logic(instr, parm, 3); break; case EXBYTE1: result = asm_arith_logic(instr, parm, 3); break; case INBYTE0: result = asm_arith_logic(instr, parm, 3); break; case INBYTE1: result = asm_arith_logic(instr, parm, 3); break; case STOREL0: result = asm_load_store(instr, parm, 4); break; case STOREL1: result = asm_load_store(instr, parm, 4); break; /* Opcodes 0x10 to 0x1F */ case ADDS0: result = asm_arith_logic(instr, parm, 3); break; case ADDS1: result = asm_arith_logic(instr, parm, 3); break; case ADDU0: result = asm_arith_logic(instr, parm, 3); break; case ADDU1: result = asm_arith_logic(instr, parm, 3); break; case ADD0: result = asm_arith_logic(instr, parm, 3); break; case ADD1: result = asm_arith_logic(instr, parm, 3); break; case LOAD0: result = asm_load_store(instr, parm, 4); break; case LOAD1: result = asm_load_store(instr, parm, 4); break; case ADDCS0: result = asm_arith_logic(instr, parm, 3); break; case ADDCS1: result = asm_arith_logic(instr, parm, 3); break; case ADDCU0: result = asm_arith_logic(instr, parm, 3); break; case ADDCU1: result = asm_arith_logic(instr, parm, 3); break; case ADDC0: result = asm_arith_logic(instr, parm, 3); break; case ADDC1: result = asm_arith_logic(instr, parm, 3); break; case STORE0: result = asm_load_store(instr, parm, 4); break; case STORE1: result = asm_load_store(instr, parm, 4); break; /* Opcodes 0x20 to 0x2F */ case SUBS0: result = asm_arith_logic(instr, parm, 3); break; case SUBS1: result = asm_arith_logic(instr, parm, 3); break; case SUBU0: result = asm_arith_logic(instr, parm, 3); break; case SUBU1: result = asm_arith_logic(instr, parm, 3); break; case SUB0: result = asm_arith_logic(instr, parm, 3); break; case SUB1: result = asm_arith_logic(instr, parm, 3); break; case LOADSET0: result = asm_load_store(instr, parm, 4); break; case LOADSET1: result = asm_load_store(instr, parm, 4); break; case SUBCS0: result = asm_arith_logic(instr, parm, 3); break; case SUBCS1: result = asm_arith_logic(instr, parm, 3); break; case SUBCU0: result = asm_arith_logic(instr, parm, 3); break; case SUBCU1: result = asm_arith_logic(instr, parm, 3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -