<commit_before>/*
 * Copyright (c) 2017 <NAME>
 * Distributed under the MIT software license, see the accompanying
 * file COPYING or http://www.opensource.org/licenses/mit-license.php.
 */
/* p-system Run-time Support Package.
 * This provides OS functions to handle procedure calls on segment 1.
 * These are also called "standard procedures" in some texts.
 */
#include "psys_rsp.h"

#include "psys_constants.h"
#include "psys_debug.h"
#include "psys_helpers.h"
#include "psys_state.h"
#include "psys_task.h"
#include "util/memutil.h"
#include "util/util_minmax.h"
#include "util/util_save_state.h"

#include <string.h>
#include <time.h>
#include <unistd.h>

/* Header for savestates */
#define PSYS_RSP_STATE_ID 0x50525350

/** Internal helper for setting IORESULT register. */
static void psys_set_io_result(struct psys_state *state, psys_word result)
{
    psys_stw(state, state->syscom + PSYS_SYSCOM_IORSLT, result);
}

/** RELOCSEG relocates the segment pointed to by the ERec.
 *
 * In this implementation, no relocation is performed at all because native code is not supported.
 */
static void psys_rsp_relocseg(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_word erec = psys_pop(state);
    if (PDBG(state, RSP)) {
        psys_debug("relocseg 0x%04x (stub)\n", erec);
    }
    /* Nothing to do here - no native code support */
}

/** moveseg(sib,srcpool,srcoffset)
 *
 * MOVESEG moves the segment at offset TOS in the pool described by TOS-1 to
 * the location specified in the SIB pointed to by TOS-2, and relocates it.
 * Only segment-relative relocation is performed.
 *
 * In this implementation, no relocation is performed at all because native code is not supported.
 */
static void psys_rsp_moveseg(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_word srcoffset       = psys_pop(state);
    psys_word srcpool         = psys_pop(state);
    psys_word sib             = psys_pop(state);
    psys_fulladdr srcpoolbase = psys_pool_get_base(state, srcpool);
    psys_word dstpool         = psys_ldw(state, sib + PSYS_SIB_Seg_Pool);
    psys_word dstoffset       = psys_ldw(state, sib + PSYS_SIB_Seg_Base);
    psys_word len             = psys_ldw(state, sib + PSYS_SIB_Seg_Leng);
    psys_fulladdr dstpoolbase = psys_pool_get_base(state, dstpool);
    if (PDBG(state, RSP)) {
        psys_debug("moveseg %04x %04x(%05x):%04x <- %04x(%05x):%04x (0x%04x words)\n",
            sib,
            dstpool, dstpoolbase, dstoffset,
            srcpool, srcpoolbase, srcoffset,
            len);
    }
    if (dstoffset == 0) {
        psys_panic("moveseg destination segment not resident\n");
    }
    memmove(psys_bytes(state, dstpoolbase) + dstoffset,
        psys_bytes(state, srcpoolbase) + srcoffset,
        len * 2);
}

/** moveleft(source,dest:array; length:integer)
 *
 * Move bytes one at a time starting from the left (low order byte).
 */
static void psys_rsp_moveleft(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_sword length     = psys_spop(state);
    psys_word dest_ofs    = psys_pop(state);
    psys_word dest_base   = psys_pop(state);
    psys_word source_ofs  = psys_pop(state);
    psys_word source_base = psys_pop(state);
    psys_byte *dest, *source;
    int x;
    if (PDBG(state, RSP)) {
        psys_debug("moveleft((0x%04x,0x%04x)=0x%04x,(0x%04x,0x%04x)=0x%04x,0x%04x)\n",
            source_base, source_ofs, source_base + source_ofs,
            dest_base, dest_ofs, dest_base + dest_ofs,
            length);
    }
    source = psys_bytes(state, source_base + source_ofs);
    dest   = psys_bytes(state, dest_base + dest_ofs);
    for (x = 0; x < length; ++x) {
        dest[x] = source[x];
    }
}

/** moveright(source,dest:array; length:integer)
 *
 * Move bytes one at a time starting from the right (high order byte).
 */
static void psys_rsp_moveright(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_sword length     = psys_spop(state);
    psys_word dest_ofs    = psys_pop(state);
    psys_word dest_base   = psys_pop(state);
    psys_word source_ofs  = psys_pop(state);
    psys_word source_base = psys_pop(state);
    psys_byte *dest, *source;
    int x;
    if (PDBG(state, RSP)) {
        psys_debug("moveleft((0x%04x,0x%04x),(0x%04x,0x%04x),0x%04x)\n",
            source_base, source_ofs, dest_base, dest_ofs, length);
    }
    source = psys_bytes(state, source_base + source_ofs);
    dest   = psys_bytes(state, dest_base + dest_ofs);
    for (x = length - 1; x >= 0; --x) {
        dest[x] = source[x];
    }
}

/** Merged i/o function - internal logic for both unit_read and unit_write */
static psys_word unitrw(struct psys_state *state, struct psys_rsp_state *rsp, bool wr, psys_word unit, psys_fulladdr buf_addr, psys_word len, psys_word block, psys_word ctrl)
{
    psys_byte *buf = psys_bytes(state, buf_addr);
    switch (unit) {
    case PSYS_UNIT_SYSTEM:
        /* Reading or writing to SYS stops the machine */
        psys_panic("Halted\n");
        break;
    case PSYS_UNIT_CONSOLE: {
        if (wr) {
            int ret = write(STDOUT_FILENO, buf, len);
            (void)ret;
        } else {
            int ret = read(STDIN_FILENO, buf, len);
            (void)ret;
        }
    } break;
    case PSYS_UNIT_DISK0: {
        unsigned x, srcblk;
        if (ctrl & 2) { /* physical addressing starts a second earlier */
            len    = 512;
            srcblk = block;
        } else {
            srcblk = block + rsp->disk0_track;
        }
        if (!rsp->disk0)
            psys_panic("disk0 not mounted\n");
        for (x = 0; x < len; x += PSYS_BLOCK_SIZE, srcblk += 1) { /* copy per block, wrapping as necessary */<commit_msg>psys: handle SYSTERM in the same way as CONSOLE in psys_rsp<commit_after>/*
 * Copyright (c) 2017 <NAME>
 * Distributed under the MIT software license, see the accompanying
 * file COPYING or http://www.opensource.org/licenses/mit-license.php.
 */
/* p-system Run-time Support Package.
 * This provides OS functions to handle procedure calls on segment 1.
 * These are also called "standard procedures" in some texts.
 */
#include "psys_rsp.h"

#include "psys_constants.h"
#include "psys_debug.h"
#include "psys_helpers.h"
#include "psys_state.h"
#include "psys_task.h"
#include "util/memutil.h"
#include "util/util_minmax.h"
#include "util/util_save_state.h"

#include <string.h>
#include <time.h>
#include <unistd.h>

/* Header for savestates */
#define PSYS_RSP_STATE_ID 0x50525350

/** Internal helper for setting IORESULT register. */
static void psys_set_io_result(struct psys_state *state, psys_word result)
{
    psys_stw(state, state->syscom + PSYS_SYSCOM_IORSLT, result);
}

/** RELOCSEG relocates the segment pointed to by the ERec.
 *
 * In this implementation, no relocation is performed at all because native code is not supported.
 */
static void psys_rsp_relocseg(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_word erec = psys_pop(state);
    if (PDBG(state, RSP)) {
        psys_debug("relocseg 0x%04x (stub)\n", erec);
    }
    /* Nothing to do here - no native code support */
}

/** moveseg(sib,srcpool,srcoffset)
 *
 * MOVESEG moves the segment at offset TOS in the pool described by TOS-1 to
 * the location specified in the SIB pointed to by TOS-2, and relocates it.
 * Only segment-relative relocation is performed.
 *
 * In this implementation, no relocation is performed at all because native code is not supported.
 */
static void psys_rsp_moveseg(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_word srcoffset       = psys_pop(state);
    psys_word srcpool         = psys_pop(state);
    psys_word sib             = psys_pop(state);
    psys_fulladdr srcpoolbase = psys_pool_get_base(state, srcpool);
    psys_word dstpool         = psys_ldw(state, sib + PSYS_SIB_Seg_Pool);
    psys_word dstoffset       = psys_ldw(state, sib + PSYS_SIB_Seg_Base);
    psys_word len             = psys_ldw(state, sib + PSYS_SIB_Seg_Leng);
    psys_fulladdr dstpoolbase = psys_pool_get_base(state, dstpool);
    if (PDBG(state, RSP)) {
        psys_debug("moveseg %04x %04x(%05x):%04x <- %04x(%05x):%04x (0x%04x words)\n",
            sib,
            dstpool, dstpoolbase, dstoffset,
            srcpool, srcpoolbase, srcoffset,
            len);
    }
    if (dstoffset == 0) {
        psys_panic("moveseg destination segment not resident\n");
    }
    memmove(psys_bytes(state, dstpoolbase) + dstoffset,
        psys_bytes(state, srcpoolbase) + srcoffset,
        len * 2);
}

/** moveleft(source,dest:array; length:integer)
 *
 * Move bytes one at a time starting from the left (low order byte).
 */
static void psys_rsp_moveleft(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_sword length     = psys_spop(state);
    psys_word dest_ofs    = psys_pop(state);
    psys_word dest_base   = psys_pop(state);
    psys_word source_ofs  = psys_pop(state);
    psys_word source_base = psys_pop(state);
    psys_byte *dest, *source;
    int x;
    if (PDBG(state, RSP)) {
        psys_debug("moveleft((0x%04x,0x%04x)=0x%04x,(0x%04x,0x%04x)=0x%04x,0x%04x)\n",
            source_base, source_ofs, source_base + source_ofs,
            dest_base, dest_ofs, dest_base + dest_ofs,
            length);
    }
    source = psys_bytes(state, source_base + source_ofs);
    dest   = psys_bytes(state, dest_base + dest_ofs);
    for (x = 0; x < length; ++x) {
        dest[x] = source[x];
    }
}

/** moveright(source,dest:array; length:integer)
 *
 * Move bytes one at a time starting from the right (high order byte).
 */
static void psys_rsp_moveright(struct psys_state *state, struct psys_rsp_state *rsp, psys_fulladdr segment, psys_fulladdr env_data)
{
    psys_sword length     = psys_spop(state);
    psys_word dest_ofs    = psys_pop(state);
    psys_word dest_base   = psys_pop(state);
    psys_word source_ofs  = psys_pop(state);
    psys_word source_base = psys_pop(state);
    psys_byte *dest, *source;
    int x;
    if (PDBG(state, RSP)) {
        psys_debug("moveleft((0x%04x,0x%04x),(0x%04x,0x%04x),0x%04x)\n",
            source_base, source_ofs, dest_base, dest_ofs, length);
    }
    source = psys_bytes(state, source_base + source_ofs);
    dest   = psys_bytes(state, dest_base + dest_ofs);
    for (x = length - 1; x >= 0; --x) {
        dest[x] = source[x];
    }
}

/** Merged i/o function - internal logic for both unit_read and unit_write */
static psys_word unitrw(struct psys_state *state, struct psys_rsp_state *rsp, bool wr, psys_word unit, psys_fulladdr buf_addr, psys_word len, psys_word block, psys_word ctrl)
{
    psys_byte *buf = psys_bytes(state, buf_addr);
    switch (unit) {
    case PSYS_UNIT_SYSTEM:
        /* Reading or writing to SYS stops the machine */
        psys_panic("Halted\n");
        break;
    case PSYS_UNIT_CONSOLE:
    case PSYS_UNIT_SYSTERM: {
        if (wr) {
            int ret = write(STDOUT_FILENO, buf, len);
            (void)ret;
        } else {
            int ret = read(STDIN_FILENO, buf, len);
            (void)ret;
        }
    } break;
    case PSYS_UNIT_DISK0: {
        unsigned x, srcblk;
        if (ctrl & 2) { /* physical addressing starts a second earlier */
            len    = 512;
            srcblk = block;
        } else {
            srcblk = block + rsp->disk0_track;
        }
        if (!rsp->disk0)
            psys_panic("disk0 not mounted\n");
        for (x = 0; x < len; x += PSYS_BLOCK_SIZE, srcblk += 1) { /* copy per block, wrapping as necessary */
{'fraction_non_alphanumeric': 0.10979529690407715, 'fraction_numerical': 0.014718321772965658, 'mean_word_length': 3.146965976850228, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5406464', 'n_tokens_mistral': 4298, 'n_tokens_neox': 4226, 'n_words': 1062}